How to serialize java object

Interface Serializable

Warning: Deserialization of untrusted data is inherently dangerous and should be avoided. Untrusted data should be carefully validated according to the «Serialization and Deserialization» section of the Secure Coding Guidelines for Java SE. Serialization Filtering describes best practices for defensive use of serial filters.

Classes that do not implement this interface will not have any of their state serialized or deserialized. All subtypes of a serializable class are themselves serializable. The serialization interface has no methods or fields and serves only to identify the semantics of being serializable.

It is possible for subtypes of non-serializable classes to be serialized and deserialized. During serialization, no data will be written for the fields of non-serializable superclasses. During deserialization, the fields of non-serializable superclasses will be initialized using the no-arg constructor of the first (bottommost) non-serializable superclass. This constructor must be accessible to the subclass that is being deserialized. It is an error to declare a class Serializable if this is not the case; the error will be detected at runtime. A serializable subtype may assume responsibility for saving and restoring the state of a non-serializable supertype’s public, protected, and (if accessible) package-access fields. See the Java Object Serialization Specification, section 3.1, for a detailed specification of the deserialization process, including handling of serializable and non-serializable classes.

When traversing a graph, an object may be encountered that does not support the Serializable interface. In this case the NotSerializableException will be thrown and will identify the class of the non-serializable object.

Читайте также:  Focus on window java

Classes that require special handling during the serialization and deserialization process must implement special methods with these exact signatures:

private void writeObject(java.io.ObjectOutputStream out) throws IOException private void readObject(java.io.ObjectInputStream in) throws IOException, ClassNotFoundException; private void readObjectNoData() throws ObjectStreamException;

The writeObject method is responsible for writing the state of the object for its particular class so that the corresponding readObject method can restore it. The default mechanism for saving the Object’s fields can be invoked by calling out.defaultWriteObject. The method does not need to concern itself with the state belonging to its superclasses or subclasses. State is saved by writing the individual fields to the ObjectOutputStream using the writeObject method or by using the methods for primitive data types supported by DataOutput.

The readObject method is responsible for reading from the stream and restoring the classes fields. It may call in.defaultReadObject to invoke the default mechanism for restoring the object’s non-static and non-transient fields. The defaultReadObject method uses information in the stream to assign the fields of the object saved in the stream with the correspondingly named fields in the current object. This handles the case when the class has evolved to add new fields. The method does not need to concern itself with the state belonging to its superclasses or subclasses. State is restored by reading data from the ObjectInputStream for the individual fields and making assignments to the appropriate fields of the object. Reading primitive data types is supported by DataInput.

The readObjectNoData method is responsible for initializing the state of the object for its particular class in the event that the serialization stream does not list the given class as a superclass of the object being deserialized. This may occur in cases where the receiving party uses a different version of the deserialized instance’s class than the sending party, and the receiver’s version extends classes that are not extended by the sender’s version. This may also occur if the serialization stream has been tampered; hence, readObjectNoData is useful for initializing deserialized objects properly despite a «hostile» or incomplete source stream.

Читайте также:  как вывести ip-адрес - BlogGood.ru

Serializable classes that need to designate an alternative object to be used when writing an object to the stream should implement this special method with the exact signature:

ANY-ACCESS-MODIFIER Object writeReplace() throws ObjectStreamException;

This writeReplace method is invoked by serialization if the method exists and it would be accessible from a method defined within the class of the object being serialized. Thus, the method can have private, protected and package-private access. Subclass access to this method follows java accessibility rules.

Classes that need to designate a replacement when an instance of it is read from the stream should implement this special method with the exact signature.

ANY-ACCESS-MODIFIER Object readResolve() throws ObjectStreamException;

This readResolve method follows the same invocation rules and accessibility rules as writeReplace.

Enum types are all serializable and receive treatment defined by the Java Object Serialization Specification during serialization and deserialization. Any declarations of the special handling methods discussed above are ignored for enum types.

Record classes can implement Serializable and receive treatment defined by the Java Object Serialization Specification, Section 1.13, «Serialization of Records». Any declarations of the special handling methods discussed above are ignored for record types.

The serialization runtime associates with each serializable class a version number, called a serialVersionUID, which is used during deserialization to verify that the sender and receiver of a serialized object have loaded classes for that object that are compatible with respect to serialization. If the receiver has loaded a class for the object that has a different serialVersionUID than that of the corresponding sender’s class, then deserialization will result in an InvalidClassException . A serializable class can declare its own serialVersionUID explicitly by declaring a field named «serialVersionUID» that must be static, final, and of type long :

ANY-ACCESS-MODIFIER static final long serialVersionUID = 42L;

