Methods Summary |
---|
private static java.io.ObjectStreamClass | addToCache(java.lang.Class cl, boolean computeSUID)Adds an extra entry mapping a given class {@code cl} to its class
descriptor, which will be computed (an ObjectStreamClass). If
{@code computeSUID} is true, this method will compute the SUID for
this class.
ObjectStreamClass result = new ObjectStreamClass();
// Now we fill in the values
result.setName(cl.getName());
result.setClass(cl);
Class<?> superclass = cl.getSuperclass();
if (superclass != null) {
result.setSuperclass(lookup(superclass));
}
Field[] declaredFields = null;
if (computeSUID) {
// Lazy computation, to save speed & space
declaredFields = cl.getDeclaredFields();
result.setSerialVersionUID((cl.isEnum() || (cl == Enum.class)) ? 0
: computeSerialVersionUID(cl, declaredFields));
}
boolean serializable = isSerializable(cl);
// Serializables need field descriptors
if (serializable && !cl.isArray()) {
if (declaredFields == null) {
declaredFields = cl.getDeclaredFields();
}
result.buildFieldDescriptors(declaredFields);
} else {
// Externalizables or arrays do not need FieldDesc info
result.setFields(new ObjectStreamField[0]);
}
byte flags = 0;
boolean externalizable = isExternalizable(cl);
if (externalizable) {
flags |= ObjectStreamConstants.SC_EXTERNALIZABLE;
} else if (serializable) {
flags |= ObjectStreamConstants.SC_SERIALIZABLE;
}
if (getPrivateWriteObjectMethod(cl) != null) {
flags |= ObjectStreamConstants.SC_WRITE_METHOD;
}
result.setFlags(flags);
classesAndDescriptors.put(cl, result);
return result;
|
void | buildFieldDescriptors(java.lang.reflect.Field[] declaredFields)Builds the collection of field descriptors for the receiver
// We could find the field ourselves in the collection, but calling
// reflect is easier. Optimize if needed.
final Field f = ObjectStreamClass.fieldSerialPersistentFields(this
.forClass());
// If we could not find the emulated fields, we'll have to compute
// dumpable fields from reflect fields
boolean useReflectFields = f == null; // Assume we will compute the
// fields to dump based on the
// reflect fields
ObjectStreamField[] _fields = null;
if (!useReflectFields) {
// The user declared a collection of emulated fields. Use them.
// We have to be able to fetch its value, even if it is private
AccessController.doPrivileged(new PriviAction<Object>(f));
try {
// static field, pass null
_fields = (ObjectStreamField[]) f.get(null);
} catch (IllegalAccessException ex) {
// WARNING - what should we do if we have no access ? This
// should not happen.
throw new RuntimeException(ex);
}
} else {
// Compute collection of dumpable fields based on reflect fields
List<ObjectStreamField> serializableFields = new ArrayList<ObjectStreamField>(
declaredFields.length);
// Filter, we are only interested in fields that are serializable
for (int i = 0; i < declaredFields.length; i++) {
Field declaredField = declaredFields[i];
int modifiers = declaredField.getModifiers();
boolean shouldBeSerialized = !(Modifier.isStatic(modifiers) || Modifier
.isTransient(modifiers));
if (shouldBeSerialized) {
ObjectStreamField field = new ObjectStreamField(
declaredField.getName(), declaredField.getType());
serializableFields.add(field);
}
}
if (serializableFields.size() == 0) {
_fields = NO_FIELDS; // If no serializable fields, share the
// special value so that users can test
} else {
// Now convert from Vector to array
_fields = new ObjectStreamField[serializableFields.size()];
_fields = serializableFields.toArray(_fields);
}
}
ObjectStreamField.sortFields(_fields);
// assign offsets
int primOffset = 0, objectOffset = 0;
for (int i = 0; i < _fields.length; i++) {
Class<?> type = _fields[i].getType();
if (type.isPrimitive()) {
_fields[i].offset = primOffset;
primOffset += primitiveSize(type);
} else {
_fields[i].offset = objectOffset++;
}
}
fields = _fields;
|
private static long | computeSerialVersionUID(java.lang.Class cl, java.lang.reflect.Field[] fields)Compute and return the Serial Version UID of the class {@code cl}.
The value is computed based on the class name, superclass chain, field
names, method names, modifiers, etc.
/*
* First we should try to fetch the static slot 'static final long
* serialVersionUID'. If it is defined, return it. If not defined, we
* really need to compute SUID using SHAOutputStream
*/
for (int i = 0; i < fields.length; i++) {
final Field field = fields[i];
if (Long.TYPE == field.getType()) {
int modifiers = field.getModifiers();
if (Modifier.isStatic(modifiers) && Modifier.isFinal(modifiers)) {
if (UID_FIELD_NAME.equals(field.getName())) {
/*
* We need to be able to see it even if we have no
* visibility. That is why we set accessible first (new
* API in reflect 1.2)
*/
AccessController.doPrivileged(new PriviAction<Object>(
field));
try {
// Static field, parameter is ignored
return field.getLong(null);
} catch (IllegalAccessException iae) {
throw new RuntimeException(Msg.getString(
"K0071", iae)); //$NON-NLS-1$
}
}
}
}
}
MessageDigest digest;
try {
digest = MessageDigest.getInstance("SHA"); //$NON-NLS-1$
} catch (NoSuchAlgorithmException e) {
throw new Error(e);
}
ByteArrayOutputStream sha = new ByteArrayOutputStream();
try {
DataOutputStream output = new DataOutputStream(sha);
output.writeUTF(cl.getName());
int classModifiers = CLASS_MODIFIERS_MASK & cl.getModifiers();
/*
* Workaround for 1F9LOQO. Arrays are ABSTRACT in JDK, but that is
* not in the specification. Since we want to be compatible for
* X-loading, we have to pretend we have the same shape
*/
boolean isArray = cl.isArray();
if (isArray) {
classModifiers |= Modifier.ABSTRACT;
}
// Required for JDK UID compatibility
if (cl.isInterface() && !Modifier.isPublic(classModifiers)) {
classModifiers &= ~Modifier.ABSTRACT;
}
output.writeInt(classModifiers);
/*
* In JDK1.2 arrays implement Cloneable and Serializable but not in
* JDK 1.1.7. So, JDK 1.2 "pretends" arrays have no interfaces when
* computing SHA-1 to be compatible.
*/
if (!isArray) {
// Interface information
Class<?>[] interfaces = cl.getInterfaces();
if (interfaces.length > 1) {
// Only attempt to sort if really needed (saves object
// creation, etc)
Comparator<Class<?>> interfaceComparator = new Comparator<Class<?>>() {
public int compare(Class<?> itf1, Class<?> itf2) {
return itf1.getName().compareTo(itf2.getName());
}
};
Arrays.sort(interfaces, interfaceComparator);
}
// Dump them
for (int i = 0; i < interfaces.length; i++) {
output.writeUTF(interfaces[i].getName());
}
}
// Field information
if (fields.length > 1) {
// Only attempt to sort if really needed (saves object creation,
// etc)
Comparator<Field> fieldComparator = new Comparator<Field>() {
public int compare(Field field1, Field field2) {
return field1.getName().compareTo(field2.getName());
}
};
Arrays.sort(fields, fieldComparator);
}
// Dump them
for (int i = 0; i < fields.length; i++) {
Field field = fields[i];
int modifiers = field.getModifiers() & FIELD_MODIFIERS_MASK;
boolean skip = Modifier.isPrivate(modifiers)
&& (Modifier.isTransient(modifiers) || Modifier
.isStatic(modifiers));
if (!skip) {
// write name, modifier & "descriptor" of all but private
// static and private transient
output.writeUTF(field.getName());
output.writeInt(modifiers);
output
.writeUTF(descriptorForFieldSignature(getFieldSignature(field)));
}
}
/*
* Normally constructors come before methods (because <init> <
* anyMethodName). However, <clinit> is an exception. Besides,
* reflect will not let us get to it.
*/
if (hasClinit(cl)) {
// write name, modifier & "descriptor"
output.writeUTF(CLINIT_NAME);
output.writeInt(CLINIT_MODIFIERS);
output.writeUTF(CLINIT_SIGNATURE);
}
// Constructor information
Constructor<?>[] constructors = cl.getDeclaredConstructors();
if (constructors.length > 1) {
// Only attempt to sort if really needed (saves object creation,
// etc)
Comparator<Constructor<?>> constructorComparator = new Comparator<Constructor<?>>() {
public int compare(Constructor<?> ctr1, Constructor<?> ctr2) {
// All constructors have same name, so we sort based on
// signature
return (getConstructorSignature(ctr1)
.compareTo(getConstructorSignature(ctr2)));
}
};
Arrays.sort(constructors, constructorComparator);
}
// Dump them
for (int i = 0; i < constructors.length; i++) {
Constructor<?> constructor = constructors[i];
int modifiers = constructor.getModifiers()
& METHOD_MODIFIERS_MASK;
boolean isPrivate = Modifier.isPrivate(modifiers);
if (!isPrivate) {
/*
* write name, modifier & "descriptor" of all but private
* ones
*
* constructor.getName() returns the constructor name as
* typed, not the VM name
*/
output.writeUTF("<init>"); //$NON-NLS-1$
output.writeInt(modifiers);
output.writeUTF(descriptorForSignature(
getConstructorSignature(constructor)).replace('/",
'."));
}
}
// Method information
Method[] methods = cl.getDeclaredMethods();
if (methods.length > 1) {
Comparator<Method> methodComparator = new Comparator<Method>() {
public int compare(Method m1, Method m2) {
int result = m1.getName().compareTo(m2.getName());
if (result == 0) {
// same name, signature will tell which one comes
// first
return getMethodSignature(m1).compareTo(
getMethodSignature(m2));
}
return result;
}
};
Arrays.sort(methods, methodComparator);
}
// Dump them
for (int i = 0; i < methods.length; i++) {
Method method = methods[i];
int modifiers = method.getModifiers() & METHOD_MODIFIERS_MASK;
boolean isPrivate = Modifier.isPrivate(modifiers);
if (!isPrivate) {
// write name, modifier & "descriptor" of all but private
// ones
output.writeUTF(method.getName());
output.writeInt(modifiers);
output.writeUTF(descriptorForSignature(
getMethodSignature(method)).replace('/", '."));
}
}
} catch (IOException e) {
throw new RuntimeException(Msg.getString("K0072", e));//$NON-NLS-1$
}
// now compute the UID based on the SHA
byte[] hash = digest.digest(sha.toByteArray());
return littleEndianLongAt(hash, 0);
|
private void | copyFieldAttributes()If a Class uses "serialPersistentFields" to define the serialized fields,
this.loadFields cannot get the "unshared" information when deserializing
fields using current implementation of ObjectInputStream. This method
provides a way to copy the "unshared" attribute from this.fields.
if ((loadFields == null) || fields == null) {
return;
}
for (int i = 0; i < loadFields.length; i++) {
ObjectStreamField loadField = loadFields[i];
String name = loadField.getName();
for (int j = 0; j < fields.length; j++) {
ObjectStreamField field = fields[j];
if (name.equals(field.getName())) {
loadField.setUnshared(field.isUnshared());
loadField.setOffset(field.getOffset());
break;
}
}
}
|
private static java.lang.String | descriptorForFieldSignature(java.lang.String signature)Returns what the serializaton specification calls "descriptor" given a
field signature.
return signature.replace('.", '/");
|
private static java.lang.String | descriptorForSignature(java.lang.String signature)Return what the serializaton specification calls "descriptor" given a
method/constructor signature.
return signature.substring(signature.indexOf("(")); //$NON-NLS-1$
|
static java.lang.reflect.Field | fieldSerialPersistentFields(java.lang.Class cl)Return the java.lang.reflect.Field {@code serialPersistentFields}
if class {@code cl} implements it. Return null otherwise.
try {
Field f = cl.getDeclaredField("serialPersistentFields"); //$NON-NLS-1$
int modifiers = f.getModifiers();
if (Modifier.isStatic(modifiers) && Modifier.isPrivate(modifiers)
&& Modifier.isFinal(modifiers)) {
if (f.getType() == ARRAY_OF_FIELDS) {
return f;
}
}
} catch (NoSuchFieldException nsm) {
// Ignored
}
return null;
|
java.io.ObjectStreamField[] | fields()Returns the collection of field descriptors for the fields of the
corresponding class
if (fields == null) {
synchronized(this){
Class<?> forCl = forClass();
if (forCl != null && isSerializable(forCl) && !forCl.isArray()) {
buildFieldDescriptors(forCl.getDeclaredFields());
} else {
// Externalizables or arrays do not need FieldDesc info
setFields(new ObjectStreamField[0]);
}
}
}
return fields;
|
public java.lang.Class | forClass()Returns the class (java.lang.Class) for this descriptor.
if (resolvedClass != null) {
return resolvedClass.get();
}
return null;
|
static native java.lang.String | getConstructorSignature(java.lang.reflect.Constructor c)Return a String representing the signature for a Constructor {@code c}.
|
public java.io.ObjectStreamField | getField(java.lang.String name)Gets a field descriptor of the class represented by this class
descriptor.
ObjectStreamField[] allFields = getFields();
for (int i = 0; i < allFields.length; i++) {
ObjectStreamField f = allFields[i];
if (f.getName().equals(name)) {
return f;
}
}
return null;
|
private static native java.lang.String | getFieldSignature(java.lang.reflect.Field f)Return a String representing the signature for a field {@code f}.
|
public java.io.ObjectStreamField[] | getFields()Returns a collection of field descriptors for the serialized fields of
the class represented by this class descriptor.
copyFieldAttributes();
return loadFields == null ? fields().clone() : loadFields.clone();
|
byte | getFlags()Returns the flags for this descriptor, where possible combined values are
ObjectStreamConstants.SC_WRITE_METHOD
ObjectStreamConstants.SC_SERIALIZABLE
ObjectStreamConstants.SC_EXTERNALIZABLE
return flags;
|
java.io.ObjectStreamField[] | getLoadFields()Returns the collection of field descriptors for the input fields of the
corresponding class
return loadFields;
|
static native java.lang.String | getMethodSignature(java.lang.reflect.Method m)Return a String representing the signature for a method {@code m}.
|
public java.lang.String | getName()Returns the name of the class represented by this descriptor.
return className;
|
static java.lang.reflect.Method | getPrivateReadObjectMethod(java.lang.Class cl)Return true if the given class {@code cl} implements private
method {@code readObject()}.
try {
Method method = cl
.getDeclaredMethod("readObject", READ_PARAM_TYPES); //$NON-NLS-1$
if (Modifier.isPrivate(method.getModifiers())
&& method.getReturnType() == VOID_CLASS) {
return method;
}
} catch (NoSuchMethodException nsm) {
// Ignored
}
return null;
|
static java.lang.reflect.Method | getPrivateReadObjectNoDataMethod(java.lang.Class cl)Return true if the given class {@code cl} implements private
method {@code readObject()}.
try {
Method method = cl.getDeclaredMethod("readObjectNoData", //$NON-NLS-1$
EMPTY_CONSTRUCTOR_PARAM_TYPES);
if (Modifier.isPrivate(method.getModifiers())
&& method.getReturnType() == VOID_CLASS) {
return method;
}
} catch (NoSuchMethodException nsm) {
// Ignored
}
return null;
|
static java.lang.reflect.Method | getPrivateWriteObjectMethod(java.lang.Class cl)Return true if the given class {@code cl} implements private
method {@code writeObject()}.
try {
Method method = cl.getDeclaredMethod("writeObject", //$NON-NLS-1$
WRITE_PARAM_TYPES);
if (Modifier.isPrivate(method.getModifiers())
&& method.getReturnType() == VOID_CLASS) {
return method;
}
} catch (NoSuchMethodException nsm) {
// Ignored
}
return null;
|
public long | getSerialVersionUID()Returns the Serial Version User ID of the class represented by this
descriptor.
return svUID;
|
java.io.ObjectStreamClass | getSuperclass()Returns the descriptor (ObjectStreamClass) of the superclass of the class
represented by the receiver.
return superclass;
|
private static native boolean | hasClinit(java.lang.Class cl)Return true if the given class {@code cl} has the
compiler-generated method {@code clinit}. Even though it is
compiler-generated, it is used by the serialization code to compute SUID.
This is unfortunate, since it may depend on compiler optimizations in
some cases.
|
static boolean | isExternalizable(java.lang.Class cl)Return true if instances of class {@code cl} are Externalizable,
false otherwise.
return EXTERNALIZABLE.isAssignableFrom(cl);
|
static boolean | isPrimitiveType(char typecode)Return true if the type code
typecode describes a primitive type
return !(typecode == '[" || typecode == 'L");
|
static boolean | isSerializable(java.lang.Class cl)Return true if instances of class {@code cl} are Serializable,
false otherwise.
return SERIALIZABLE.isAssignableFrom(cl);
|
private static long | littleEndianLongAt(byte[] buffer, int position)Return a little endian long stored in a given position of the buffer
long result = 0;
for (int i = position + 7; i >= position; i--) {
result = (result << 8) + (buffer[i] & 0xff);
}
return result;
|
public static java.io.ObjectStreamClass | lookup(java.lang.Class cl)Returns the descriptor corresponding to the class {@code cl}. If the
class is not serializable or externalizable then {@code null} is
returned.
boolean serializable = isSerializable(cl);
boolean externalizable = isExternalizable(cl);
// Has to be either Serializable or Externalizable
if (!serializable && !externalizable) {
return null;
}
return lookupStreamClass(cl, true);
|
static java.io.ObjectStreamClass | lookupStreamClass(java.lang.Class cl)Return the descriptor (ObjectStreamClass) corresponding to the class
{@code cl}. Returns an ObjectStreamClass even if instances of the
class cannot be serialized
return lookupStreamClass(cl, isSerializable(cl) || isExternalizable(cl));
|
private static synchronized java.io.ObjectStreamClass | lookupStreamClass(java.lang.Class cl, boolean computeSUID)Return the descriptor (ObjectStreamClass) corresponding to the class
{@code cl}. Returns an ObjectStreamClass even if instances of the
class cannot be serialized
// Synchronized because of the lookup table 'classesAndDescriptors'
ObjectStreamClass cachedValue = classesAndDescriptors.get(cl);
if (cachedValue != null) {
return cachedValue;
}
return addToCache(cl, computeSUID);
|
static java.lang.reflect.Method | methodReadResolve(java.lang.Class cl)Return the java.lang.reflect.Method {@code readResolve} if class
{@code cl} implements it. Return null otherwise.
Class<?> search = cl;
while (search != null) {
try {
Method method = search.getDeclaredMethod(
"readResolve", (Class[]) null); //$NON-NLS-1$
if (search == cl
|| (method.getModifiers() & Modifier.PRIVATE) == 0) {
return method;
}
return null;
} catch (NoSuchMethodException nsm) {
}
search = search.getSuperclass();
}
return null;
|
static java.lang.reflect.Method | methodWriteReplace(java.lang.Class cl)Return the java.lang.reflect.Method {@code writeReplace} if class
{@code cl} implements it. Return null otherwise.
Class<?> search = cl;
while (search != null) {
try {
Method method = search.getDeclaredMethod(
"writeReplace", (Class[]) null); //$NON-NLS-1$
if (search == cl
|| (method.getModifiers() & Modifier.PRIVATE) == 0) {
return method;
}
return null;
} catch (NoSuchMethodException nsm) {
// Ignored
}
search = search.getSuperclass();
}
return null;
|
private static native void | oneTimeInitialization()
|
private int | primitiveSize(java.lang.Class type)
if (type == Byte.TYPE || type == Boolean.TYPE) {
return 1;
}
if (type == Short.TYPE || type == Character.TYPE) {
return 2;
}
if (type == Integer.TYPE || type == Float.TYPE) {
return 4;
}
if (type == Long.TYPE || type == Double.TYPE) {
return 8;
}
return 0;
|
void | setClass(java.lang.Class c)Set the class (java.lang.Class) that the receiver represents
resolvedClass = new WeakReference<Class<?>>(c);
|
void | setFields(java.io.ObjectStreamField[] f)Set the collection of field descriptors for the fields of the
corresponding class
fields = f;
|
void | setFlags(byte b)Set the flags for this descriptor, where possible combined values are
ObjectStreamConstants.SC_WRITE_METHOD
ObjectStreamConstants.SC_SERIALIZABLE
ObjectStreamConstants.SC_EXTERNALIZABLE
flags = b;
|
void | setLoadFields(java.io.ObjectStreamField[] f)Set the collection of field descriptors for the input fields of the
corresponding class
loadFields = f;
|
void | setName(java.lang.String newName)Set the name of the class represented by the receiver
className = newName;
|
void | setSerialVersionUID(long l)Set the Serial Version User ID of the class represented by the receiver
svUID = l;
|
void | setSuperclass(java.io.ObjectStreamClass c)Set the descriptor for the superclass of the class described by the
receiver
superclass = c;
|
public java.lang.String | toString()Returns a string containing a concise, human-readable description of this
descriptor.
return getName() + ": static final long serialVersionUID =" //$NON-NLS-1$
+ getSerialVersionUID() + "L;"; //$NON-NLS-1$
|