Java processing and analysis of serialVersionUID serialization

Source: Internet
Author: User

After the java serialization process was analyzed last time, the processing of serialVersionUID is not very clear. Now let's look at the code and understand how to process serialVersionUID,
The following code is called when ObjectOutputStream. java calls writeObject:
 
This is to call the writeNonProxy method of ObjectStreamClass. java and write metadata information of non-proxy classes.
When writing class metadata, The serialVersionUID will be written:

[Java]
/**
* Writes non-proxy class descriptor information to given output stream.
*/
Void writeNonProxy (ObjectOutputStream out) throws IOException {
Out. writeUTF (name );
Out. writeLong (getSerialVersionUID ());
 
Byte flags = 0;
If (externalizable ){
Flags | = ObjectStreamConstants. SC _EXTERNALIZABLE;
Int protocol = out. getProtocolVersion ();
If (protocol! = ObjectStreamConstants. PROTOCOL_VERSION_1 ){
Flags | = ObjectStreamConstants. SC _BLOCK_DATA;
}
} Else if (serializable ){
Flags | = ObjectStreamConstants. SC _SERIALIZABLE;
}
If (hasWriteObjectData ){
Flags | = ObjectStreamConstants. SC _WRITE_METHOD;
}
If (isEnum ){
Flags | = ObjectStreamConstants. SC _ENUM;
}
Out. writeByte (flags );
 
Out. writeShort (fields. length );
For (int I = 0; I <fields. length; I ++ ){
ObjectStreamField f = fields [I];
Out. writeByte (f. getTypeCode ());
Out. writeUTF (f. getName ());
If (! F. isPrimitive ()){
Out. writeTypeString (f. getTypeString ());
}
}
}

The following sections are verified during reading:
Call the readNonProxy method of ObjectStreamClass. java in the readObject method of ObjectInputStream. java,
 
Here we will read suid = Long. valueOf (in. readLong (); that is, read serialVersionUID, and then verify if (isEnum & suid. longValue () first ()! = 0L) if it is an enumeration class, the serialVersionUID is 0.

[Java]
Void readNonProxy (ObjectInputStream in)
Throws IOException, ClassNotFoundException
{
Name = in. readUTF ();
Suid = Long. valueOf (in. readLong ());
IsProxy = false;
 
Byte flags = in. readByte ();
HasWriteObjectData =
(Flags & ObjectStreamConstants. SC _WRITE_METHOD )! = 0 );
HasBlockExternalData =
(Flags & ObjectStreamConstants. SC _BLOCK_DATA )! = 0 );
Externalizable =
(Flags & ObjectStreamConstants. SC _EXTERNALIZABLE )! = 0 );
Boolean sflag =
(Flags & ObjectStreamConstants. SC _SERIALIZABLE )! = 0 );
If (externalizable & sflag ){
Throw new InvalidClassException (
Name, "serializable and externalizable flags conflict ");
}
Serializable = externalizable | sflag;
IsEnum = (flags & ObjectStreamConstants. SC _ENUM )! = 0 );
If (isEnum & suid. longValue ()! = 0L ){
Throw new InvalidClassException (name,
"Enum descriptor has non-zero serialVersionUID:" + suid );
}

Int numFields = in. readShort ();
If (isEnum & numFields! = 0 ){
Throw new InvalidClassException (name,
"Enum descriptor has non-zero field count:" + numFields );
}
Fields = (numFields> 0 )?
New ObjectStreamField [numFields]: NO_FIELDS;
For (int I = 0; I <numFields; I ++ ){
Char tcode = (char) in. readByte ();
String fname = in. readUTF ();
String signature = (tcode = 'l') | (tcode = '['))?
In. readTypeString (): new String (new char [] {tcode });
Try {
Fields [I] = new ObjectStreamField (fname, signature, false );
} Catch (RuntimeException e ){
Throw (IOException) new InvalidClassException (name,
"Invalid descriptor for field" + fname). initCause (e );
}
}
ComputeFieldOffsets ();
}

Next, we will perform the next verification on the serialVersionUID: Also in the ObjectStreamClass. java initNonProxy method, suid = Long. valueOf (model. getSerialVersionUID (); remove the serialVersionUID and if (serializable = localDesc of the serialized model object. serializable &&! Cl. isArray () & suid. longValue ()! = LocalDesc. getSerialVersionUID () and then judge whether the local class object inherits the serializable interface, and cl is not an array, and the serialVersionUID must be consistent with the serialVersionUID of the currently serialized class Object.

[Java]
/**
* Initializes class descriptor representing a non-proxy class.
*/
Void initNonProxy (ObjectStreamClass model,
Class cl,
ClassNotFoundException resolveEx,
ObjectStreamClass superDesc)
Throws InvalidClassException
{
This. cl = cl;
This. resolveEx = resolveEx;
This. superDesc = superDesc;
Name = model. name;
Suid = Long. valueOf (model. getSerialVersionUID ());
IsProxy = false;
IsEnum = model. isEnum;
Serializable = model. serializable;
Externalizable = model. externalizable;
HasBlockExternalData = model. hasBlockExternalData;
HasWriteObjectData = model. hasWriteObjectData;
Fields = model. fields;
PrimDataSize = model. primDataSize;
NumObjFields = model. numObjFields;

If (cl! = Null ){
LocalDesc = lookup (cl, true );
If (localDesc. isProxy ){
Throw new InvalidClassException (
"Cannot bind non-proxy descriptor to a proxy class ");
}
If (isEnum! = LocalDesc. isEnum ){
Throw new InvalidClassException (isEnum?
"Cannot bind enum descriptor to a non-enum class ":
"Cannot bind non-enum descriptor to an enum class ");
}

If (serializable = localDesc. serializable &&
! Cl. isArray ()&&
Suid. longValue ()! = LocalDesc. getSerialVersionUID ())
{
Throw new InvalidClassException (localDesc. name,
"Local class incompatible:" +
"Stream classdesc serialVersionUID =" + suid +
", Local class serialVersionUID =" +
LocalDesc. getSerialVersionUID ());
}

If (! ClassNamesEqual (name, localDesc. name )){
Throw new InvalidClassException (localDesc. name,
"Local class name incompatible with stream class" +
"Name \" "+ name + "\"");
}

If (! IsEnum ){
If (serializable = localDesc. serializable )&&
(Externalizable! = LocalDesc. externalizable ))
{
Throw new InvalidClassException (localDesc. name,
"Serializable incompatible with Externalizable ");
}
 
If (serializable! = LocalDesc. serializable) |
(Externalizable! = LocalDesc. externalizable) |
! (Serializable | externalizable ))
{
DeserializeEx = new InvalidClassException (localDesc. name,
"Class invalid for deserialization ");
}
}

Cons = localDesc. cons;
WriteObjectMethod = localDesc. writeObjectMethod;
ReadObjectMethod = localDesc. readObjectMethod;
ReadObjectNoDataMethod = localDesc. readObjectNoDataMethod;
WriteReplaceMethod = localDesc. writeReplaceMethod;
ReadResolveMethod = localDesc. readResolveMethod;
If (deserializeEx = null ){
DeserializeEx = localDesc. deserializeEx;
}
}
FieldRefl = getReflector (fields, localDesc );
// Reassign to matched fields so as to reflect local unshared settings
Fields = fieldRefl. getFields ();
}
Author: zhongweijian

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.