DEV Community

Java Efetivo (livro)
Java Efetivo (livro)

Posted on

Item 90: Pense em usar proxies de serialização em vez de instâncias serializadas

Atenção: Com as evoluções do Java e práticas modernas, existem alternativas mais seguras e eficientes para lidar com serialização/desserialização. Mas como estamos estudando o livro vamos considerar para aprender. VER NO TÓPICO FINAL SOBRE SERIALIZAÇÃO

Resumo do Item 90: Use Proxies de Serialização em vez de Instâncias Serializadas

Problemas da Serialização Direta
Riscos de segurança e bugs:

  • Permite criar objetos sem passar por construtores normais.
  • Violação de invariantes: Desserialização pode gerar instâncias inválidas.
  • Ataques maliciosos: Streams de bytes manipuladas podem explorar vulnerabilidades.

O que é o Padrão de Proxy de Serialização?
Objetivo: Substituir a serialização nativa por uma abordagem segura e controlada.

Funcionamento:

  • Cria uma classe proxy aninhada (serializável) que encapsula o estado da classe principal.
  • Garante que apenas o proxy é serializado/desserializado, não a classe original.

Implementação do Proxy de Serialização

Criar a classe proxy:

  • Classe estática privada, serializável, com campos idênticos à classe principal.
  • Construtor recebe a instância original e copia seus dados.
private static class SerializationProxy implements Serializable {
    private final Date start;
    private final Date end;

    SerializationProxy(Period p) {
        this.start = p.start;
        this.end = p.end;
    }
}
Enter fullscreen mode Exit fullscreen mode

Método writeReplace na classe principal:
Substitui a instância original pelo proxy durante a serialização.

private Object writeReplace() {
    return new SerializationProxy(this);
}
Enter fullscreen mode Exit fullscreen mode

Bloquear desserialização direta:
Adicionar readObject que lança exceção para evitar bypass do proxy.

private void readObject(ObjectInputStream ois) throws InvalidObjectException {
    throw new InvalidObjectException("Use o proxy!");
}
Enter fullscreen mode Exit fullscreen mode

Método readResolve no proxy:
Converte o proxy de volta em uma instância válida da classe principal.

private Object readResolve() {
    return new Period(start, end); // Usa o construtor público
}
Enter fullscreen mode Exit fullscreen mode

Vantagens do Padrão

Segurança reforçada:

  • Elimina riscos de streams maliciosas e exposição de campos privados.
  • Preserva imutabilidade: Campos final são mantidos sem restrições.

Flexibilidade:

  • Permite alterar a implementação interna da classe sem quebrar compatibilidade (ex.: EnumSet).
  • Simplicidade: Mais fácil de validar do que cópias defensivas.

Limitações

  • Classes extensíveis: Não funciona bem se a classe pode ser herdada por usuários (viola encapsulamento).
  • Grafos circulares: Pode causar ClassCastException em objetos com referências cíclicas.
  • Desempenho: ~14% mais lento que serialização padrão (trade-off aceitável para segurança).

Conclusão

  • Use proxies de serialização sempre que:
  • A classe tem invariantes complexas.
  • A segurança é crítica (ex.: dados sensíveis).
  • Quer evitar códigos de validação/cópia defensiva manuais.
  • Priorize este padrão sobre readObject/writeObject customizados para garantir robustez e imutabilidade real.

Chave: O proxy assegura que a desserialização sempre passa pelo construtor público, validando invariantes e bloqueando ataques!


Exemplos do Livro:

Image description

Image description

Image description

Image description

Image description

Heroku

Build apps, not infrastructure.

Dealing with servers, hardware, and infrastructure can take up your valuable time. Discover the benefits of Heroku, the PaaS of choice for developers since 2007.

Visit Site

Top comments (0)

A Workflow Copilot. Tailored to You.

Pieces.app image

Our desktop app, with its intelligent copilot, streamlines coding by generating snippets, extracting code from screenshots, and accelerating problem-solving.

Read the docs