DEV Community

Java Efetivo (livro)
Java Efetivo (livro)

Posted on

2 1 1

Serialização em Java na atualidade e novas abordagens em 2025

O padrão de proxy de serialização (recomendada pelo livro) ainda é uma solução válida e segura no Java, especialmente para classes com invariantes complexas ou que exigem imutabilidade real. No entanto, com as evoluções da linguagem e das práticas de desenvolvimento, há abordagens mais modernas e recomendadas para muitos cenários.

Abordagens mais modernas para segurança na serialização e desserialização

1- Evitar completamente a serialização nativa do Java (Serializable)

  • O próprio criador do Java (Joshua Bloch) recomenda evitar Serializable devido aos riscos de segurança e complexidade.
  • Em vez disso, é melhor utilizar formatos de serialização mais seguros, como JSON, XML ou Protobuf, que oferecem mais controle sobre o que está sendo serializado.

Alternativas:

  • Usar Jackson (com.fasterxml.jackson.databind) para JSON.
  • Utilizar Protocol Buffers (protobuf) / Apache Avro para uma serialização mais eficiente e segura.

Links:
https://www.linkedin.com/pulse/o-linkedin-substituiu-json-por-protobuf-e-conseguiu-uma-deschamps-s2jkf/

2- Uso de classes imutáveis e transient

  • Objetos imutáveis são naturalmente mais seguros para serialização.

Usar Classes Imutáveis Modernas
Substitua tipos mutáveis (ex.: Date, ArrayList) por classes imutáveis do java.time (LocalDate, Instant) ou coleções imutáveis (List.of(), Set.copyOf()).

Records (Java 16+):

public record Period(LocalDate start, LocalDate end) { 
    // Validação no construtor compacto
    public Period {
        if (end.isBefore(start)) throw new IllegalArgumentException();
    }
}
Enter fullscreen mode Exit fullscreen mode

Simplifica a criação de classes imutáveis e elimina a necessidade de cópias defensivas.

  • Marcar campos sensíveis como transient impede que sejam serializados.

Exemplo:

public final class SecureData implements Serializable {
    private static final long serialVersionUID = 1L;

    private final String publicData;
    private transient String sensitiveData; // Não será serializado

    public SecureData(String publicData, String sensitiveData) {
        this.publicData = publicData;
        this.sensitiveData = sensitiveData;
    }
}

Enter fullscreen mode Exit fullscreen mode

3- ObjectInputFilter (Desde Java 9)

  • Java 9 introduziu o ObjectInputFilter, que permite definir filtros de segurança para impedir ataques de desserialização de objetos inesperados ou perigosos.

Exemplo:

ObjectInputFilter filter = ObjectInputFilter.Config.createFilter(
    "com.meusistema.SeguraClass;!*"
);
ObjectInputStream ois = new ObjectInputStream(new FileInputStream("data.ser"));
ois.setObjectInputFilter(filter);

Enter fullscreen mode Exit fullscreen mode

Benefício: Permite controlar quais classes podem ser desserializadas.

4- Biblioteca Kryo (Mais segura e rápida)

  • Kryo é uma alternativa moderna e eficiente para serialização, sendo mais rápida e mais segura que a serialização padrão do Java.
Kryo kryo = new Kryo();
Output output = new Output(new FileOutputStream("data.bin"));
kryo.writeObject(output, myObject);
output.close();

Enter fullscreen mode Exit fullscreen mode

Leitura:
https://medium.com/@prekshaan95/kryo-serialization-and-deserialization-in-java-9e6da25e2a76

Benefício: Melhor desempenho e segurança, usado em frameworks como Akka.

5- Serialização Customizada com writeObject() e readObject()

private void readObject(ObjectInputStream ois) throws IOException, ClassNotFoundException {
    throw new InvalidObjectException("Desserialização não permitida!");
}

Enter fullscreen mode Exit fullscreen mode

Benefício: Bloqueia ataques de desserialização.

6- Serialização com Frameworks Seguros
Spring Boot / Micronaut / Quarkus:

  • Frameworks modernos evitam a serialização nativa do Java, preferindo JSON via REST APIs.
  • Usam DTOs (Data Transfer Objects) imutáveis para transferência segura de dados.

7- Padrão de Serialização Baseada em Construtores
Em vez de depender de proxies, use construtores ou factories para reconstruir objetos após a desserialização:

public class Period implements Serializable {
    private final LocalDate start;
    private final LocalDate end;

    // Construtor público com validação
    public Period(LocalDate start, LocalDate end) {
        if (end.isBefore(start)) throw new IllegalArgumentException();
        this.start = start;
        this.end = end;
    }

    private Object readObject(ObjectInputStream ois) throws IOException, ClassNotFoundException {
        ois.defaultReadObject();
        return new Period(start, end); // Reconstrução segura
    }
}
Enter fullscreen mode Exit fullscreen mode

Quando o Proxy de Serialização Ainda é Útil?

  • Cenários críticos: Sistemas financeiros, APIs de segurança, onde a validação rigorosa é essencial.
  • Legado: Projetos que não podem migrar para formatos modernos (ex.: sistemas embarcados, aplicações empresariais antigas).

Comparativo: Proxy vs. Alternativas Modernas

Image description

Conclusão: Qual abordagem usar?

Image description

Se a segurança for crítica, evite Serializable e use JSON ou Protobuf. Se ainda precisar usar Serializable, aplique ObjectInputFilter e classes imutáveis.

Heroku

Simplify your DevOps and maximize your time.

Since 2007, Heroku has been the go-to platform for developers as it monitors uptime, performance, and infrastructure concerns, allowing you to focus on writing code.

Learn More

Top comments (0)

Image of Docusign

🛠️ Bring your solution into Docusign. Reach over 1.6M customers.

Docusign is now extensible. Overcome challenges with disconnected products and inaccessible data by bringing your solutions into Docusign and publishing to 1.6M customers in the App Center.

Learn more