ObjectStreamClass может быть полезным классом для анализа характеристик сериализации сериализованного класса, загруженного в JVM. В этом посте рассматривается некоторая информация, которую этот класс предоставляет о загруженном сериализованном классе.
ObjectStreamClass предоставляет два статических метода для поиска класса: lookup (class) и lookupAny (Class) . Первый, lookup(Class) , будет возвращать экземпляр ObjectStreamClass тогда, когда предоставленный класс сериализуем и возвращает нуль, если предоставленный класс не сериализуем. Во-вторых, lookupAny(Class) возвращает экземпляр ObjectStreamClass для предоставленного класса независимо от того, является ли он сериализуемым или нет.
Как только экземпляр ObjectStreamClass предоставляется с помощью статических методов «поиска», этот экземпляр можно запросить для имени класса , для UID серийной версии и для сериализуемых полей .
Чтобы продемонстрировать использование ObjectStreamClass , я сначала перечислю листинги кода для двух простых классов, которые будут частью демонстрации. Один класс, Person , является Сериализуемым , но имеет временное поле. Другой класс, UnserializablePerson , почти идентичен, но он не Serializable.
Person.java
|
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
|
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; } @Override public String toString() { return this.fullName; }} |
UnserializablePerson.java
|
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
|
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; } @Override public String toString() { return this.fullName; }} |
Имея два класса для запуска использования вместе с ObjectStreamClass , пришло время взглянуть на простое демонстрационное приложение, которое демонстрирует использование ObjectStreamClass .
ObjectStreamClassDemo.java
|
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
|
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 class out.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 для классов, которые не сериализуются, но в этом случае доступно только имя класса.
Приведенный выше код показывает UID последовательной версии для Person.java 1940442894442614965. Когда serialver запускается в командной строке , генерируется и отображается тот же UID последовательной версии.
Приятно, что возможность программно рассчитывать тот же UID последовательной версии, который будет рассчитан с serialver инструмента serialver , поставляемого с Oracle JDK, заключается в том, что в сгенерированный код можно явно добавить тот же UID последовательной версии, который в любом случае будет добавлен неявно. Любой дружественный JVM сценарий или инструмент (например, написанный на Groovy), которому необходимо знать неявный UID ObjectStreamClass версии класса, может использовать ObjectStreamClass для получения этого UID ObjectStreamClass версии.

