Methods Summary |
---|
public int | available()Returns the number of bytes of primitive data that can be read from this
stream without blocking. This method should not be used at any arbitrary
position; just when reading primitive data types (int, char etc).
// returns 0 if next data is an object, or N if reading primitive types
checkReadPrimitiveTypes();
return primitiveData.available();
|
private void | checkReadPrimitiveTypes()Checks to if it is ok to read primitive types from this stream at
this point. One is not supposed to read primitive types when about to
read an object, for example, so an exception has to be thrown.
// If we still have primitive data, it is ok to read primitive data
if (primitiveData == input || primitiveData.available() > 0) {
return;
}
// If we got here either we had no Stream previously created or
// we no longer have data in that one, so get more bytes
do {
int next = 0;
if (hasPushbackTC) {
hasPushbackTC = false;
} else {
next = input.read();
pushbackTC = (byte) next;
}
switch (pushbackTC) {
case TC_BLOCKDATA:
primitiveData = new ByteArrayInputStream(readBlockData());
return;
case TC_BLOCKDATALONG:
primitiveData = new ByteArrayInputStream(
readBlockDataLong());
return;
case TC_RESET:
resetState();
break;
default:
if (next != -1) {
pushbackTC();
}
return;
}
// Only TC_RESET falls through
} while (true);
|
private static void | checkedSetSuperClassDesc(java.io.ObjectStreamClass desc, java.io.ObjectStreamClass superDesc)
if (desc.equals(superDesc)) {
throw new StreamCorruptedException();
}
desc.setSuperclass(superDesc);
|
public void | close()Closes this stream. This implementation closes the source stream.
input.close();
|
public void | defaultReadObject()Default method to read objects from this stream. Serializable fields
defined in the object's class and superclasses are read from the source
stream.
// We can't be called from just anywhere. There are rules.
if (currentObject != null || !mustResolve) {
readFieldValues(currentObject, currentClass);
} else {
throw new NotActiveException();
}
|
private void | discardData()Reads and discards block data and objects until TC_ENDBLOCKDATA is found.
primitiveData = emptyStream;
boolean resolve = mustResolve;
mustResolve = false;
do {
byte tc = nextTC();
if (tc == TC_ENDBLOCKDATA) {
mustResolve = resolve;
return; // End of annotation
}
readContent(tc);
} while (true);
|
protected boolean | enableResolveObject(boolean enable)Enables object replacement for this stream. By default this is not
enabled. Only trusted subclasses (loaded with system class loader) are
allowed to change this status.
if (enable) {
// The Stream has to be trusted for this feature to be enabled.
// trusted means the stream's classloader has to be null
SecurityManager currentManager = System.getSecurityManager();
if (currentManager != null) {
currentManager.checkPermission(SUBSTITUTION_PERMISSION);
}
}
boolean originalValue = enableResolve;
enableResolve = enable;
return originalValue;
|
private int | findStreamSuperclass(java.lang.Class cl, java.util.ArrayList classList, int lastIndex)
ObjectStreamClass objCl;
String forName;
for (int i = lastIndex; i < classList.size(); i++) {
objCl = classList.get(i);
forName = objCl.forClass().getName();
if (objCl.getName().equals(forName)) {
if (cl.getName().equals(objCl.getName())) {
return i;
}
} else {
// there was a class replacement
if (cl.getName().equals(forName)) {
return i;
}
}
}
return -1;
|
private static java.lang.String | getBaseName(java.lang.String fullName)
int k = fullName.lastIndexOf("."); //$NON-NLS-1$
if (k == -1 || k == (fullName.length() - 1)) {
return fullName;
}
return fullName.substring(k + 1);
|
private static java.lang.ClassLoader | getClosestUserClassLoader()Searches up the call stack to find the closest user-defined class loader.
Class<?>[] stackClasses = VMStack.getClasses(-1, false);
for (Class<?> stackClass : stackClasses) {
ClassLoader loader = stackClass.getClassLoader();
if (loader != null && loader != bootstrapLoader
&& loader != systemLoader) {
return loader;
}
}
return null;
|
private boolean | inSamePackage(java.lang.Class c1, java.lang.Class c2)Checks if two classes belong to the same package.
String nameC1 = c1.getName();
String nameC2 = c2.getName();
int indexDotC1 = nameC1.lastIndexOf('.");
int indexDotC2 = nameC2.lastIndexOf('.");
// BEGIN android-changed
// copied from newer version of harmony
if (indexDotC1 != indexDotC2) {
return false; // cannot be in the same package if indices are not
}
// END android-changed
// the same
if (indexDotC1 < 0) {
return true; // both of them are in default package
}
return nameC1.substring(0, indexDotC1).equals(
nameC2.substring(0, indexDotC2));
|
private static native java.lang.Object | newInstance(java.lang.Class instantiationClass, java.lang.Class constructorClass)Create and return a new instance of class {@code instantiationClass}
but running the constructor defined in class
{@code constructorClass} (same as {@code instantiationClass}
or a superclass).
Has to be native to avoid visibility rules and to be able to have
{@code instantiationClass} not the same as
{@code constructorClass} (no such API in java.lang.reflect).
|
private int | nextHandle()Return the next {@code int} handle to be used to indicate cyclic
references being loaded from the stream.
return this.currentHandle++;
|
private byte | nextTC()Return the next token code (TC) from the receiver, which indicates what
kind of object follows
if (hasPushbackTC) {
hasPushbackTC = false; // We are consuming it
} else {
// Just in case a later call decides to really push it back,
// we don't require the caller to pass it as parameter
pushbackTC = input.readByte();
}
return pushbackTC;
|
private static native void | objSetField(java.lang.Object instance, java.lang.Class declaringClass, java.lang.String fieldName, java.lang.String fieldTypeName, java.lang.Object value)Set a given declared field named {@code fieldName} of
{@code instance} to the new value {@code value}.
This method could be implemented non-natively on top of java.lang.reflect
implementations that support the {@code setAccessible} API, at the
expense of extra object creation (java.lang.reflect.Field). Otherwise
Serialization could not set private fields, except by the use of a native
method like this one.
|
private void | pushbackTC()Pushes back the last TC code read
hasPushbackTC = true;
|
public int | read()Reads a single byte from the source stream and returns it as an integer
in the range from 0 to 255. Returns -1 if the end of the source stream
has been reached. Blocks if no input is available.
checkReadPrimitiveTypes();
return primitiveData.read();
|
public int | read(byte[] buffer, int offset, int length)Reads at most {@code length} bytes from the source stream and stores them
in byte array {@code buffer} starting at offset {@code count}. Blocks
until {@code count} bytes have been read, the end of the source stream is
detected or an exception is thrown.
// BEGIN android-changed
if (buffer == null) {
throw new NullPointerException(Msg.getString("K0047")); //$NON-NLS-1$
}
// avoid int overflow
// Exception priorities (in case of multiple errors) differ from
// RI, but are spec-compliant.
// removed redundant check, used (offset | length) < 0 instead of
// (offset < 0) || (length < 0) to safe one operation
if ((offset | length) < 0 || length > buffer.length - offset) {
throw new ArrayIndexOutOfBoundsException(Msg.getString("K002f")); //$NON-NLS-1$
}
// END android-changed
if (length == 0) {
return 0;
}
checkReadPrimitiveTypes();
return primitiveData.read(buffer, offset, length);
|
private byte[] | readBlockData()Reads and returns an array of raw bytes with primitive data. The array
will have up to 255 bytes. The primitive data will be in the format
described by {@code DataOutputStream}.
byte[] result = new byte[input.readByte() & 0xff];
input.readFully(result);
return result;
|
private byte[] | readBlockDataLong()Reads and returns an array of raw bytes with primitive data. The array
will have more than 255 bytes. The primitive data will be in the format
described by {@code DataOutputStream}.
byte[] result = new byte[input.readInt()];
input.readFully(result);
return result;
|
public boolean | readBoolean()Reads a boolean from the source stream.
return primitiveTypes.readBoolean();
|
public byte | readByte()Reads a byte (8 bit) from the source stream.
return primitiveTypes.readByte();
|
public char | readChar()Reads a character (16 bit) from the source stream.
return primitiveTypes.readChar();
|
private java.io.ObjectStreamClass | readClassDesc()Reads a class descriptor (an {@code ObjectStreamClass}) from the
stream.
byte tc = nextTC();
switch (tc) {
case TC_CLASSDESC:
return readNewClassDesc(false);
case TC_PROXYCLASSDESC:
Class<?> proxyClass = readNewProxyClassDesc();
ObjectStreamClass streamClass = ObjectStreamClass
.lookup(proxyClass);
streamClass.setLoadFields(new ObjectStreamField[0]);
registerObjectRead(streamClass, Integer.valueOf(nextHandle()),
false);
checkedSetSuperClassDesc(streamClass, readClassDesc());
return streamClass;
case TC_REFERENCE:
return (ObjectStreamClass) readCyclicReference();
case TC_NULL:
return null;
default:
throw new StreamCorruptedException(Msg.getString(
"K00d2", Integer.toHexString(tc & 0xff))); //$NON-NLS-1$
}
|
protected java.io.ObjectStreamClass | readClassDescriptor()Reads a class descriptor from the source stream.
ObjectStreamClass newClassDesc = new ObjectStreamClass();
String name = input.readUTF();
if ("".equals(name)) {
throw new IOException("The stream is corrupted.");
}
newClassDesc.setName(name);
newClassDesc.setSerialVersionUID(input.readLong());
newClassDesc.setFlags(input.readByte());
// We must register the class descriptor before reading field
// descriptors.
// if called outside of readObject, the descriptorHandle might be null
descriptorHandle = (null == descriptorHandle ? Integer
.valueOf(nextHandle()) : descriptorHandle);
registerObjectRead(newClassDesc, descriptorHandle, false);
descriptorHandle = null;
readFieldDescriptors(newClassDesc);
return newClassDesc;
|
private java.lang.Object | readContent(byte tc)Reads the content of the receiver based on the previously read token
{@code tc}.
switch (tc) {
case TC_BLOCKDATA:
return readBlockData();
case TC_BLOCKDATALONG:
return readBlockDataLong();
case TC_CLASS:
return readNewClass(false);
case TC_CLASSDESC:
return readNewClassDesc(false);
case TC_ARRAY:
return readNewArray(false);
case TC_OBJECT:
return readNewObject(false);
case TC_STRING:
return readNewString(false);
case TC_LONGSTRING:
return readNewLongString(false);
case TC_REFERENCE:
return readCyclicReference();
case TC_NULL:
return null;
case TC_EXCEPTION:
Exception exc = readException();
throw new WriteAbortedException(Msg.getString("K00d3"), exc); //$NON-NLS-1$
case TC_RESET:
resetState();
return null;
default:
throw new StreamCorruptedException(Msg.getString(
"K00d2", Integer.toHexString(tc & 0xff))); //$NON-NLS-1$
}
|
private java.lang.Object | readCyclicReference()Reads the next item from the stream assuming it is a cyclic reference to
an object previously read. Return the actual object previously read.
return registeredObjectRead(readNewHandle());
|
public double | readDouble()Reads a double (64 bit) from the source stream.
return primitiveTypes.readDouble();
|
private java.lang.Object | readEnum(boolean unshared)
// read classdesc for Enum first
ObjectStreamClass classDesc = readEnumDesc();
Integer newHandle = Integer.valueOf(nextHandle());
// read name after class desc
String name;
byte tc = nextTC();
switch (tc) {
case TC_REFERENCE:
if (unshared) {
readNewHandle();
throw new InvalidObjectException(Msg.getString("KA002")); //$NON-NLS-1$
}
name = (String) readCyclicReference();
break;
case TC_STRING:
name = (String) readNewString(unshared);
break;
default:
throw new StreamCorruptedException(Msg.getString("K00d2"));//$NON-NLS-1$
}
Enum<?> result = Enum.valueOf((Class) classDesc.forClass(), name);
registerObjectRead(result, newHandle, unshared);
return result;
|
private java.io.ObjectStreamClass | readEnumDesc()
byte tc = nextTC();
switch (tc) {
case TC_CLASSDESC:
return readEnumDescInternal();
case TC_REFERENCE:
return (ObjectStreamClass) readCyclicReference();
case TC_NULL:
return null;
default:
throw new StreamCorruptedException(Msg.getString(
"K00d2", Integer.toHexString(tc & 0xff))); //$NON-NLS-1$
}
|
private java.io.ObjectStreamClass | readEnumDescInternal()
ObjectStreamClass classDesc;
primitiveData = input;
Integer oldHandle = descriptorHandle;
descriptorHandle = Integer.valueOf(nextHandle());
classDesc = readClassDescriptor();
if (descriptorHandle != null) {
registerObjectRead(classDesc, descriptorHandle, false);
}
descriptorHandle = oldHandle;
primitiveData = emptyStream;
classDesc.setClass(resolveClass(classDesc));
// Consume unread class annotation data and TC_ENDBLOCKDATA
discardData();
ObjectStreamClass superClass = readClassDesc();
checkedSetSuperClassDesc(classDesc, superClass);
// Check SUIDs, note all SUID for Enum is 0L
if (0L != classDesc.getSerialVersionUID()
|| 0L != superClass.getSerialVersionUID()) {
throw new InvalidClassException(superClass.getName(), Msg
.getString("K00da", superClass, //$NON-NLS-1$
superClass));
}
byte tc = nextTC();
// discard TC_ENDBLOCKDATA after classDesc if any
if (tc == TC_ENDBLOCKDATA) {
// read next parent class. For enum, it may be null
superClass.setSuperclass(readClassDesc());
} else {
// not TC_ENDBLOCKDATA, push back for next read
pushbackTC();
}
return classDesc;
|
private java.lang.Exception | readException()Read the next item assuming it is an exception. The exception is not a
regular instance in the object graph, but the exception instance that
happened (if any) when dumping the original object graph. The set of seen
objects will be reset just before and just after loading this exception
object.
When exceptions are found normally in the object graph, they are loaded
as a regular object, and not by this method. In that case, the set of
"known objects" is not reset.
resetSeenObjects();
// Now we read the Throwable object that was saved
// WARNING - the grammar says it is a Throwable, but the
// WriteAbortedException constructor takes an Exception. So, we read an
// Exception from the stream
Exception exc = (Exception) readObject();
// We reset the receiver's state (the grammar has "reset" in normal
// font)
resetSeenObjects();
return exc;
|
private void | readFieldDescriptors(java.io.ObjectStreamClass cDesc)Reads a collection of field descriptors (name, type name, etc) for the
class descriptor {@code cDesc} (an {@code ObjectStreamClass})
short numFields = input.readShort();
ObjectStreamField[] fields = new ObjectStreamField[numFields];
// We set it now, but each element will be inserted in the array further
// down
cDesc.setLoadFields(fields);
// Check ObjectOutputStream.writeFieldDescriptors
for (short i = 0; i < numFields; i++) {
char typecode = (char) input.readByte();
String fieldName = input.readUTF();
boolean isPrimType = ObjectStreamClass.isPrimitiveType(typecode);
String classSig;
if (isPrimType) {
classSig = String.valueOf(typecode);
} else {
// The spec says it is a UTF, but experience shows they dump
// this String using writeObject (unlike the field name, which
// is saved with writeUTF).
// And if resolveObject is enabled, the classSig may be modified
// so that the original class descriptor cannot be read
// properly, so it is disabled.
boolean old = enableResolve;
try {
enableResolve = false;
classSig = (String) readObject();
} finally {
enableResolve = old;
}
}
ObjectStreamField f = new ObjectStreamField(classSig, fieldName);
fields[i] = f;
}
|
private void | readFieldValues(EmulatedFieldsForLoading emulatedFields)Reads a collection of field values for the emulated fields
{@code emulatedFields}
EmulatedFields.ObjectSlot[] slots = emulatedFields.emulatedFields()
.slots();
for (ObjectSlot element : slots) {
element.defaulted = false;
Class<?> type = element.field.getType();
if (type == Integer.TYPE) {
element.fieldValue = Integer.valueOf(input.readInt());
} else if (type == Byte.TYPE) {
element.fieldValue = Byte.valueOf(input.readByte());
} else if (type == Character.TYPE) {
element.fieldValue = Character.valueOf(input.readChar());
} else if (type == Short.TYPE) {
element.fieldValue = Short.valueOf(input.readShort());
} else if (type == Boolean.TYPE) {
element.fieldValue = Boolean.valueOf(input.readBoolean());
} else if (type == Long.TYPE) {
element.fieldValue = Long.valueOf(input.readLong());
} else if (type == Float.TYPE) {
element.fieldValue = Float.valueOf(input.readFloat());
} else if (type == Double.TYPE) {
element.fieldValue = Double.valueOf(input.readDouble());
} else {
// Either array or Object
try {
element.fieldValue = readObject();
} catch (ClassNotFoundException cnf) {
// WARNING- Not sure this is the right thing to do. Write
// test case.
throw new InvalidClassException(cnf.toString());
}
}
}
|
private void | readFieldValues(java.lang.Object obj, java.io.ObjectStreamClass classDesc)Reads a collection of field values for the class descriptor
{@code classDesc} (an {@code ObjectStreamClass}). The
values will be used to set instance fields in object {@code obj}.
This is the default mechanism, when emulated fields (an
{@code GetField}) are not used. Actual values to load are stored
directly into the object {@code obj}.
// Now we must read all fields and assign them to the receiver
ObjectStreamField[] fields = classDesc.getLoadFields();
fields = (null == fields ? new ObjectStreamField[] {} : fields);
Class<?> declaringClass = classDesc.forClass();
if (declaringClass == null && mustResolve) {
throw new ClassNotFoundException(classDesc.getName());
}
for (ObjectStreamField fieldDesc : fields) {
// Code duplication starts, just because Java is typed
if (fieldDesc.isPrimitive()) {
try {
switch (fieldDesc.getTypeCode()) {
case 'B":
setField(obj, declaringClass, fieldDesc.getName(),
input.readByte());
break;
case 'C":
setField(obj, declaringClass, fieldDesc.getName(),
input.readChar());
break;
case 'D":
setField(obj, declaringClass, fieldDesc.getName(),
input.readDouble());
break;
case 'F":
setField(obj, declaringClass, fieldDesc.getName(),
input.readFloat());
break;
case 'I":
setField(obj, declaringClass, fieldDesc.getName(),
input.readInt());
break;
case 'J":
setField(obj, declaringClass, fieldDesc.getName(),
input.readLong());
break;
case 'S":
setField(obj, declaringClass, fieldDesc.getName(),
input.readShort());
break;
case 'Z":
setField(obj, declaringClass, fieldDesc.getName(),
input.readBoolean());
break;
default:
throw new StreamCorruptedException(Msg.getString(
"K00d5", fieldDesc.getTypeCode())); //$NON-NLS-1$
}
} catch (NoSuchFieldError err) {
}
} else {
// Object type (array included).
String fieldName = fieldDesc.getName();
boolean setBack = false;
ObjectStreamField field = classDesc.getField(fieldName);
if (mustResolve && field == null) {
setBack = true;
mustResolve = false;
}
Object toSet;
if (field != null && field.isUnshared()) {
toSet = readUnshared();
} else {
toSet = readObject();
}
if (setBack) {
mustResolve = true;
}
if (field != null) {
if (toSet != null) {
// BEGIN android-removed
// Class<?> fieldType = field.getType();
// END android-removed
// BEGIN android-added
// Originally getTypeInternal() was called getType().
// After the semantics of getType() changed inside
// Harmony, the check below wasn't adjusted and didn't
// work anymore.
Class<?> fieldType = field.getTypeInternal();
// END android-added
Class<?> valueType = toSet.getClass();
if (!fieldType.isAssignableFrom(valueType)) {
throw new ClassCastException(Msg.getString(
"K00d4", new String[] { //$NON-NLS-1$
fieldType.toString(), valueType.toString(),
classDesc.getName() + "." //$NON-NLS-1$
+ fieldName }));
}
try {
objSetField(obj, declaringClass, fieldName, field
.getTypeString(), toSet);
} catch (NoSuchFieldError e) {
// Ignored
}
}
}
}
}
|
public java.io.ObjectInputStream$GetField | readFields()Reads the persistent fields of the object that is currently being read
from the source stream. The values read are stored in a GetField object
that provides access to the persistent fields. This GetField object is
then returned.
// We can't be called from just anywhere. There are rules.
if (currentObject == null) {
throw new NotActiveException();
}
EmulatedFieldsForLoading result = new EmulatedFieldsForLoading(
currentClass);
readFieldValues(result);
return result;
|
public float | readFloat()Reads a float (32 bit) from the source stream.
return primitiveTypes.readFloat();
|
public void | readFully(byte[] buffer)Reads bytes from the source stream into the byte array {@code buffer}.
This method will block until {@code buffer.length} bytes have been read.
primitiveTypes.readFully(buffer);
|
public void | readFully(byte[] buffer, int offset, int length)Reads bytes from the source stream into the byte array {@code buffer}.
This method will block until {@code length} number of bytes have been
read.
primitiveTypes.readFully(buffer, offset, length);
|
private void | readHierarchy(java.lang.Object object, java.io.ObjectStreamClass classDesc)Walks the hierarchy of classes described by class descriptor
{@code classDesc} and reads the field values corresponding to
fields declared by the corresponding class descriptor. The instance to
store field values into is {@code object}. If the class
(corresponding to class descriptor {@code classDesc}) defines
private instance method {@code readObject} it will be used to load
field values.
// We can't be called from just anywhere. There are rules.
if (object == null && mustResolve) {
throw new NotActiveException();
}
ArrayList<ObjectStreamClass> streamClassList = new ArrayList<ObjectStreamClass>(
32);
ObjectStreamClass nextStreamClass = classDesc;
while (nextStreamClass != null) {
streamClassList.add(0, nextStreamClass);
nextStreamClass = nextStreamClass.getSuperclass();
}
if (object == null) {
Iterator<ObjectStreamClass> streamIt = streamClassList.iterator();
while (streamIt.hasNext()) {
ObjectStreamClass streamClass = streamIt.next();
readObjectForClass(null, streamClass);
}
} else {
ArrayList<Class<?>> classList = new ArrayList<Class<?>>(32);
Class<?> nextClass = object.getClass();
while (nextClass != null) {
Class<?> testClass = nextClass.getSuperclass();
if (testClass != null) {
classList.add(0, nextClass);
}
nextClass = testClass;
}
int lastIndex = 0;
for (int i = 0; i < classList.size(); i++) {
Class<?> superclass = classList.get(i);
int index = findStreamSuperclass(superclass, streamClassList,
lastIndex);
if (index == -1) {
readObjectNoData(object, superclass);
} else {
for (int j = lastIndex; j <= index; j++) {
readObjectForClass(object, streamClassList.get(j));
}
lastIndex = index + 1;
}
}
}
|
public int | readInt()Reads an integer (32 bit) from the source stream.
return primitiveTypes.readInt();
|
public java.lang.String | readLine()Reads the next line from the source stream. Lines are terminated by
{@code '\r'}, {@code '\n'}, {@code "\r\n"} or an {@code EOF}.
return primitiveTypes.readLine();
|
public long | readLong()Reads a long (64 bit) from the source stream.
return primitiveTypes.readLong();
|
private java.lang.Object | readNewArray(boolean unshared)Read a new array from the receiver. It is assumed the array has not been
read yet (not a cyclic reference). Return the array read.
ObjectStreamClass classDesc = readClassDesc();
if (classDesc == null) {
throw new InvalidClassException(Msg.getString("K00d1")); //$NON-NLS-1$
}
Integer newHandle = Integer.valueOf(nextHandle());
// Array size
int size = input.readInt();
Class<?> arrayClass = classDesc.forClass();
Class<?> componentType = arrayClass.getComponentType();
Object result = Array.newInstance(componentType, size);
registerObjectRead(result, newHandle, unshared);
// Now we have code duplication just because Java is typed. We have to
// read N elements and assign to array positions, but we must typecast
// the array first, and also call different methods depending on the
// elements.
if (componentType.isPrimitive()) {
if (componentType == Integer.TYPE) {
int[] intArray = (int[]) result;
for (int i = 0; i < size; i++) {
intArray[i] = input.readInt();
}
} else if (componentType == Byte.TYPE) {
byte[] byteArray = (byte[]) result;
input.readFully(byteArray, 0, size);
} else if (componentType == Character.TYPE) {
char[] charArray = (char[]) result;
for (int i = 0; i < size; i++) {
charArray[i] = input.readChar();
}
} else if (componentType == Short.TYPE) {
short[] shortArray = (short[]) result;
for (int i = 0; i < size; i++) {
shortArray[i] = input.readShort();
}
} else if (componentType == Boolean.TYPE) {
boolean[] booleanArray = (boolean[]) result;
for (int i = 0; i < size; i++) {
booleanArray[i] = input.readBoolean();
}
} else if (componentType == Long.TYPE) {
long[] longArray = (long[]) result;
for (int i = 0; i < size; i++) {
longArray[i] = input.readLong();
}
} else if (componentType == Float.TYPE) {
float[] floatArray = (float[]) result;
for (int i = 0; i < size; i++) {
floatArray[i] = input.readFloat();
}
} else if (componentType == Double.TYPE) {
double[] doubleArray = (double[]) result;
for (int i = 0; i < size; i++) {
doubleArray[i] = input.readDouble();
}
} else {
throw new ClassNotFoundException(Msg.getString(
"K00d7", classDesc.getName())); //$NON-NLS-1$
}
} else {
// Array of Objects
Object[] objectArray = (Object[]) result;
for (int i = 0; i < size; i++) {
objectArray[i] = readObject();
}
}
if (enableResolve) {
result = resolveObject(result);
registerObjectRead(result, newHandle, false);
}
return result;
|
private java.lang.Class | readNewClass(boolean unshared)Reads a new class from the receiver. It is assumed the class has not been
read yet (not a cyclic reference). Return the class read.
ObjectStreamClass classDesc = readClassDesc();
if (classDesc != null) {
Integer newHandle = Integer.valueOf(nextHandle());
Class<?> localClass = classDesc.forClass();
if (localClass != null) {
registerObjectRead(localClass, newHandle, unshared);
}
return localClass;
}
throw new InvalidClassException(Msg.getString("K00d1")); //$NON-NLS-1$
|
private java.io.ObjectStreamClass | readNewClassDesc(boolean unshared)Reads a new class descriptor from the receiver. It is assumed the class
descriptor has not been read yet (not a cyclic reference). Return the
class descriptor read.
// So read...() methods can be used by
// subclasses during readClassDescriptor()
primitiveData = input;
Integer oldHandle = descriptorHandle;
descriptorHandle = Integer.valueOf(nextHandle());
ObjectStreamClass newClassDesc = readClassDescriptor();
if (descriptorHandle != null) {
registerObjectRead(newClassDesc, descriptorHandle, unshared);
}
descriptorHandle = oldHandle;
primitiveData = emptyStream;
// We need to map classDesc to class.
try {
newClassDesc.setClass(resolveClass(newClassDesc));
// Check SUIDs
verifySUID(newClassDesc);
// Check base name of the class
verifyBaseName(newClassDesc);
} catch (ClassNotFoundException e) {
if (mustResolve) {
throw e;
// Just continue, the class may not be required
}
}
// Resolve the field signatures using the class loader of the
// resolved class
ObjectStreamField[] fields = newClassDesc.getLoadFields();
fields = (null == fields ? new ObjectStreamField[] {} : fields);
ClassLoader loader = newClassDesc.forClass() == null ? callerClassLoader
: newClassDesc.forClass().getClassLoader();
for (ObjectStreamField element : fields) {
element.resolve(loader);
}
// Consume unread class annotation data and TC_ENDBLOCKDATA
discardData();
checkedSetSuperClassDesc(newClassDesc, readClassDesc());
return newClassDesc;
|
private java.lang.Integer | readNewHandle()Write a new handle describing a cyclic reference from the stream.
return Integer.valueOf(input.readInt());
|
private java.lang.Object | readNewLongString(boolean unshared)Read a new String in UTF format from the receiver. Return the string
read.
long length = input.readLong();
Object result = input.decodeUTF((int) length);
if (enableResolve) {
result = resolveObject(result);
}
int newHandle = nextHandle();
registerObjectRead(result, Integer.valueOf(newHandle), unshared);
return result;
|
private java.lang.Object | readNewObject(boolean unshared)Read a new object from the stream. It is assumed the object has not been
loaded yet (not a cyclic reference). Return the object read.
If the object implements {@code Externalizable} its
{@code readExternal} is called. Otherwise, all fields described by
the class hierarchy are loaded. Each class can define how its declared
instance fields are loaded by defining a private method
{@code readObject}
ObjectStreamClass classDesc = readClassDesc();
if (classDesc == null) {
throw new InvalidClassException(Msg.getString("K00d1")); //$NON-NLS-1$
}
Integer newHandle = Integer.valueOf(nextHandle());
// Note that these values come from the Stream, and in fact it could be
// that the classes have been changed so that the info below now
// conflicts with the newer class
boolean wasExternalizable = (classDesc.getFlags() & SC_EXTERNALIZABLE) > 0;
boolean wasSerializable = (classDesc.getFlags() & SC_SERIALIZABLE) > 0;
// Maybe we should cache the values above in classDesc ? It may be the
// case that when reading classDesc we may need to read more stuff
// depending on the values above
Class<?> objectClass = classDesc.forClass();
Object result, registeredResult = null;
if (objectClass != null) {
// The class of the instance may not be the same as the class of the
// constructor to run
// This is the constructor to run if Externalizable
Class<?> constructorClass = objectClass;
// WARNING - What if the object is serializable and externalizable ?
// Is that possible ?
if (wasSerializable) {
// Now we must run the constructor of the class just above the
// one that implements Serializable so that slots that were not
// dumped can be initialized properly
while (constructorClass != null
&& ObjectStreamClass.isSerializable(constructorClass)) {
constructorClass = constructorClass.getSuperclass();
}
}
// Fetch the empty constructor, or null if none.
Constructor<?> constructor = null;
if (constructorClass != null) {
try {
constructor = constructorClass
.getDeclaredConstructor(ObjectStreamClass.EMPTY_CONSTRUCTOR_PARAM_TYPES);
} catch (NoSuchMethodException nsmEx) {
// Ignored
}
}
// Has to have an empty constructor
if (constructor == null) {
throw new InvalidClassException(constructorClass.getName(), Msg
.getString("K00dc")); //$NON-NLS-1$
}
int constructorModifiers = constructor.getModifiers();
// Now we must check if the empty constructor is visible to the
// instantiation class
if (Modifier.isPrivate(constructorModifiers)
|| (wasExternalizable && !Modifier
.isPublic(constructorModifiers))) {
throw new InvalidClassException(constructorClass.getName(), Msg
.getString("K00dc")); //$NON-NLS-1$
}
// We know we are testing from a subclass, so the only other case
// where the visibility is not allowed is when the constructor has
// default visibility and the instantiation class is in a different
// package than the constructor class
if (!Modifier.isPublic(constructorModifiers)
&& !Modifier.isProtected(constructorModifiers)) {
// Not public, not private and not protected...means default
// visibility. Check if same package
if (!inSamePackage(constructorClass, objectClass)) {
throw new InvalidClassException(constructorClass.getName(),
Msg.getString("K00dc")); //$NON-NLS-1$
}
}
// Now we know which class to instantiate and which constructor to
// run. We are allowed to run the constructor.
result = newInstance(objectClass, constructorClass);
registerObjectRead(result, newHandle, unshared);
registeredResult = result;
} else {
result = null;
}
try {
// This is how we know what to do in defaultReadObject. And it is
// also used by defaultReadObject to check if it was called from an
// invalid place. It also allows readExternal to call
// defaultReadObject and have it work.
currentObject = result;
currentClass = classDesc;
// If Externalizable, just let the object read itself
if (wasExternalizable) {
boolean blockData = (classDesc.getFlags() & SC_BLOCK_DATA) > 0;
if (!blockData) {
primitiveData = input;
}
if (mustResolve) {
Externalizable extern = (Externalizable) result;
extern.readExternal(this);
}
if (blockData) {
// Similar to readHierarchy. Anything not read by
// readExternal has to be consumed here
discardData();
} else {
primitiveData = emptyStream;
}
} else {
// If we got here, it is Serializable but not Externalizable.
// Walk the hierarchy reading each class' slots
readHierarchy(result, classDesc);
}
} finally {
// Cleanup, needs to run always so that we can later detect invalid
// calls to defaultReadObject
currentObject = null;
currentClass = null;
}
if (objectClass != null) {
Object readResolveMethod = readResolveCache.get(objectClass);
if (readResolveMethod != this) {
if (readResolveMethod == null) {
final Method readResolve = ObjectStreamClass
.methodReadResolve(objectClass);
if (readResolve == null) {
readResolveCache.put(objectClass, this);
readResolveMethod = null;
} else {
// Has replacement method
AccessController.doPrivileged(new PriviAction<Object>(
readResolve));
readResolveCache.put(objectClass, readResolve);
readResolveMethod = readResolve;
}
}
if (readResolveMethod != null) {
try {
result = ((Method) readResolveMethod).invoke(result,
(Object[]) null);
} catch (IllegalAccessException iae) {
} catch (InvocationTargetException ite) {
Throwable target = ite.getTargetException();
if (target instanceof ObjectStreamException) {
throw (ObjectStreamException) target;
} else if (target instanceof Error) {
throw (Error) target;
} else {
throw (RuntimeException) target;
}
}
}
}
}
// We get here either if class-based replacement was not needed or if it
// was needed but produced the same object or if it could not be
// computed.
// The object to return is the one we instantiated or a replacement for
// it
if (result != null && enableResolve) {
result = resolveObject(result);
}
if (registeredResult != result) {
registerObjectRead(result, newHandle, unshared);
}
return result;
|
private java.lang.Class | readNewProxyClassDesc()Reads a new proxy class descriptor from the receiver. It is assumed the
proxy class descriptor has not been read yet (not a cyclic reference).
Return the proxy class descriptor read.
int count = input.readInt();
String[] interfaceNames = new String[count];
for (int i = 0; i < count; i++) {
interfaceNames[i] = input.readUTF();
}
Class<?> proxy = resolveProxyClass(interfaceNames);
// Consume unread class annotation data and TC_ENDBLOCKDATA
discardData();
return proxy;
|
private java.lang.Object | readNewString(boolean unshared)Read a string encoded in {@link DataInput modified UTF-8} from the
receiver. Return the string read.
Object result = input.readUTF();
if (enableResolve) {
result = resolveObject(result);
}
int newHandle = nextHandle();
registerObjectRead(result, Integer.valueOf(newHandle), unshared);
return result;
|
private java.lang.Object | readNonPrimitiveContent(boolean unshared)Reads the content of the receiver based on the previously read token
{@code tc}. Primitive data content is considered an error.
checkReadPrimitiveTypes();
if (primitiveData.available() > 0) {
OptionalDataException e = new OptionalDataException();
e.length = primitiveData.available();
throw e;
}
do {
byte tc = nextTC();
switch (tc) {
case TC_CLASS:
return readNewClass(unshared);
case TC_CLASSDESC:
return readNewClassDesc(unshared);
case TC_ARRAY:
return readNewArray(unshared);
case TC_OBJECT:
return readNewObject(unshared);
case TC_STRING:
return readNewString(unshared);
case TC_LONGSTRING:
return readNewLongString(unshared);
case TC_ENUM:
return readEnum(unshared);
case TC_REFERENCE:
if (unshared) {
readNewHandle();
throw new InvalidObjectException(Msg.getString("KA002")); //$NON-NLS-1$
}
return readCyclicReference();
case TC_NULL:
return null;
case TC_EXCEPTION:
Exception exc = readException();
throw new WriteAbortedException(Msg.getString("K00d3"), exc); //$NON-NLS-1$
case TC_RESET:
resetState();
break;
case TC_ENDBLOCKDATA: // Can occur reading class annotation
pushbackTC();
OptionalDataException e = new OptionalDataException();
e.eof = true;
throw e;
default:
throw new StreamCorruptedException(Msg.getString(
"K00d2", Integer.toHexString(tc & 0xff))); //$NON-NLS-1$
}
// Only TC_RESET falls through
} while (true);
|
public final java.lang.Object | readObject()Reads the next object from the source stream.
return readObject(false);
|
private java.lang.Object | readObject(boolean unshared)
boolean restoreInput = (primitiveData == input);
if (restoreInput) {
primitiveData = emptyStream;
}
// This is the spec'ed behavior in JDK 1.2. Very bizarre way to allow
// behavior overriding.
if (subclassOverridingImplementation && !unshared) {
return readObjectOverride();
}
// If we still had primitive types to read, should we discard them
// (reset the primitiveTypes stream) or leave as is, so that attempts to
// read primitive types won't read 'past data' ???
Object result;
try {
// We need this so we can tell when we are returning to the
// original/outside caller
if (++nestedLevels == 1) {
// Remember the caller's class loader
// BEGIN android-changed
callerClassLoader = getClosestUserClassLoader();
// END android-changed
}
result = readNonPrimitiveContent(unshared);
if (restoreInput) {
primitiveData = input;
}
} finally {
// We need this so we can tell when we are returning to the
// original/outside caller
if (--nestedLevels == 0) {
// We are going to return to the original caller, perform
// cleanups.
// No more need to remember the caller's class loader
callerClassLoader = null;
}
}
// Done reading this object. Is it time to return to the original
// caller? If so we need to perform validations first.
if (nestedLevels == 0 && validations != null) {
// We are going to return to the original caller. If validation is
// enabled we need to run them now and then cleanup the validation
// collection
try {
for (InputValidationDesc element : validations) {
element.validator.validateObject();
}
} finally {
// Validations have to be renewed, since they are only called
// from readObject
validations = null;
}
}
return result;
|
private void | readObjectForClass(java.lang.Object object, java.io.ObjectStreamClass classDesc)
// Have to do this before calling defaultReadObject or anything that
// calls defaultReadObject
currentObject = object;
currentClass = classDesc;
boolean hadWriteMethod = (classDesc.getFlags() & SC_WRITE_METHOD) > 0;
Class<?> targetClass = classDesc.forClass();
final Method readMethod;
if (targetClass == null || !mustResolve) {
readMethod = null;
} else {
readMethod = ObjectStreamClass
.getPrivateReadObjectMethod(targetClass);
}
try {
if (readMethod != null) {
// We have to be able to fetch its value, even if it is private
AccessController.doPrivileged(new PriviAction<Object>(
readMethod));
try {
readMethod.invoke(object, new Object[] { this });
} catch (InvocationTargetException e) {
Throwable ex = e.getTargetException();
if (ex instanceof ClassNotFoundException) {
throw (ClassNotFoundException) ex;
} else if (ex instanceof RuntimeException) {
throw (RuntimeException) ex;
} else if (ex instanceof Error) {
throw (Error) ex;
}
throw (IOException) ex;
} catch (IllegalAccessException e) {
throw new RuntimeException(e.toString());
}
} else {
defaultReadObject();
}
if (hadWriteMethod) {
discardData();
}
} finally {
// Cleanup, needs to run always so that we can later detect invalid
// calls to defaultReadObject
currentObject = null; // We did not set this, so we do not need to
// clean it
currentClass = null;
}
|
private void | readObjectNoData(java.lang.Object object, java.lang.Class cl)
if (!ObjectStreamClass.isSerializable(cl)) {
return;
}
final Method readMethod = ObjectStreamClass
.getPrivateReadObjectNoDataMethod(cl);
if (readMethod != null) {
AccessController.doPrivileged(new PriviAction<Object>(readMethod));
try {
readMethod.invoke(object, new Object[0]);
} catch (InvocationTargetException e) {
Throwable ex = e.getTargetException();
if (ex instanceof RuntimeException) {
throw (RuntimeException) ex;
} else if (ex instanceof Error) {
throw (Error) ex;
}
throw (ObjectStreamException) ex;
} catch (IllegalAccessException e) {
throw new RuntimeException(e.toString());
}
}
|
protected java.lang.Object | readObjectOverride()Method to be overriden by subclasses to read the next object from the
source stream.
if (input == null) {
return null;
}
// Subclasses must override.
throw new IOException();
|
public short | readShort()Reads a short (16 bit) from the source stream.
return primitiveTypes.readShort();
|
protected void | readStreamHeader()Reads and validates the ObjectInputStream header from the source stream.
if (input.readShort() == STREAM_MAGIC
&& input.readShort() == STREAM_VERSION) {
return;
}
throw new StreamCorruptedException();
|
public java.lang.String | readUTF()Reads a string encoded in {@link DataInput modified UTF-8} from the
source stream.
return primitiveTypes.readUTF();
|
public java.lang.Object | readUnshared()Reads the next unshared object from the source stream.
return readObject(true);
|
public int | readUnsignedByte()Reads an unsigned byte (8 bit) from the source stream.
return primitiveTypes.readUnsignedByte();
|
public int | readUnsignedShort()Reads an unsigned short (16 bit) from the source stream.
return primitiveTypes.readUnsignedShort();
|
private void | registerObjectRead(java.lang.Object obj, java.lang.Integer handle, boolean unshared)Assume object {@code obj} has been read, and assign a handle to
it, {@code handle}.
objectsRead.put(handle, unshared ? UNSHARED_OBJ : obj);
|
public synchronized void | registerValidation(java.io.ObjectInputValidation object, int priority)Registers a callback for post-deserialization validation of objects. It
allows to perform additional consistency checks before the {@code
readObject()} method of this class returns its result to the caller. This
method can only be called from within the {@code readObject()} method of
a class that implements "special" deserialization rules. It can be called
multiple times. Validation callbacks are then done in order of decreasing
priority, defined by {@code priority}.
// Validation can only be registered when inside readObject calls
Object instanceBeingRead = this.currentObject;
// We can't be called from just anywhere. There are rules.
if (instanceBeingRead == null) {
throw new NotActiveException();
}
if (object == null) {
throw new InvalidObjectException(Msg.getString("K00d9")); //$NON-NLS-1$
}
// From now on it is just insertion in a SortedCollection. Since
// the Java class libraries don't provide that, we have to
// implement it from scratch here.
InputValidationDesc desc = new InputValidationDesc();
desc.validator = object;
desc.priority = priority;
// No need for this, validateObject does not take a parameter
// desc.toValidate = instanceBeingRead;
if (validations == null) {
validations = new InputValidationDesc[1];
validations[0] = desc;
} else {
int i = 0;
for (; i < validations.length; i++) {
InputValidationDesc validation = validations[i];
// Sorted, higher priority first.
if (priority >= validation.priority) {
break; // Found the index where to insert
}
}
InputValidationDesc[] oldValidations = validations;
int currentSize = oldValidations.length;
validations = new InputValidationDesc[currentSize + 1];
System.arraycopy(oldValidations, 0, validations, 0, i);
System.arraycopy(oldValidations, i, validations, i + 1, currentSize
- i);
validations[i] = desc;
}
|
private java.lang.Object | registeredObjectRead(java.lang.Integer handle)Return the object previously read tagged with handle {@code handle}.
Object res = objectsRead.get(handle);
if (res == UNSHARED_OBJ) {
throw new InvalidObjectException(Msg.getString("KA010")); //$NON-NLS-1$
}
return res;
|
private void | resetSeenObjects()Reset the collection of objects already loaded by the receiver.
objectsRead = new Hashtable<Integer, Object>();
currentHandle = baseWireHandle;
primitiveData = emptyStream;
|
private void | resetState()Reset the receiver. The collection of objects already read by the
receiver is reset, and internal structures are also reset so that the
receiver knows it is in a fresh clean state.
resetSeenObjects();
hasPushbackTC = false;
pushbackTC = 0;
// nestedLevels = 0;
|
protected java.lang.Class | resolveClass(java.io.ObjectStreamClass osClass)Loads the Java class corresponding to the class descriptor {@code
osClass} that has just been read from the source stream.
String className = osClass.getName();
// if it is primitive class, for example, long.class
Class<?> cls = PRIMITIVE_CLASSES.get(className);
if (null == cls) {
// not primitive class
// Use the first non-null ClassLoader on the stack. If null, use the
// system class loader
return Class.forName(className, true, callerClassLoader);
}
return cls;
|
protected java.lang.Object | resolveObject(java.lang.Object object)Allows trusted subclasses to substitute the specified original {@code
object} with a new object. Object substitution has to be activated first
with calling {@code enableResolveObject(true)}. This implementation just
returns {@code object}.
// By default no object replacement. Subclasses can override
return object;
|
protected java.lang.Class | resolveProxyClass(java.lang.String[] interfaceNames)Creates the proxy class that implements the interfaces specified in
{@code interfaceNames}.
// BEGIN android-removed
// ClassLoader loader = VM.getNonBootstrapClassLoader();
// END android-removed
// BEGIN android-added
ClassLoader loader = ClassLoader.getSystemClassLoader();
// END android-added
Class<?>[] interfaces = new Class<?>[interfaceNames.length];
for (int i = 0; i < interfaceNames.length; i++) {
interfaces[i] = Class.forName(interfaceNames[i], false, loader);
}
try {
return Proxy.getProxyClass(loader, interfaces);
} catch (IllegalArgumentException e) {
throw new ClassNotFoundException(e.toString(), e);
}
|
private static native void | setField(java.lang.Object instance, java.lang.Class declaringClass, java.lang.String fieldName, byte value)Set a given declared field named {@code fieldName} of
{@code instance} to the new {@code byte} value
{@code value}.
This method could be implemented non-natively on top of java.lang.reflect
implementations that support the {@code setAccessible} API, at the
expense of extra object creation (java.lang.reflect.Field). Otherwise
Serialization could not set private fields, except by the use of a native
method like this one.
|
private static native void | setField(java.lang.Object instance, java.lang.Class declaringClass, java.lang.String fieldName, char value)Set a given declared field named {@code fieldName} of
{@code instance} to the new {@code char} value
{@code value}.
This method could be implemented non-natively on top of java.lang.reflect
implementations that support the {@code setAccessible} API, at the
expense of extra object creation (java.lang.reflect.Field). Otherwise
Serialization could not set private fields, except by the use of a native
method like this one.
|
private static native void | setField(java.lang.Object instance, java.lang.Class declaringClass, java.lang.String fieldName, double value)Set a given declared field named {@code fieldName} of
{@code instance} to the new {@code double} value
{@code value}.
This method could be implemented non-natively on top of java.lang.reflect
implementations that support the {@code setAccessible} API, at the
expense of extra object creation (java.lang.reflect.Field). Otherwise
Serialization could not set private fields, except by the use of a native
method like this one.
|
private static native void | setField(java.lang.Object instance, java.lang.Class declaringClass, java.lang.String fieldName, float value)Set a given declared field named {@code fieldName} of
{@code instance} to the new {@code float} value
{@code value}.
This method could be implemented non-natively on top of java.lang.reflect
implementations that support the {@code setAccessible} API, at the
expense of extra object creation (java.lang.reflect.Field). Otherwise
Serialization could not set private fields, except by the use of a native
method like this one.
|
private static native void | setField(java.lang.Object instance, java.lang.Class declaringClass, java.lang.String fieldName, int value)Set a given declared field named {@code fieldName} of
{@code instance} to the new {@code int} value
{@code value}.
This method could be implemented non-natively on top of java.lang.reflect
implementations that support the {@code setAccessible} API, at the
expense of extra object creation (java.lang.reflect.Field). Otherwise
Serialization could not set private fields, except by the use of a native
method like this one.
|
private static native void | setField(java.lang.Object instance, java.lang.Class declaringClass, java.lang.String fieldName, long value)Set a given declared field named {@code fieldName} of
{@code instance} to the new {@code long} value
{@code value}.
This method could be implemented non-natively on top of java.lang.reflect
implementations that support the {@code setAccessible} API, at the
expense of extra object creation (java.lang.reflect.Field). Otherwise
Serialization could not set private fields, except by the use of a native
method like this one.
|
private static native void | setField(java.lang.Object instance, java.lang.Class declaringClass, java.lang.String fieldName, short value)Set a given declared field named {@code fieldName} of
{@code instance} to the new {@code short} value
{@code value}.
This method could be implemented non-natively on top of java.lang.reflect
implementations that support the {@code setAccessible} API, at the
expense of extra object creation (java.lang.reflect.Field). Otherwise
Serialization could not set private fields, except by the use of a native
method like this one.
|
private static native void | setField(java.lang.Object instance, java.lang.Class declaringClass, java.lang.String fieldName, boolean value)Set a given declared field named {@code fieldName} of
{@code instance} to the new {@code boolean} value
{@code value}.
This method could be implemented non-natively on top of java.lang.reflect
implementations that support the {@code setAccessible} API, at the
expense of extra object creation (java.lang.reflect.Field). Otherwise
Serialization could not set private fields, except by the use of a native
method like this one.
|
public int | skipBytes(int length)Skips {@code length} bytes on the source stream. This method should not
be used to skip bytes at any arbitrary position, just when reading
primitive data types (int, char etc).
// To be used with available. Ok to call if reading primitive buffer
if (input == null) {
throw new NullPointerException();
}
int offset = 0;
while (offset < length) {
checkReadPrimitiveTypes();
long skipped = primitiveData.skip(length - offset);
if (skipped == 0) {
return offset;
}
offset += (int) skipped;
}
return length;
|
private void | verifyBaseName(java.io.ObjectStreamClass loadedStreamClass)Verify if the base name for descriptor {@code loadedStreamClass}
matches the base name of the corresponding loaded class.
Class<?> localClass = loadedStreamClass.forClass();
ObjectStreamClass localStreamClass = ObjectStreamClass
.lookupStreamClass(localClass);
String loadedClassBaseName = getBaseName(loadedStreamClass.getName());
String localClassBaseName = getBaseName(localStreamClass.getName());
if (!loadedClassBaseName.equals(localClassBaseName)) {
throw new InvalidClassException(loadedStreamClass.getName(), Msg
.getString("KA015", loadedClassBaseName, //$NON-NLS-1$
localClassBaseName));
}
|
private void | verifySUID(java.io.ObjectStreamClass loadedStreamClass)Verify if the SUID for descriptor {@code loadedStreamClass}matches
the SUID of the corresponding loaded class.
Class<?> localClass = loadedStreamClass.forClass();
// Instances of java.lang.Class are always Serializable, even if their
// instances aren't (e.g. java.lang.Object.class). We cannot call lookup
// because it returns null if the parameter represents instances that
// cannot be serialized, and that is not what we want. If we are loading
// an instance of java.lang.Class, we better have the corresponding
// ObjectStreamClass.
ObjectStreamClass localStreamClass = ObjectStreamClass
.lookupStreamClass(localClass);
if (loadedStreamClass.getSerialVersionUID() != localStreamClass
.getSerialVersionUID()) {
throw new InvalidClassException(loadedStreamClass.getName(), Msg
.getString("K00da", loadedStreamClass, //$NON-NLS-1$
localStreamClass));
}
|