diff -r 3392f250c784 -r ecbd252fd3a7 emul/compact/src/main/java/java/io/ObjectStreamClass.java --- a/emul/compact/src/main/java/java/io/ObjectStreamClass.java Fri Mar 22 16:59:47 2013 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,1396 +0,0 @@ -/* - * Copyright (c) 1996, 2011, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -package java.io; - -import java.lang.ref.Reference; -import java.lang.ref.ReferenceQueue; -import java.lang.ref.SoftReference; -import java.lang.ref.WeakReference; -import java.lang.reflect.Constructor; -import java.lang.reflect.Field; -import java.lang.reflect.InvocationTargetException; -import java.lang.reflect.Member; -import java.lang.reflect.Method; -import java.lang.reflect.Modifier; -import java.lang.reflect.Proxy; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collections; -import java.util.Comparator; -import java.util.HashSet; -import java.util.Set; - -/** - * Serialization's descriptor for classes. It contains the name and - * serialVersionUID of the class. The ObjectStreamClass for a specific class - * loaded in this Java VM can be found/created using the lookup method. - * - *
The algorithm to compute the SerialVersionUID is described in
- * Object
- * Serialization Specification, Section 4.6, Stream Unique Identifiers.
- *
- * @author Mike Warres
- * @author Roger Riggs
- * @see ObjectStreamField
- * @see Object Serialization Specification, Section 4, Class Descriptors
- * @since JDK1.1
- */
-public class ObjectStreamClass implements Serializable {
-
- /** serialPersistentFields value indicating no serializable fields */
- public static final ObjectStreamField[] NO_FIELDS =
- new ObjectStreamField[0];
-
- private static final long serialVersionUID = -6120832682080437368L;
- private static final ObjectStreamField[] serialPersistentFields =
- NO_FIELDS;
-
-
- /** class associated with this descriptor (if any) */
- private Class> cl;
- /** name of class represented by this descriptor */
- private String name;
- /** serialVersionUID of represented class (null if not computed yet) */
- private volatile Long suid;
-
- /** true if represents dynamic proxy class */
- private boolean isProxy;
- /** true if represents enum type */
- private boolean isEnum;
- /** true if represented class implements Serializable */
- private boolean serializable;
- /** true if represented class implements Externalizable */
- private boolean externalizable;
- /** true if desc has data written by class-defined writeObject method */
- private boolean hasWriteObjectData;
- /**
- * true if desc has externalizable data written in block data format; this
- * must be true by default to accommodate ObjectInputStream subclasses which
- * override readClassDescriptor() to return class descriptors obtained from
- * ObjectStreamClass.lookup() (see 4461737)
- */
- private boolean hasBlockExternalData = true;
-
- /** exception (if any) thrown while attempting to resolve class */
- private ClassNotFoundException resolveEx;
- /** exception (if any) to throw if non-enum deserialization attempted */
- private InvalidClassException deserializeEx;
- /** exception (if any) to throw if non-enum serialization attempted */
- private InvalidClassException serializeEx;
- /** exception (if any) to throw if default serialization attempted */
- private InvalidClassException defaultSerializeEx;
-
- /** serializable fields */
- private ObjectStreamField[] fields;
- /** aggregate marshalled size of primitive fields */
- private int primDataSize;
- /** number of non-primitive fields */
- private int numObjFields;
- /** reflector for setting/getting serializable field values */
-// private FieldReflector fieldRefl;
- /** data layout of serialized objects described by this class desc */
- private volatile ClassDataSlot[] dataLayout;
-
- /** serialization-appropriate constructor, or null if none */
- private Constructor cons;
- /** class-defined writeObject method, or null if none */
- private Method writeObjectMethod;
- /** class-defined readObject method, or null if none */
- private Method readObjectMethod;
- /** class-defined readObjectNoData method, or null if none */
- private Method readObjectNoDataMethod;
- /** class-defined writeReplace method, or null if none */
- private Method writeReplaceMethod;
- /** class-defined readResolve method, or null if none */
- private Method readResolveMethod;
-
- /** local class descriptor for represented class (may point to self) */
- private ObjectStreamClass localDesc;
- /** superclass descriptor appearing in stream */
- private ObjectStreamClass superDesc;
-
- /**
- * Initializes native code.
- */
- private static native void initNative();
- static {
- initNative();
- }
-
- /**
- * Find the descriptor for a class that can be serialized. Creates an
- * ObjectStreamClass instance if one does not exist yet for class. Null is
- * returned if the specified class does not implement java.io.Serializable
- * or java.io.Externalizable.
- *
- * @param cl class for which to get the descriptor
- * @return the class descriptor for the specified class
- */
- public static ObjectStreamClass lookup(Class> cl) {
- return lookup(cl, false);
- }
-
- /**
- * Returns the descriptor for any class, regardless of whether it
- * implements {@link Serializable}.
- *
- * @param cl class for which to get the descriptor
- * @return the class descriptor for the specified class
- * @since 1.6
- */
- public static ObjectStreamClass lookupAny(Class> cl) {
- return lookup(cl, true);
- }
-
- /**
- * Returns the name of the class described by this descriptor.
- * This method returns the name of the class in the format that
- * is used by the {@link Class#getName} method.
- *
- * @return a string representing the name of the class
- */
- public String getName() {
- return name;
- }
-
- /**
- * Return the serialVersionUID for this class. The serialVersionUID
- * defines a set of classes all with the same name that have evolved from a
- * common root class and agree to be serialized and deserialized using a
- * common format. NonSerializable classes have a serialVersionUID of 0L.
- *
- * @return the SUID of the class described by this descriptor
- */
- public long getSerialVersionUID() {
- // REMIND: synchronize instead of relying on volatile?
- if (suid == null) {
- return computeDefaultSUID(cl);
- }
- return suid.longValue();
- }
-
- /**
- * Return the class in the local VM that this version is mapped to. Null
- * is returned if there is no corresponding local class.
- *
- * @return the Class
instance that this descriptor represents
- */
- public Class> forClass() {
- return cl;
- }
-
- /**
- * Return an array of the fields of this serializable class.
- *
- * @return an array containing an element for each persistent field of
- * this class. Returns an array of length zero if there are no
- * fields.
- * @since 1.2
- */
- public ObjectStreamField[] getFields() {
- return getFields(true);
- }
-
- /**
- * Get the field of this class by name.
- *
- * @param name the name of the data field to look for
- * @return The ObjectStreamField object of the named field or null if
- * there is no such named field.
- */
- public ObjectStreamField getField(String name) {
- return getField(name, null);
- }
-
- /**
- * Return a string describing this ObjectStreamClass.
- */
- public String toString() {
- return name + ": static final long serialVersionUID = " +
- getSerialVersionUID() + "L;";
- }
-
- /**
- * Looks up and returns class descriptor for given class, or null if class
- * is non-serializable and "all" is set to false.
- *
- * @param cl class to look up
- * @param all if true, return descriptors for all classes; if false, only
- * return descriptors for serializable classes
- */
- static ObjectStreamClass lookup(Class> cl, boolean all) {
- if (!(all || Serializable.class.isAssignableFrom(cl))) {
- return null;
- }
- Object entry = null;
- EntryFuture future = null;
- if (entry == null) {
- EntryFuture newEntry = new EntryFuture();
- Reference> newRef = new SoftReference<>(newEntry);
- if (entry == null) {
- future = newEntry;
- }
- }
-
- if (entry instanceof ObjectStreamClass) { // check common case first
- return (ObjectStreamClass) entry;
- }
- if (entry instanceof EntryFuture) {
- future = (EntryFuture) entry;
- if (true) {
- /*
- * Handle nested call situation described by 4803747: waiting
- * for future value to be set by a lookup() call further up the
- * stack will result in deadlock, so calculate and set the
- * future value here instead.
- */
- entry = null;
- } else {
- entry = future.get();
- }
- }
- if (entry == null) {
- try {
- entry = new ObjectStreamClass(cl);
- } catch (Throwable th) {
- entry = th;
- }
- // nested lookup call already set future
- entry = future.get();
- }
-
- if (entry instanceof ObjectStreamClass) {
- return (ObjectStreamClass) entry;
- } else if (entry instanceof RuntimeException) {
- throw (RuntimeException) entry;
- } else if (entry instanceof Error) {
- throw (Error) entry;
- } else {
- throw new InternalError("unexpected entry: " + entry);
- }
- }
-
- /**
- * Placeholder used in class descriptor and field reflector lookup tables
- * for an entry in the process of being initialized. (Internal) callers
- * which receive an EntryFuture belonging to another thread as the result
- * of a lookup should call the get() method of the EntryFuture; this will
- * return the actual entry once it is ready for use and has been set(). To
- * conserve objects, EntryFutures synchronize on themselves.
- */
- private static class EntryFuture {
-
- private static final Object unset = new Object();
- private Object entry = unset;
-
- /**
- * Attempts to set the value contained by this EntryFuture. If the
- * EntryFuture's value has not been set already, then the value is
- * saved, any callers blocked in the get() method are notified, and
- * true is returned. If the value has already been set, then no saving
- * or notification occurs, and false is returned.
- */
- synchronized boolean set(Object entry) {
- if (this.entry != unset) {
- return false;
- }
- this.entry = entry;
- notifyAll();
- return true;
- }
-
- /**
- * Returns the value contained by this EntryFuture, blocking if
- * necessary until a value is set.
- */
- synchronized Object get() {
- boolean interrupted = false;
- while (entry == unset) {
- try {
- wait();
- } catch (InterruptedException ex) {
- interrupted = true;
- }
- }
- return entry;
- }
- }
-
- /**
- * Creates local class descriptor representing given class.
- */
- private ObjectStreamClass(final Class> cl) {
- this.cl = cl;
- name = cl.getName();
- isProxy = Proxy.isProxyClass(cl);
- isEnum = Enum.class.isAssignableFrom(cl);
- serializable = Serializable.class.isAssignableFrom(cl);
- externalizable = Externalizable.class.isAssignableFrom(cl);
-
- Class> superCl = cl.getSuperclass();
- superDesc = (superCl != null) ? lookup(superCl, false) : null;
- localDesc = this;
-
- suid = Long.valueOf(0);
- fields = NO_FIELDS;
-
-
- if (deserializeEx == null) {
- if (isEnum) {
- deserializeEx = new InvalidClassException(name, "enum type");
- } else if (cons == null) {
- deserializeEx = new InvalidClassException(
- name, "no valid constructor");
- }
- }
- for (int i = 0; i < fields.length; i++) {
- if (fields[i].getField() == null) {
- defaultSerializeEx = new InvalidClassException(
- name, "unmatched serializable field(s) declared");
- }
- }
- }
-
- /**
- * Creates blank class descriptor which should be initialized via a
- * subsequent call to initProxy(), initNonProxy() or readNonProxy().
- */
- ObjectStreamClass() {
- }
-
- /**
- * Initializes class descriptor representing a proxy class.
- */
- void initProxy(Class> cl,
- ClassNotFoundException resolveEx,
- ObjectStreamClass superDesc)
- throws InvalidClassException
- {
- this.cl = cl;
- this.resolveEx = resolveEx;
- this.superDesc = superDesc;
- isProxy = true;
- serializable = true;
- suid = Long.valueOf(0);
- fields = NO_FIELDS;
-
- if (cl != null) {
- localDesc = lookup(cl, true);
- if (!localDesc.isProxy) {
- throw new InvalidClassException(
- "cannot bind proxy descriptor to a non-proxy class");
- }
- name = localDesc.name;
- externalizable = localDesc.externalizable;
- cons = localDesc.cons;
- writeReplaceMethod = localDesc.writeReplaceMethod;
- readResolveMethod = localDesc.readResolveMethod;
- deserializeEx = localDesc.deserializeEx;
- }
- }
-
- /**
- * 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;
- }
- }
- // reassign to matched fields so as to reflect local unshared settings
- fields = null;
- }
-
- /**
- * Reads non-proxy class descriptor information from given input stream.
- * The resulting class descriptor is not fully functional; it can only be
- * used as input to the ObjectInputStream.resolveClass() and
- * ObjectStreamClass.initNonProxy() methods.
- */
- 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();
- }
-
- /**
- * 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());
- }
- }
- }
-
- /**
- * Returns ClassNotFoundException (if any) thrown while attempting to
- * resolve local class corresponding to this class descriptor.
- */
- ClassNotFoundException getResolveException() {
- return resolveEx;
- }
-
- /**
- * Throws an InvalidClassException if object instances referencing this
- * class descriptor should not be allowed to deserialize. This method does
- * not apply to deserialization of enum constants.
- */
- void checkDeserialize() throws InvalidClassException {
- if (deserializeEx != null) {
- InvalidClassException ice =
- new InvalidClassException(deserializeEx.classname,
- deserializeEx.getMessage());
- ice.initCause(deserializeEx);
- throw ice;
- }
- }
-
- /**
- * Throws an InvalidClassException if objects whose class is represented by
- * this descriptor should not be allowed to serialize. This method does
- * not apply to serialization of enum constants.
- */
- void checkSerialize() throws InvalidClassException {
- if (serializeEx != null) {
- InvalidClassException ice =
- new InvalidClassException(serializeEx.classname,
- serializeEx.getMessage());
- ice.initCause(serializeEx);
- throw ice;
- }
- }
-
- /**
- * Throws an InvalidClassException if objects whose class is represented by
- * this descriptor should not be permitted to use default serialization
- * (e.g., if the class declares serializable fields that do not correspond
- * to actual fields, and hence must use the GetField API). This method
- * does not apply to deserialization of enum constants.
- */
- void checkDefaultSerialize() throws InvalidClassException {
- if (defaultSerializeEx != null) {
- InvalidClassException ice =
- new InvalidClassException(defaultSerializeEx.classname,
- defaultSerializeEx.getMessage());
- ice.initCause(defaultSerializeEx);
- throw ice;
- }
- }
-
- /**
- * Returns superclass descriptor. Note that on the receiving side, the
- * superclass descriptor may be bound to a class that is not a superclass
- * of the subclass descriptor's bound class.
- */
- ObjectStreamClass getSuperDesc() {
- return superDesc;
- }
-
- /**
- * Returns the "local" class descriptor for the class associated with this
- * class descriptor (i.e., the result of
- * ObjectStreamClass.lookup(this.forClass())) or null if there is no class
- * associated with this descriptor.
- */
- ObjectStreamClass getLocalDesc() {
- return localDesc;
- }
-
- /**
- * Returns arrays of ObjectStreamFields representing the serializable
- * fields of the represented class. If copy is true, a clone of this class
- * descriptor's field array is returned, otherwise the array itself is
- * returned.
- */
- ObjectStreamField[] getFields(boolean copy) {
- return copy ? fields.clone() : fields;
- }
-
- /**
- * Looks up a serializable field of the represented class by name and type.
- * A specified type of null matches all types, Object.class matches all
- * non-primitive types, and any other non-null type matches assignable
- * types only. Returns matching field, or null if no match found.
- */
- ObjectStreamField getField(String name, Class> type) {
- for (int i = 0; i < fields.length; i++) {
- ObjectStreamField f = fields[i];
- if (f.getName().equals(name)) {
- if (type == null ||
- (type == Object.class && !f.isPrimitive()))
- {
- return f;
- }
- Class> ftype = f.getType();
- if (ftype != null && type.isAssignableFrom(ftype)) {
- return f;
- }
- }
- }
- return null;
- }
-
- /**
- * Returns true if class descriptor represents a dynamic proxy class, false
- * otherwise.
- */
- boolean isProxy() {
- return isProxy;
- }
-
- /**
- * Returns true if class descriptor represents an enum type, false
- * otherwise.
- */
- boolean isEnum() {
- return isEnum;
- }
-
- /**
- * Returns true if represented class implements Externalizable, false
- * otherwise.
- */
- boolean isExternalizable() {
- return externalizable;
- }
-
- /**
- * Returns true if represented class implements Serializable, false
- * otherwise.
- */
- boolean isSerializable() {
- return serializable;
- }
-
- /**
- * Returns true if class descriptor represents externalizable class that
- * has written its data in 1.2 (block data) format, false otherwise.
- */
- boolean hasBlockExternalData() {
- return hasBlockExternalData;
- }
-
- /**
- * Returns true if class descriptor represents serializable (but not
- * externalizable) class which has written its data via a custom
- * writeObject() method, false otherwise.
- */
- boolean hasWriteObjectData() {
- return hasWriteObjectData;
- }
-
- /**
- * Returns true if represented class is serializable/externalizable and can
- * be instantiated by the serialization runtime--i.e., if it is
- * externalizable and defines a public no-arg constructor, or if it is
- * non-externalizable and its first non-serializable superclass defines an
- * accessible no-arg constructor. Otherwise, returns false.
- */
- boolean isInstantiable() {
- return (cons != null);
- }
-
- /**
- * Returns true if represented class is serializable (but not
- * externalizable) and defines a conformant writeObject method. Otherwise,
- * returns false.
- */
- boolean hasWriteObjectMethod() {
- return (writeObjectMethod != null);
- }
-
- /**
- * Returns true if represented class is serializable (but not
- * externalizable) and defines a conformant readObject method. Otherwise,
- * returns false.
- */
- boolean hasReadObjectMethod() {
- return (readObjectMethod != null);
- }
-
- /**
- * Returns true if represented class is serializable (but not
- * externalizable) and defines a conformant readObjectNoData method.
- * Otherwise, returns false.
- */
- boolean hasReadObjectNoDataMethod() {
- return (readObjectNoDataMethod != null);
- }
-
- /**
- * Returns true if represented class is serializable or externalizable and
- * defines a conformant writeReplace method. Otherwise, returns false.
- */
- boolean hasWriteReplaceMethod() {
- return (writeReplaceMethod != null);
- }
-
- /**
- * Returns true if represented class is serializable or externalizable and
- * defines a conformant readResolve method. Otherwise, returns false.
- */
- boolean hasReadResolveMethod() {
- return (readResolveMethod != null);
- }
-
- /**
- * Creates a new instance of the represented class. If the class is
- * externalizable, invokes its public no-arg constructor; otherwise, if the
- * class is serializable, invokes the no-arg constructor of the first
- * non-serializable superclass. Throws UnsupportedOperationException if
- * this class descriptor is not associated with a class, if the associated
- * class is non-serializable or if the appropriate no-arg constructor is
- * inaccessible/unavailable.
- */
- Object newInstance()
- throws InstantiationException, InvocationTargetException,
- UnsupportedOperationException
- {
- if (cons != null) {
- try {
- return cons.newInstance();
- } catch (IllegalAccessException ex) {
- // should not occur, as access checks have been suppressed
- throw new InternalError();
- }
- } else {
- throw new UnsupportedOperationException();
- }
- }
-
- /**
- * Invokes the writeObject method of the represented serializable class.
- * Throws UnsupportedOperationException if this class descriptor is not
- * associated with a class, or if the class is externalizable,
- * non-serializable or does not define writeObject.
- */
- void invokeWriteObject(Object obj, ObjectOutputStream out)
- throws IOException, UnsupportedOperationException
- {
- if (writeObjectMethod != null) {
- try {
- writeObjectMethod.invoke(obj, new Object[]{ out });
- } catch (InvocationTargetException ex) {
- Throwable th = ex.getTargetException();
- if (th instanceof IOException) {
- throw (IOException) th;
- } else {
- throwMiscException(th);
- }
- } catch (IllegalAccessException ex) {
- // should not occur, as access checks have been suppressed
- throw new InternalError();
- }
- } else {
- throw new UnsupportedOperationException();
- }
- }
-
- /**
- * Invokes the readObject method of the represented serializable class.
- * Throws UnsupportedOperationException if this class descriptor is not
- * associated with a class, or if the class is externalizable,
- * non-serializable or does not define readObject.
- */
- void invokeReadObject(Object obj, ObjectInputStream in)
- throws ClassNotFoundException, IOException,
- UnsupportedOperationException
- {
- if (readObjectMethod != null) {
- try {
- readObjectMethod.invoke(obj, new Object[]{ in });
- } catch (InvocationTargetException ex) {
- Throwable th = ex.getTargetException();
- if (th instanceof ClassNotFoundException) {
- throw (ClassNotFoundException) th;
- } else if (th instanceof IOException) {
- throw (IOException) th;
- } else {
- throwMiscException(th);
- }
- } catch (IllegalAccessException ex) {
- // should not occur, as access checks have been suppressed
- throw new InternalError();
- }
- } else {
- throw new UnsupportedOperationException();
- }
- }
-
- /**
- * Invokes the readObjectNoData method of the represented serializable
- * class. Throws UnsupportedOperationException if this class descriptor is
- * not associated with a class, or if the class is externalizable,
- * non-serializable or does not define readObjectNoData.
- */
- void invokeReadObjectNoData(Object obj)
- throws IOException, UnsupportedOperationException
- {
- if (readObjectNoDataMethod != null) {
- try {
- readObjectNoDataMethod.invoke(obj, (Object[]) null);
- } catch (InvocationTargetException ex) {
- Throwable th = ex.getTargetException();
- if (th instanceof ObjectStreamException) {
- throw (ObjectStreamException) th;
- } else {
- throwMiscException(th);
- }
- } catch (IllegalAccessException ex) {
- // should not occur, as access checks have been suppressed
- throw new InternalError();
- }
- } else {
- throw new UnsupportedOperationException();
- }
- }
-
- /**
- * Invokes the writeReplace method of the represented serializable class and
- * returns the result. Throws UnsupportedOperationException if this class
- * descriptor is not associated with a class, or if the class is
- * non-serializable or does not define writeReplace.
- */
- Object invokeWriteReplace(Object obj)
- throws IOException, UnsupportedOperationException
- {
- if (writeReplaceMethod != null) {
- try {
- return writeReplaceMethod.invoke(obj, (Object[]) null);
- } catch (InvocationTargetException ex) {
- Throwable th = ex.getTargetException();
- if (th instanceof ObjectStreamException) {
- throw (ObjectStreamException) th;
- } else {
- throwMiscException(th);
- throw new InternalError(); // never reached
- }
- } catch (IllegalAccessException ex) {
- // should not occur, as access checks have been suppressed
- throw new InternalError();
- }
- } else {
- throw new UnsupportedOperationException();
- }
- }
-
- /**
- * Invokes the readResolve method of the represented serializable class and
- * returns the result. Throws UnsupportedOperationException if this class
- * descriptor is not associated with a class, or if the class is
- * non-serializable or does not define readResolve.
- */
- Object invokeReadResolve(Object obj)
- throws IOException, UnsupportedOperationException
- {
- if (readResolveMethod != null) {
- try {
- return readResolveMethod.invoke(obj, (Object[]) null);
- } catch (InvocationTargetException ex) {
- Throwable th = ex.getTargetException();
- if (th instanceof ObjectStreamException) {
- throw (ObjectStreamException) th;
- } else {
- throwMiscException(th);
- throw new InternalError(); // never reached
- }
- } catch (IllegalAccessException ex) {
- // should not occur, as access checks have been suppressed
- throw new InternalError();
- }
- } else {
- throw new UnsupportedOperationException();
- }
- }
-
- /**
- * Class representing the portion of an object's serialized form allotted
- * to data described by a given class descriptor. If "hasData" is false,
- * the object's serialized form does not contain data associated with the
- * class descriptor.
- */
- static class ClassDataSlot {
-
- /** class descriptor "occupying" this slot */
- final ObjectStreamClass desc;
- /** true if serialized form includes data for this slot's descriptor */
- final boolean hasData;
-
- ClassDataSlot(ObjectStreamClass desc, boolean hasData) {
- this.desc = desc;
- this.hasData = hasData;
- }
- }
-
- /**
- * Returns array of ClassDataSlot instances representing the data layout
- * (including superclass data) for serialized objects described by this
- * class descriptor. ClassDataSlots are ordered by inheritance with those
- * containing "higher" superclasses appearing first. The final
- * ClassDataSlot contains a reference to this descriptor.
- */
- ClassDataSlot[] getClassDataLayout() throws InvalidClassException {
- // REMIND: synchronize instead of relying on volatile?
- if (dataLayout == null) {
- dataLayout = getClassDataLayout0();
- }
- return dataLayout;
- }
-
- private ClassDataSlot[] getClassDataLayout0()
- throws InvalidClassException
- {
- ArrayList