Java Serialization and Deserialization Explained

Java Serialization and Deserialization Explained

By - Srushti Kulkarni11/12/2025

In the world of Java programming, two concepts that often come up—yet sometimes confuse developers—are serialization and deserialization. Put simply, serialization is the process of converting a live object into a sequence of bytes; deserialization is the reverse, turning that byte stream back into an object. In a Java context, these operations are provided by the java.io package and play an important role in object persistence, communication, caching, and more. In this blog, we’ll explore what these terms mean, how they work in Java, when and why you might use them, and some important caveats and best-practices to keep in mind. Java Serialization and Deserialization Explained — learn how to convert objects to bytes and restore them for data storage and communication.

 

What is Serialization?

Serialization in Java refers to the conversion of an object’s internal state (its non-static, non-transient fields) into a format (typically a stream of bytes) that can be stored (for example in a file or database) or transferred (for example, over a network) so that it can later be reconstructed.In effect, you are taking the state of an object—its field values—and writing that out in such a way that you can later read it and reconstruct the object in the same or another Java process.

Why is this useful? Because when you have objects in memory, they only live as long as the JVM process is running and the object is referenced. But sometimes you want to save that object state for later (persistence) or send it to another machine or process (communication). Serialization enables that.

 

How does it work in Java?

In standard Java serialization:

  • • A class must implement the marker interface java.io.Serializable. GeeksforGeeks+1
     
  • • You typically use java.io.ObjectOutputStream to write the object: e.g. writeObject(obj).
     
  • • Fields marked transient are skipped in serialization (they are not written). Static fields are not part of object state and hence are not serialized. Baeldung on Kotlin
     
  • • The serialized stream contains metadata (class name, version info, field values, references) so that it can be used to reconstruct the object. HowToDoInJava
     
  • • The object graph is handled: if the object has references to other objects (that also implement Serializable), those objects are (recursively) serialized too. If any referenced object is not serializable, a NotSerializableException occurs. Scaler+1
     
  • • Because Java’s built-in serialization is designed to be “platform independent” (you can serialize on one machine and deserialize on another) it must include enough information to reconstruct the object in a compatible way

public class Person implements Serializable {

    private static final long serialVersionUID = 1L;

    private String name;

    private int age;

    private transient String password;

 

    // constructors, getters, setters …

}

 

// Serialization

Person p = new Person("Alice", 30, "secret123");

try (FileOutputStream fos = new FileOutputStream("person.dat");

     ObjectOutputStream oos = new ObjectOutputStream(fos)) {

    oos.writeObject(p);

}

 

In this example password will not be serialized because it is marked transient. The file person.dat now holds a byte stream representing the object.

 

What is Deserialization?

Deserialization is simply the reverse of serialization: reading a stream of bytes (that was created by serialization) and recreating the object with its state, as long as the class definition is available in the executing JVM. Oracle Docs+1
Using our Person example:

try (FileInputStream fis = new FileInputStream("person.dat");

     ObjectInputStream ois = new ObjectInputStream(fis)) {

    Person p2 = (Person) ois.readObject();

    System.out.println(p2.getName());  // prints "Alice"

}

 

Here the readObject() method reconstructs the object, casting it back into the proper class. The constructor of Person is not called during deserialization (internally Java creates the object and sets its fields via reflection).
It’s important that the class of the serialized object (and any referenced objects) is present on the current JVM’s classpath. Otherwise you’ll get a ClassNotFoundException. 

Explore Other Demanding Courses

No courses available for the selected domain.

Why Use Serialization / Deserialization?

Here are some of the key use-cases:

  • • Persistence: Saving an object’s state (for example user settings, application state) to a file or database, and later loading it back.
     
  • • Communication/Networking: Sending objects over the network between JVMs (for example in remote method invocation, distributed systems) by converting them to a transportable form.
     
  • • Caching / Deep Copying: One trick for creating a deep copy of an object is serializing it and then deserializing it into a fresh instance. Medium
     
  • • Session replication / checkpointing: In enterprise applications you may serialize session objects to disk or across cluster nodes.

     

