search

Home  >  Q&A  >  body text

java - Why can't the Class defined in Serializable be serialized?

Fields in a Serializable class must themselves be either Serializable or transient even if the class is never explicitly serialized or deserialized. That's because under load, most J2EE application frameworks flush objects to disk, and an allegedly Serializable object with non-transient, non-serializable data members could cause program crashes, and open the door to attackers.

This rule raises an issue on non-Serializable fields, and on collection fields when they are not private (because they could be assigned non-Serializable values externally), and when they are assigned non-Serializable types within the class.

Noncompliant Code Example

public class Address {
  //...
}

public class Person implements Serializable {
  private static final long serialVersionUID = 1905122041950251207L;

  private String name;
  private Address address;  // Noncompliant; Address isn't serializable
}
欧阳克欧阳克2728 days ago1282

reply all(2)I'll reply

  • 扔个三星炸死你

    扔个三星炸死你2017-06-30 09:58:37

    When an object is serialized, according to Java's default serialization rules, all members in the object must be serialized. That is to say, these Classes must implement Serializable.

    So, you have two ways to modify it. One is to implement the Serializable interface in Address, and the other is to add the transient mark to the address member in Person so that the member will not be serialized.

    reply
    0
  • typecho

    typecho2017-06-30 09:58:37

    If the address member needs to be serialized, the Address class also needs to implement the Serializable interface.
    If the address member does not need to be serialized, you can add the transient keyword, then the address member will not be serialized and the value will be null. As follows:

    public class Person implements Serializable {
      private static final long serialVersionUID = 1905122041950251207L;
    
      private String name;
      private transient Address address;  // Noncompliant; Address isn't serializable
    }

    Of course there are other ways:
    For example, implementing the Externalizable interface and overriding the readExternal(ObjectInput in) and writeExternal(ObjectOutput out) methods.
    There is also an alternative implementation of the Externalizableinterface method, or implement the Serializableinterface, adding writeObject(ObjectOutputStream obs) and readObject(ObjectInputStream ois) methods.


    Tell me again why Address must implement Serializable, or add the transient keyword Person in order to be serialized?
    Let’s first take a look at the exception thrown by using ObjectOutputStream to persist the object without processing

    Exception in thread "main" java.io.NotSerializableException

    Look at ObjectOutputStreamSource code:

    /**
         * Underlying writeObject/writeUnshared implementation.
         */
        private void writeObject0(Object obj, boolean unshared)
            throws IOException
        {
                //......
                // remaining cases
                if (obj instanceof String) {
                    writeString((String) obj, unshared);
                } else if (cl.isArray()) {
                    writeArray(obj, desc, unshared);
                } else if (obj instanceof Enum) {
                    writeEnum((Enum<?>) obj, desc, unshared);
                } else if (obj instanceof Serializable) {
                    writeOrdinaryObject(obj, desc, unshared);
                } else {
                    if (extendedDebugInfo) {
                        throw new NotSerializableException(
                            cl.getName() + "\n" + debugInfoStack.toString());
                    } else {
                        throw new NotSerializableException(cl.getName());
                    }
                }
            } finally {
                depth--;
                bout.setBlockDataMode(oldMode);
            }
        }

    It can be seen from this that if the object type being written is String, Array, Enum, or Serializable, it can be serialized, otherwise NotSerializableException will be thrown. And when serializing an object, not only the current object itself will be serialized, but other objects referenced by the object will also be serialized.

    reply
    0
  • Cancelreply