If a serializable class does not explicitly declare a serialVersionUID, then the serialization runtime will calculate a default serialVersionUID value for that class based on various aspects of the class, as described in the Java Object Serialization Specification. This specification defines the serialVersionUID of an enum type to be 0L. However, it is strongly recommended that all serializable classes other than enum types explicitly declare serialVersionUID values, since the default serialVersionUID computation is highly sensitive to class details that may vary depending on compiler implementations, and can thus result in unexpected InvalidClassException s during deserialization. Therefore, to guarantee a consistent serialVersionUID value across different java compiler implementations, a serializable class must declare an explicit serialVersionUID value. It is also strongly advised that explicit serialVersionUID declarations use the private modifier where possible, since such declarations apply only to the immediately declaring class—serialVersionUID fields are not useful as inherited members. Array classes cannot declare an explicit serialVersionUID, so they always have the default computed value, but the requirement for matching serialVersionUID values is waived for array classes.

Report a bug or suggest an enhancement
For further API reference and developer documentation see the Java SE Documentation, which contains more detailed, developer-targeted descriptions with conceptual overviews, definitions of terms, workarounds, and working code examples. Other versions.
Java is a trademark or registered trademark of Oracle and/or its affiliates in the US and other countries.
Copyright © 1993, 2023, Oracle and/or its affiliates, 500 Oracle Parkway, Redwood Shores, CA 94065 USA.
All rights reserved. Use is subject to license terms and the documentation redistribution policy.

Источник

Serializable Objects

To serialize an object means to convert its state to a byte stream so that the byte stream can be reverted back into a copy of the object. A Java object is serializable if its class or any of its superclasses implements either the java.io.Serializable interface or its subinterface, java.io.Externalizable. Deserialization is the process of converting the serialized form of an object back into a copy of the object.

For example, the java.awt.Button class implements the Serializable interface, so you can serialize a java.awt.Button object and store that serialized state in a file. Later, you can read back the serialized state and deserialize into a java.awt.Button object.

The Java platform specifies a default way by which serializable objects are serialized. A (Java) class can override this default serialization and define its own way of serializing objects of that class. The Object Serialization Specification describes object serialization in detail.

When an object is serialized, information that identifies its class is recorded in the serialized stream. However, the class’s definition («class file») itself is not recorded. It is the responsibility of the system that is deserializing the object to determine how to locate and load the necessary class files. For example, a Java application might include in its classpath a JAR file that contains the class files of the serialized object(s) or load the class definitions by using information stored in the directory, as explained later in this lesson.

Binding a Serializable Object

You can store a serializable object in the directory if the underlying service provider supports that action, as does Oracle’s LDAP service provider.

The following example invokes Context.bind to bind an AWT button to the name "cn=Button". To associate attributes with the new binding, you use DirContext.bind . To overwrite an existing binding, use Context.rebind and DirContext.rebind .

// Create the object to be bound Button b = new Button("Push me"); // Perform the bind ctx.bind("cn=Button", b);

You can then read the object back using Context.lookup , as follows.

// Check that it is bound Button b2 = (Button)ctx.lookup("cn=Button"); System.out.println(b2);

Running this example produces the following output.

# java SerObj java.awt.Button[button0,0,0,0x0,invalid,label=Push me]

Specifying a Codebase

Note: The procedures described here are for binding a serializable object in a directory service that follows the schema defined in RFC 2713. These procedures might not be generally applicable to other naming and directory services that support binding a serializable object with a specified codebase.

When a serialized object is bound in the directory as shown in the previous example, applications that read the serialized object from the directory must have access to the class definitions necessary to deserialize the object.

Alternatively, you can record a codebase with the serialized object in the directory, either when you bind the object or subsequently by adding an attribute by using DirContext.modifyAttributes . You can use any attribute to record this codebase and have your application read that attribute from the directory and use it appropriately. Or you can use the "javaCodebase" attribute specified in . In the latter case, Oracle’s LDAP service provider will automatically use the attribute to load the class definitions as needed. "javaCodebase" should contain the URL of a codebase directory or a JAR file. If the codebase contains more than one URL, then each URL must be separated by a space character.

The following example resembles the one for binding a java.awt.Button. It differs in that it uses a user-defined Serializable class, Flower , and supplies a "javaCodebase" attribute that contains the location of Flower‘s class definition. Here’s the code that does the binding.

String codebase = . ; // Create the object to be bound Flower f = new Flower("rose", "pink"); // Perform the bind and specify the codebase ctx.bind("cn=Flower", f, new BasicAttributes("javaCodebase", codebase));

When you run this example , you must supply the URL of the location at which the class file Flower.class was installed. For example, if Flower.class was installed at the Web server web1, in the directory example/classes, then you would run this example as follows.

# java SerObjWithCodebase http://web1/example/classes/ pink rose

Afterward, you may remove Flower.class from your classpath and run any program that looks up or lists this object without directly referencing the Flower class. If your program references Flower directly, then you must make its class file available for compilation and execution.

Источник

Оцените статью