Important Considerations

While serialization/deserialization seem simple in concept, there are some important caveats and best-practices you should keep in mind.

serialVersionUID

When a class implements Serializable, you should explicitly declare a private static final long serialVersionUID field. This ID acts as a version identifier ensuring that the serialized and deserialized class definitions are compatible. If you don’t declare this, Java will generate one at runtime based on class details which may change when you refactor the class; then deserialization may fail with an InvalidClassException. 

Security risks

Deserialization is known to be a frequent source of security vulnerabilities (so-called deserialization attacks) because malicious byte streams might lead to unwanted object creation, code execution or invalid state. 

 Therefore it is vital to not blindly deserialize data from untrusted sources, validate content, restrict what classes can be deserialized, consider safer alternatives (such as JSON with Jackson/Gson) in networked contexts. In fact some developers recommend avoiding Java’s built-in serialization altogether in favor of safer formats. 

Performance & versioning

  • Serialization can be relatively heavy (reflection, graph traversal) and may affect performance if used heavily for large object graphs.
     
  • If your classes evolve (fields added/removed) you may break compatibility for previously serialized data unless you design carefully (for example by providing default values, declaring serialVersionUID, handling readObject()/writeObject() methods).
     
  • Static fields are not serialized, so their values will always be from the runtime defaults or current class loading; similarly transient fields are skipped.

     

Alternatives

Depending on your use-case, you may use other serialization formats: JSON, XML, Protobuf, etc. They may offer better interoperability (between languages/systems), readability, versioning control, or security features. 

 

When to Use (and When to Avoid) Java’s Built-In Serialization

Use the built-in Java mechanism when:

  • • You need to preserve exact object graphs within a Java-to-Java context.
     
  • • You need to persist or transport objects with minimal extra work (i.e., the class is simple, stable, fully controlled by you).
     
  • • You are working in a trusted environment where security is not a big concern (for example internal caching).

     

Avoid or use alternatives when:

  • • You need cross-language interoperability (e.g., Java ↔ Python or Java ↔ JavaScript).
     
  • • You are handling untrusted data over a network or storage that could be tampered with.
     
  • • Performance or control (size of the stream, versioning, schema evolution) are critical.
     
  • • Your object graph is extremely large and you need optimized format (Protobuf, Avro).

     

 

Best-Practice Checklist

Here’s a quick checklist for designing serializable classes:

  1. 1. Make your class implement Serializable only if you intend serialization.
     
  2. 2. Declare private static final long serialVersionUID = ….
     
  3. 3. Mark non-serializable fields as transient.
     
  4. 4. Consider custom writeObject(ObjectOutputStream) / readObject(ObjectInputStream) methods if you need to control serialization (e.g., encryption, validation).
     
  5. 5. During deserialization, validate state (e.g., null checks, value ranges) rather than trusting the stream blindly.
     
  6. 6. Avoid serialization of sensitive data (passwords, private keys) unless you handle them securely.
     
  7. 7. Document compatibility strategy (what changes are allowed across versions) for serialized classes.
     
  8. 8. Consider switching to a safer, more portable format like JSON/Protobuf when appropriate.

     

Summary

In summary: serialization converts a Java object into a byte stream so that it can be persisted or transmitted; deserialization reconstructs the object from the byte stream. The built-in Java mechanism (via Serializable, ObjectOutputStream, ObjectInputStream) makes this fairly straightforward—but it demands care around versioning, security, and performance. When used appropriately, serialization helps you preserve object state, share objects between JVMs, or cache object data. When used improperly (especially in network/untrusted contexts), it can expose your system to risks. For many modern applications, you may prefer using alternative formats (JSON, Protobuf) that provide better control and interoperability.

 

Do visit our channel to learn More: SevenMentor

 

Author:-

Srushti Kulkarni

Get Free Consultation

Loading...

Call the Trainer and Book your free demo Class..... Call now!!!

| SevenMentor Pvt Ltd.

© Copyright 2025 | SevenMentor Pvt Ltd.

Share on FacebookShare on TwitterVisit InstagramShare on LinkedIn