ObjectStreamClass可以是有用的类,用于分析JVM中加载的序列化类的序列化特征。 这篇文章介绍了此类提供的有关已加载序列化类的一些信息。
ObjectStreamClass
提供了两个用于查找类的静态方法: lookup(class)和lookupAny(Class) 。 第一个lookup(Class)
仅在提供的类可序列化时返回ObjectStreamClass
的实例,如果提供的类不可序列化则返回null。 第二个方法lookupAny(Class)
返回所提供类的ObjectStreamClass
实例,而不管其是否可序列化。
一旦通过静态“ lookup”方法提供了ObjectStreamClass
实例,就可以查询该实例的类名 , 序列号UID和可序列化的字段 。
为了演示ObjectStreamClass
用法,我首先列出了两个简单类的代码清单,它们将是演示的一部分。 一类Person
是可序列化的 ,但具有一个过渡字段。 另一个类UnserializablePerson
几乎相同,但不可序列化。
人.java
package dustin.examples.serialization;import java.io.Serializable;/*** Person class intended for demonstration of ObjectStreamClass.* * @author Dustin*/
public class Person implements Serializable
{private final String lastName;private final String firstName;transient private final String fullName;public Person(final String newLastName, final String newFirstName){this.lastName = newLastName;this.firstName = newFirstName;this.fullName = this.firstName + " " + this.lastName;}public String getFirstName(){return this.firstName;}public String getLastName(){return this.lastName;}public String getFullName(){return this.fullName;}@Overridepublic String toString(){return this.fullName;}
}
UnserializablePerson.java
package dustin.examples.serialization;/*** Person class intended for demonstration of ObjectStreamClass.* * @author Dustin*/
public class UnserializablePerson
{private final String lastName;private final String firstName;private final String fullName;public UnserializablePerson(final String newLastName, final String newFirstName){this.lastName = newLastName;this.firstName = newFirstName;this.fullName = this.firstName + " " + this.lastName;}public String getFirstName(){return this.firstName;}public String getLastName(){return this.lastName;}public String getFullName(){return this.fullName;}@Overridepublic String toString(){return this.fullName;}
}
现在有了两个可以与ObjectStreamClass
结合使用的类,现在该看看一个简单的演示应用程序,该应用程序演示ObjectStreamClass
使用。
ObjectStreamClassDemo.java
package dustin.examples.serialization;import static java.lang.System.out;import java.io.ObjectStreamClass;
import java.io.ObjectStreamField;/*** Demonstrates use of ObjectStreamDemo.* * @author Dustin*/
public class ObjectStreamClassDemo
{/*** Displays class name, serial version UID, and serializable fields as* indicated by the provided instance of ObjectStreamClass.* * @param serializedClass */public static void displaySerializedClassInformation(final ObjectStreamClass serializedClass){final String serializedClassName = serializedClass.getName();out.println("Class Name: " + serializedClassName);final long serializedVersionUid = serializedClass.getSerialVersionUID();out.println("serialversionuid: " + serializedVersionUid);final ObjectStreamField[] fields = serializedClass.getFields();out.println("Serialized Fields:");for (final ObjectStreamField field : fields){out.println("\t" + field.getTypeString() + " " + field.getName());}}/*** Main function that demonstrates use of ObjectStreamDemo.* * @param arguments Command line arguments; none expected.*/public static void main(String[] arguments){// Example 1: ObjectStreamClass.lookup(Class) on a Serializable classout.println("\n=== ObjectStreamClass.lookup(Serializable) ===");final ObjectStreamClass serializedClass = ObjectStreamClass.lookup(Person.class);displaySerializedClassInformation(serializedClass);// Example 2: ObjectStreamClass.lookup(Class) on a class that is not// Serializable (which will result in a NullPointerException// when trying to access null returned from 'lookup'out.println("\n=== ObjectStreamClass.lookup(Unserializable) ===");try{final ObjectStreamClass unserializedClass =ObjectStreamClass.lookup(UnserializablePerson.class);displaySerializedClassInformation(unserializedClass);}catch (NullPointerException npe){out.println("NullPointerException: Unable to lookup unserializable class with ObjectStreamClass.lookup.");}// Example 3: ObjectStreamClass.lookupAny(Class) works without the// NullPointerException, but only provides name of the class as// Serial Version UID and serialized fields do not apply in the// case of a class that is not serializable.out.println("\n=== ObjectStreamClass.lookupAny(Unserializable) ===");final ObjectStreamClass unserializedClass =ObjectStreamClass.lookupAny(UnserializablePerson.class);displaySerializedClassInformation(unserializedClass);}
}
上面的源代码中的注释指示了正在演示的内容。 下一个屏幕快照中显示了运行此类的输出。
当上面显示的输出与之前的代码相关联时,我们可以进行一些与ObjectStreamClass
相关的观察。 这些包括以下事实:可序列化类的transient
字段未作为可序列化字段之一返回。 我们还看到,如果提供给它的类不可序列化,则ObjectStreamClass.lookup(Class)
方法将返回null。 ObjectStreamClass.lookupAny(Class)
对于无法序列化的类返回ObjectStreamClass
的实例,但是在这种情况下,只有该类的名称可用。
上面的代码显示了1940442894442614965的Person.java的串行版本UID。当在命令行上运行 serialver时 ,将生成并显示相同的串行版本UID。
以编程方式计算与Oracle JDK附带的serialver
工具所计算出的相同串行版本UID的功能的serialver
在于,可以显式地将相同的串行版本UID添加到生成的代码中 ,而无论如何将其隐式添加。 任何需要了解类的隐式Serial Version UID的JVM友好脚本或工具(例如,用Groovy编写的脚本)或工具,都可以使用ObjectStreamClass
来获取该Serial Version UID。
翻译自: https://www.javacodegeeks.com/2014/02/objectstreamclass-peeking-at-a-java-objects-serialization.html