Start line:  
End line:  

Snippet Preview

Snippet HTML Code

Stack Overflow Questions
java.rmi.UnmarshalException: error unmarshalling arguments; nested exception is: java.lang.ClassCastException: java.io.ObjectStreamClass cannot be cast to java.lang.String at sun.rmi.transport.StreamRemoteCall.exceptionReceivedFromServer(StreamRemoteCall.java:255) at sun.rmi.transport.StreamRemoteCall.executeCall(StreamRemoteCall.java:233) at sun.rmi.server.UnicastRef.invoke(UnicastRef.java:359...
   /*
    * Copyright 1996-2006 Sun Microsystems, Inc.  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.  Sun designates this
    * particular file as subject to the "Classpath" exception as provided
    * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
   * CA 95054 USA or visit www.sun.com if you need additional information or
   * have any questions.
   */
  
  package java.io;
  
  import java.util.Arrays;
  import java.util.HashSet;
  import java.util.Set;
  import sun.misc.Unsafe;
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(s):
Mike Warres
Roger Riggs
Since:
JDK1.1
See also:
ObjectStreamField
Object Serialization Specification, Section 4, Class Descriptors
  
  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 =
          ;

    
reflection factory for obtaining serialization constructors
  
      private static final ReflectionFactory reflFactory = (ReflectionFactory)
          AccessController.doPrivileged(
              new ReflectionFactory.GetReflectionFactoryAction());
  
      private static class Caches {
        
cache mapping local classes -> descriptors
  
          static final ConcurrentMap<WeakClassKey,Reference<?>> localDescs =
              new ConcurrentHashMap<WeakClassKey,Reference<?>>();

        
cache mapping field group/local desc pairs -> field reflectors
  
          static final ConcurrentMap<FieldReflectorKey,Reference<?>> reflectors =
              new ConcurrentHashMap<FieldReflectorKey,Reference<?>>();

        
queue for WeakReferences to local classes
  
          private static final ReferenceQueue<Class<?>> localDescsQueue =
              new ReferenceQueue<Class<?>>();
        
queue for WeakReferences to field reflectors keys
  
          private static final ReferenceQueue<Class<?>> reflectorsQueue =
              new ReferenceQueue<Class<?>>();
      }

    
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.

Parameters:
cl class for which to get the descriptor
Returns:
the class descriptor for the specified class
 
     public static ObjectStreamClass lookup(Class<?> cl) {
         return lookup(clfalse);
     }

    
Returns the descriptor for any class, regardless of whether it implements Serializable.

Parameters:
cl class for which to get the descriptor
Returns:
the class descriptor for the specified class
Since:
1.6
 
     public static ObjectStreamClass lookupAny(Class<?> cl) {
         return lookup(cltrue);
     }

    
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 java.lang.Class.getName() method.

Returns:
a string representing the name of the class
 
     public String getName() {
         return ;
     }

    
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.

Returns:
the SUID of the class described by this descriptor
 
     public long getSerialVersionUID() {
         // REMIND: synchronize instead of relying on volatile?
         if ( == null) {
              = (Long) AccessController.doPrivileged(
                 new PrivilegedAction() {
                     public Object run() {
                         return Long.valueOf(computeDefaultSUID());
                     }
                 }
             );
         }
         return .longValue();
     }

    
Return the class in the local VM that this version is mapped to. Null is returned if there is no corresponding local class.

Returns:
the Class instance that this descriptor represents
 
     public Class<?> forClass() {
         return ;
     }

    
Return an array of the fields of this serializable class.

Returns:
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.

Parameters:
name the name of the data field to look for
Returns:
The ObjectStreamField object of the named field or null if there is no such named field.
 
     public ObjectStreamField getField(String name) {
         return getField(namenull);
     }

    
Return a string describing this ObjectStreamClass.
 
     public String toString() {
         return  + ": 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.

Parameters:
cl class to look up
all if true, return descriptors for all classes; if false, only return descriptors for serializable classes
 
     static ObjectStreamClass lookup(Class clboolean all) {
         if (!(all || Serializable.class.isAssignableFrom(cl))) {
             return null;
         }
         WeakClassKey key = new WeakClassKey(cl.);
         Reference<?> ref = ..get(key);
         Object entry = null;
         if (ref != null) {
             entry = ref.get();
         }
         EntryFuture future = null;
         if (entry == null) {
             EntryFuture newEntry = new EntryFuture();
             Reference<?> newRef = new SoftReference<EntryFuture>(newEntry);
             do {
                 if (ref != null) {
                     ..remove(keyref);
                 }
                 ref = ..putIfAbsent(keynewRef);
                 if (ref != null) {
                     entry = ref.get();
                 }
             } while (ref != null && entry == null);
             if (entry == null) {
                 future = newEntry;
             }
         }
 
         if (entry instanceof ObjectStreamClass) {  // check common case first
             return (ObjectStreamClassentry;
         }
         if (entry instanceof EntryFuture) {
             future = (EntryFutureentry;
             if (future.getOwner() == Thread.currentThread()) {
                 /*
                  * 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;
             }
             if (future.set(entry)) {
                 ..put(keynew SoftReference<Object>(entry));
             } else {
                 // nested lookup call already set future
                 entry = future.get();
             }
         }
 
         if (entry instanceof ObjectStreamClass) {
             return (ObjectStreamClassentry;
         } else if (entry instanceof RuntimeException) {
             throw (RuntimeExceptionentry;
         } else if (entry instanceof Error) {
             throw (Errorentry;
         } 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 final Thread owner = Thread.currentThread();
         private Object entry = ;

        
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. != ) {
                 return false;
             }
             this. = 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 ( == ) {
                 try {
                     wait();
                 } catch (InterruptedException ex) {
                     interrupted = true;
                 }
             }
             if (interrupted) {
                 AccessController.doPrivileged(
                     new PrivilegedAction() {
                         public Object run() {
                             Thread.currentThread().interrupt();
                             return null;
                         }
                     }
                 );
             }
             return ;
         }

        
Returns the thread that created this EntryFuture.
 
         Thread getOwner() {
             return ;
         }
     }

    
Creates local class descriptor representing given class.
 
     private ObjectStreamClass(final Class cl) {
         this. = cl;
          = cl.getName();
          = Proxy.isProxyClass(cl);
          = Enum.class.isAssignableFrom(cl);
          = Serializable.class.isAssignableFrom(cl);
          = Externalizable.class.isAssignableFrom(cl);
 
         Class superCl = cl.getSuperclass();
          = (superCl != null) ? lookup(superClfalse) : null;
          = this;
 
         if () {
             AccessController.doPrivileged(new PrivilegedAction() {
                 public Object run() {
                     if () {
                          = Long.valueOf(0);
                          = ;
                         return null;
                     }
                     if (cl.isArray()) {
                          = ;
                         return null;
                     }
 
                      = getDeclaredSUID(cl);
                     try {
                          = getSerialFields(cl);
                         computeFieldOffsets();
                     } catch (InvalidClassException e) {
                          =  = e;
                          = ;
                     }
 
                     if () {
                          = getExternalizableConstructor(cl);
                     } else {
                          = getSerializableConstructor(cl);
                          = getPrivateMethod(cl"writeObject",
                             new Class[] { ObjectOutputStream.class },
                             .);
                          = getPrivateMethod(cl"readObject",
                             new Class[] { ObjectInputStream.class },
                             .);
                          = getPrivateMethod(
                             cl"readObjectNoData"null.);
                          = ( != null);
                     }
                      = getInheritableMethod(
                         cl"writeReplace"nullObject.class);
                      = getInheritableMethod(
                         cl"readResolve"nullObject.class);
                     return null;
                 }
             });
         } else {
              = Long.valueOf(0);
              = ;
         }
 
         try {
              = getReflector(this);
         } catch (InvalidClassException ex) {
             // field mismatches impossible when matching local fields vs. self
             throw new InternalError();
         }
 
         if ( == null) {
             if () {
                  = new InvalidClassException("enum type");
             } else if ( == null) {
                  = new InvalidClassException(
                     "no valid constructor");
             }
         }
         for (int i = 0; i < .i++) {
             if ([i].getField() == null) {
                  = new InvalidClassException(
                     "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;
         this. = resolveEx;
         this. = superDesc;
          = true;
          = true;
          = Long.valueOf(0);
          = ;
 
         if (cl != null) {
              = lookup(cltrue);
             if (!.) {
                 throw new InvalidClassException(
                     "cannot bind proxy descriptor to a non-proxy class");
             }
              = .;
              = .;
              = .;
              = .;
              = .;
              = .;
         }
          = getReflector();
     }

    
Initializes class descriptor representing a non-proxy class.
 
     void initNonProxy(ObjectStreamClass model,
                       Class cl,
                       ClassNotFoundException resolveEx,
                       ObjectStreamClass superDesc)
         throws InvalidClassException
     {
         this. = cl;
         this. = resolveEx;
         this. = superDesc;
          = model.name;
          = Long.valueOf(model.getSerialVersionUID());
          = false;
          = model.isEnum;
          = model.serializable;
          = model.externalizable;
          = model.hasBlockExternalData;
          = model.hasWriteObjectData;
          = model.fields;
          = model.primDataSize;
          = model.numObjFields;
 
         if (cl != null) {
              = lookup(cltrue);
             if (.) {
                 throw new InvalidClassException(
                     "cannot bind non-proxy descriptor to a proxy class");
             }
             if ( != .) {
                 throw new InvalidClassException( ?
                     "cannot bind enum descriptor to a non-enum class" :
                     "cannot bind non-enum descriptor to an enum class");
             }
 
             if ( == . &&
                 !cl.isArray() &&
                 .longValue() != .getSerialVersionUID())
             {
                 throw new InvalidClassException(.,
                     "local class incompatible: " +
                     "stream classdesc serialVersionUID = " +  +
                     ", local class serialVersionUID = " +
                     .getSerialVersionUID());
             }
 
             if (!classNamesEqual(.)) {
                 throw new InvalidClassException(.,
                     "local class name incompatible with stream class " +
                     "name \"" +  + "\"");
             }
 
             if (!) {
                 if (( == .) &&
                     ( != .))
                 {
                     throw new InvalidClassException(.,
                         "Serializable incompatible with Externalizable");
                 }
 
                 if (( != .) ||
                     ( != .) ||
                     !( || ))
                 {
                      = new InvalidClassException(.,
                         "class invalid for deserialization");
                 }
             }
 
              = .;
              = .;
              = .;
              = .;
              = .;
             if ( == null) {
                  = .;
             }
         }
          = getReflector();
         // reassign to matched fields so as to reflect local unshared settings
          = .getFields();
     }

    
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 IOExceptionClassNotFoundException
     {
          = in.readUTF();
          = Long.valueOf(in.readLong());
          = false;
 
         byte flags = in.readByte();
          =
             ((flags & .) != 0);
          =
             ((flags & .) != 0);
          =
             ((flags & .) != 0);
         boolean sflag =
             ((flags & .) != 0);
         if ( && sflag) {
             throw new InvalidClassException(
                 "serializable and externalizable flags conflict");
         }
          =  || sflag;
          = ((flags & .) != 0);
         if ( && .longValue() != 0L) {
             throw new InvalidClassException(,
                 "enum descriptor has non-zero serialVersionUID: " + );
         }
 
         int numFields = in.readShort();
         if ( && numFields != 0) {
             throw new InvalidClassException(,
                 "enum descriptor has non-zero field count: " + numFields);
         }
          = (numFields > 0) ?
             new ObjectStreamField[numFields] : ;
         for (int i = 0; i < numFieldsi++) {
             char tcode = (charin.readByte();
             String fname = in.readUTF();
             String signature = ((tcode == 'L') || (tcode == '[')) ?
                 in.readTypeString() : new String(new char[] { tcode });
             try {
                 [i] = new ObjectStreamField(fnamesignaturefalse);
             } catch (RuntimeException e) {
                 throw (IOExceptionnew InvalidClassException(,
                     "invalid descriptor for field " + fname).initCause(e);
             }
         }
         computeFieldOffsets();
     }

    
Writes non-proxy class descriptor information to given output stream.
 
     void writeNonProxy(ObjectOutputStream outthrows IOException {
         out.writeUTF();
         out.writeLong(getSerialVersionUID());
 
         byte flags = 0;
         if () {
             flags |= .;
             int protocol = out.getProtocolVersion();
             if (protocol != .) {
                 flags |= .;
             }
         } else if () {
             flags |= .;
         }
         if () {
             flags |= .;
         }
         if () {
             flags |= .;
         }
         out.writeByte(flags);
 
         out.writeShort(.);
         for (int i = 0; i < .i++) {
             ObjectStreamField f = [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.
 
         return ;
     }

    
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 ( != null) {
             InvalidClassException ice =
                 new InvalidClassException(.,
                                           .getMessage());
             ice.initCause();
             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 ( != null) {
             InvalidClassException ice =
                 new InvalidClassException(.,
                                           .getMessage());
             ice.initCause();
             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 ( != null) {
             InvalidClassException ice =
                 new InvalidClassException(.,
                                           .getMessage());
             ice.initCause();
             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.
 
         return ;
     }

    
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.
 
         return ;
     }

    
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 ? .clone() : ;
     }

    
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 nameClass type) {
         for (int i = 0; i < .i++) {
             ObjectStreamField f = [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 ;
     }

    
Returns true if class descriptor represents an enum type, false otherwise.
 
     boolean isEnum() {
         return ;
     }

    
Returns true if represented class implements Externalizable, false otherwise.
 
     boolean isExternalizable() {
         return ;
     }

    
Returns true if represented class implements Serializable, false otherwise.
 
     boolean isSerializable() {
         return ;
     }

    
Returns true if class descriptor represents externalizable class that has written its data in 1.2 (block data) format, false otherwise.
 
     boolean hasBlockExternalData() {
         return ;
     }

    
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 ;
     }

    
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 ( != null);
     }

    
Returns true if represented class is serializable (but not externalizable) and defines a conformant writeObject method. Otherwise, returns false.
 
     boolean hasWriteObjectMethod() {
         return ( != null);
     }

    
Returns true if represented class is serializable (but not externalizable) and defines a conformant readObject method. Otherwise, returns false.
 
     boolean hasReadObjectMethod() {
         return ( != null);
     }

    
Returns true if represented class is serializable (but not externalizable) and defines a conformant readObjectNoData method. Otherwise, returns false.
 
     boolean hasReadObjectNoDataMethod() {
         return ( != null);
     }

    
Returns true if represented class is serializable or externalizable and defines a conformant writeReplace method. Otherwise, returns false.
 
     boolean hasWriteReplaceMethod() {
         return ( != null);
     }

    
Returns true if represented class is serializable or externalizable and defines a conformant readResolve method. Otherwise, returns false.
 
     boolean hasReadResolveMethod() {
         return ( != 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()
                UnsupportedOperationException
     {
         if ( != null) {
             try {
                 return .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 objObjectOutputStream out)
         throws IOExceptionUnsupportedOperationException
     {
         if ( != null) {
             try {
                 .invoke(objnew Object[]{ out });
             } catch (InvocationTargetException ex) {
                 Throwable th = ex.getTargetException();
                 if (th instanceof IOException) {
                     throw (IOExceptionth;
                 } 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 objObjectInputStream in)
         throws ClassNotFoundExceptionIOException,
                UnsupportedOperationException
     {
         if ( != null) {
             try {
                 .invoke(objnew Object[]{ in });
             } catch (InvocationTargetException ex) {
                 Throwable th = ex.getTargetException();
                 if (th instanceof ClassNotFoundException) {
                     throw (ClassNotFoundExceptionth;
                 } else if (th instanceof IOException) {
                     throw (IOExceptionth;
                 } 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.
    {
        if ( != null) {
            try {
                .invoke(obj, (Object[]) null);
            } catch (InvocationTargetException ex) {
                Throwable th = ex.getTargetException();
                if (th instanceof ObjectStreamException) {
                    throw (ObjectStreamExceptionth;
                } 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.
    {
        if ( != null) {
            try {
                return .invoke(obj, (Object[]) null);
            } catch (InvocationTargetException ex) {
                Throwable th = ex.getTargetException();
                if (th instanceof ObjectStreamException) {
                    throw (ObjectStreamExceptionth;
                } 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.
    {
        if ( != null) {
            try {
                return .invoke(obj, (Object[]) null);
            } catch (InvocationTargetException ex) {
                Throwable th = ex.getTargetException();
                if (th instanceof ObjectStreamException) {
                    throw (ObjectStreamExceptionth;
                } 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 descboolean hasData) {
            this. = desc;
            this. = 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.
        // REMIND: synchronize instead of relying on volatile?
        if ( == null) {
             = getClassDataLayout0();
        }
        return ;
    }
        throws InvalidClassException
    {
        ArrayList slots = new ArrayList();
        Class start = end = ;
        // locate closest non-serializable superclass
        while (end != null && Serializable.class.isAssignableFrom(end)) {
            end = end.getSuperclass();
        }
        for (ObjectStreamClass d = thisd != nulld = d.superDesc) {
            // search up inheritance hierarchy for class with matching name
            String searchName = (d.cl != null) ? d.cl.getName() : d.name;
            Class match = null;
            for (Class c = startc != endc = c.getSuperclass()) {
                if (searchName.equals(c.getName())) {
                    match = c;
                    break;
                }
            }
            // add "no data" slot for each unmatched class below match
            if (match != null) {
                for (Class c = startc != matchc = c.getSuperclass()) {
                    slots.add(new ClassDataSlot(
                        ObjectStreamClass.lookup(ctrue), false));
                }
                start = match.getSuperclass();
            }
            // record descriptor/class pairing
            slots.add(new ClassDataSlot(d.getVariantFor(match), true));
        }
        // add "no data" slot for any leftover unmatched classes
        for (Class c = startc != endc = c.getSuperclass()) {
            slots.add(new ClassDataSlot(
                ObjectStreamClass.lookup(ctrue), false));
        }
        // order slots from superclass -> subclass
        Collections.reverse(slots);
        return (ClassDataSlot[])
            slots.toArray(new ClassDataSlot[slots.size()]);
    }

    
Returns aggregate size (in bytes) of marshalled primitive field values for represented class.
    int getPrimDataSize() {
        return ;
    }

    
Returns number of non-primitive serializable fields of represented class.
    int getNumObjFields() {
        return ;
    }

    
Fetches the serializable primitive field values of object obj and marshals them into byte array buf starting at offset 0. It is the responsibility of the caller to ensure that obj is of the proper type if non-null.
    void getPrimFieldValues(Object objbyte[] buf) {
        .getPrimFieldValues(objbuf);
    }

    
Sets the serializable primitive fields of object obj using values unmarshalled from byte array buf starting at offset 0. It is the responsibility of the caller to ensure that obj is of the proper type if non-null.
    void setPrimFieldValues(Object objbyte[] buf) {
        .setPrimFieldValues(objbuf);
    }

    
Fetches the serializable object field values of object obj and stores them in array vals starting at offset 0. It is the responsibility of the caller to ensure that obj is of the proper type if non-null.
    void getObjFieldValues(Object objObject[] vals) {
        .getObjFieldValues(objvals);
    }

    
Sets the serializable object fields of object obj using values from array vals starting at offset 0. It is the responsibility of the caller to ensure that obj is of the proper type if non-null.
    void setObjFieldValues(Object objObject[] vals) {
        .setObjFieldValues(objvals);
    }

    
Calculates and sets serializable field offsets, as well as primitive data size and object field count totals. Throws InvalidClassException if fields are illegally ordered.
    private void computeFieldOffsets() throws InvalidClassException {
         = 0;
         = 0;
        int firstObjIndex = -1;
        for (int i = 0; i < .i++) {
            ObjectStreamField f = [i];
            switch (f.getTypeCode()) {
                case 'Z':
                case 'B':
                    f.setOffset(++);
                    break;
                case 'C':
                case 'S':
                    f.setOffset();
                     += 2;
                    break;
                case 'I':
                case 'F':
                    f.setOffset();
                     += 4;
                    break;
                case 'J':
                case 'D':
                    f.setOffset();
                     += 8;
                    break;
                case '[':
                case 'L':
                    f.setOffset(++);
                    if (firstObjIndex == -1) {
                        firstObjIndex = i;
                    }
                    break;
                default:
                    throw new InternalError();
            }
        }
        if (firstObjIndex != -1 &&
            firstObjIndex +  != .)
        {
            throw new InvalidClassException("illegal field order");
        }
    }

    
If given class is the same as the class associated with this class descriptor, returns reference to this class descriptor. Otherwise, returns variant of this class descriptor bound to given class.
        throws InvalidClassException
    {
        if (this. == cl) {
            return this;
        }
        ObjectStreamClass desc = new ObjectStreamClass();
        if () {
            desc.initProxy(clnull);
        } else {
            desc.initNonProxy(thisclnull);
        }
        return desc;
    }

    
Returns public no-arg constructor of given class, or null if none found. Access checks are disabled on the returned constructor (if any), since the defining class may still be non-public.
    private static Constructor getExternalizableConstructor(Class cl) {
        try {
            Constructor cons = cl.getDeclaredConstructor((Class[]) null);
            cons.setAccessible(true);
            return ((cons.getModifiers() & .) != 0) ?
                cons : null;
        } catch (NoSuchMethodException ex) {
            return null;
        }
    }

    
Returns subclass-accessible no-arg constructor of first non-serializable superclass, or null if none found. Access checks are disabled on the returned constructor (if any).
    private static Constructor getSerializableConstructor(Class cl) {
        Class initCl = cl;
        while (Serializable.class.isAssignableFrom(initCl)) {
            if ((initCl = initCl.getSuperclass()) == null) {
                return null;
            }
        }
        try {
            Constructor cons = initCl.getDeclaredConstructor((Class[]) null);
            int mods = cons.getModifiers();
            if ((mods & .) != 0 ||
                ((mods & (. | .)) == 0 &&
                 !packageEquals(clinitCl)))
            {
                return null;
            }
            cons = .newConstructorForSerialization(clcons);
            cons.setAccessible(true);
            return cons;
        } catch (NoSuchMethodException ex) {
            return null;
        }
    }

    
Returns non-static, non-abstract method with given signature provided it is defined by or accessible (via inheritance) by the given class, or null if no match found. Access checks are disabled on the returned method (if any).
    private static Method getInheritableMethod(Class clString name,
                                               Class[] argTypes,
                                               Class returnType)
    {
        Method meth = null;
        Class defCl = cl;
        while (defCl != null) {
            try {
                meth = defCl.getDeclaredMethod(nameargTypes);
                break;
            } catch (NoSuchMethodException ex) {
                defCl = defCl.getSuperclass();
            }
        }
        if ((meth == null) || (meth.getReturnType() != returnType)) {
            return null;
        }
        meth.setAccessible(true);
        int mods = meth.getModifiers();
        if ((mods & (. | .)) != 0) {
            return null;
        } else if ((mods & (. | .)) != 0) {
            return meth;
        } else if ((mods & .) != 0) {
            return (cl == defCl) ? meth : null;
        } else {
            return packageEquals(cldefCl) ? meth : null;
        }
    }

    
Returns non-static private method with given signature defined by given class, or null if none found. Access checks are disabled on the returned method (if any).
    private static Method getPrivateMethod(Class clString name,
                                           Class[] argTypes,
                                           Class returnType)
    {
        try {
            Method meth = cl.getDeclaredMethod(nameargTypes);
            meth.setAccessible(true);
            int mods = meth.getModifiers();
            return ((meth.getReturnType() == returnType) &&
                    ((mods & .) == 0) &&
                    ((mods & .) != 0)) ? meth : null;
        } catch (NoSuchMethodException ex) {
            return null;
        }
    }

    
Returns true if classes are defined in the same runtime package, false otherwise.
    private static boolean packageEquals(Class cl1Class cl2) {
        return (cl1.getClassLoader() == cl2.getClassLoader() &&
                getPackageName(cl1).equals(getPackageName(cl2)));
    }

    
Returns package name of given class.
    private static String getPackageName(Class cl) {
        String s = cl.getName();
        int i = s.lastIndexOf('[');
        if (i >= 0) {
            s = s.substring(i + 2);
        }
        i = s.lastIndexOf('.');
        return (i >= 0) ? s.substring(0, i) : "";
    }

    
Compares class names for equality, ignoring package names. Returns true if class names equal, false otherwise.
    private static boolean classNamesEqual(String name1String name2) {
        name1 = name1.substring(name1.lastIndexOf('.') + 1);
        name2 = name2.substring(name2.lastIndexOf('.') + 1);
        return name1.equals(name2);
    }

    
Returns JVM type signature for given class.
    static String getClassSignature(Class cl) {
        StringBuilder sbuf = new StringBuilder();
        while (cl.isArray()) {
            sbuf.append('[');
            cl = cl.getComponentType();
        }
        if (cl.isPrimitive()) {
            if (cl == .) {
                sbuf.append('I');
            } else if (cl == .) {
                sbuf.append('B');
            } else if (cl == .) {
                sbuf.append('J');
            } else if (cl == .) {
                sbuf.append('F');
            } else if (cl == .) {
                sbuf.append('D');
            } else if (cl == .) {
                sbuf.append('S');
            } else if (cl == .) {
                sbuf.append('C');
            } else if (cl == .) {
                sbuf.append('Z');
            } else if (cl == .) {
                sbuf.append('V');
            } else {
                throw new InternalError();
            }
        } else {
            sbuf.append('L' + cl.getName().replace('.''/') + ';');
        }
        return sbuf.toString();
    }

    
Returns JVM type signature for given list of parameters and return type.
    private static String getMethodSignature(Class[] paramTypes,
                                             Class retType)
    {
        StringBuilder sbuf = new StringBuilder();
        sbuf.append('(');
        for (int i = 0; i < paramTypes.lengthi++) {
            sbuf.append(getClassSignature(paramTypes[i]));
        }
        sbuf.append(')');
        sbuf.append(getClassSignature(retType));
        return sbuf.toString();
    }

    
Convenience method for throwing an exception that is either a RuntimeException, Error, or of some unexpected type (in which case it is wrapped inside an IOException).
    private static void throwMiscException(Throwable ththrows IOException {
        if (th instanceof RuntimeException) {
            throw (RuntimeExceptionth;
        } else if (th instanceof Error) {
            throw (Errorth;
        } else {
            IOException ex = new IOException("unexpected exception type");
            ex.initCause(th);
            throw ex;
        }
    }

    
Returns ObjectStreamField array describing the serializable fields of the given class. Serializable fields backed by an actual field of the class are represented by ObjectStreamFields with corresponding non-null Field objects. Throws InvalidClassException if the (explicitly declared) serializable fields are invalid.
    private static ObjectStreamField[] getSerialFields(Class cl)
        throws InvalidClassException
    {
        ObjectStreamField[] fields;
        if (Serializable.class.isAssignableFrom(cl) &&
            !Externalizable.class.isAssignableFrom(cl) &&
            !Proxy.isProxyClass(cl) &&
            !cl.isInterface())
        {
            if ((fields = getDeclaredSerialFields(cl)) == null) {
                fields = getDefaultSerialFields(cl);
            }
            Arrays.sort(fields);
        } else {
            fields = ;
        }
        return fields;
    }

    
Returns serializable fields of given class as defined explicitly by a "serialPersistentFields" field, or null if no appropriate "serialPersistentFields" field is defined. Serializable fields backed by an actual field of the class are represented by ObjectStreamFields with corresponding non-null Field objects. For compatibility with past releases, a "serialPersistentFields" field with a null value is considered equivalent to not declaring "serialPersistentFields". Throws InvalidClassException if the declared serializable fields are invalid--e.g., if multiple fields share the same name.
    private static ObjectStreamField[] getDeclaredSerialFields(Class cl)
        throws InvalidClassException
    {
        ObjectStreamField[] serialPersistentFields = null;
        try {
            Field f = cl.getDeclaredField("serialPersistentFields");
            int mask = . | . | .;
            if ((f.getModifiers() & mask) == mask) {
                f.setAccessible(true);
                serialPersistentFields = (ObjectStreamField[]) f.get(null);
            }
        } catch (Exception ex) {
        }
        if (serialPersistentFields == null) {
            return null;
        } else if (serialPersistentFields.length == 0) {
            return ;
        }
        ObjectStreamField[] boundFields =
            new ObjectStreamField[serialPersistentFields.length];
        Set fieldNames = new HashSet(serialPersistentFields.length);
        for (int i = 0; i < serialPersistentFields.lengthi++) {
            ObjectStreamField spf = serialPersistentFields[i];
            String fname = spf.getName();
            if (fieldNames.contains(fname)) {
                throw new InvalidClassException(
                    "multiple serializable fields named " + fname);
            }
            fieldNames.add(fname);
            try {
                Field f = cl.getDeclaredField(fname);
                if ((f.getType() == spf.getType()) &&
                    ((f.getModifiers() & .) == 0))
                {
                    boundFields[i] =
                        new ObjectStreamField(fspf.isUnshared(), true);
                }
            } catch (NoSuchFieldException ex) {
            }
            if (boundFields[i] == null) {
                boundFields[i] = new ObjectStreamField(
                    fnamespf.getType(), spf.isUnshared());
            }
        }
        return boundFields;
    }

    
Returns array of ObjectStreamFields corresponding to all non-static non-transient fields declared by given class. Each ObjectStreamField contains a Field object for the field it represents. If no default serializable fields exist, NO_FIELDS is returned.
    private static ObjectStreamField[] getDefaultSerialFields(Class cl) {
        Field[] clFields = cl.getDeclaredFields();
        ArrayList list = new ArrayList();
        int mask = . | .;
        for (int i = 0; i < clFields.lengthi++) {
            if ((clFields[i].getModifiers() & mask) == 0) {
                list.add(new ObjectStreamField(clFields[i], falsetrue));
            }
        }
        int size = list.size();
        return (size == 0) ?  :
            (ObjectStreamField[]) list.toArray(new ObjectStreamField[size]);
    }

    
Returns explicit serial version UID value declared by given class, or null if none.
    private static Long getDeclaredSUID(Class cl) {
        try {
            Field f = cl.getDeclaredField("serialVersionUID");
            int mask = . | .;
            if ((f.getModifiers() & mask) == mask) {
                f.setAccessible(true);
                return Long.valueOf(f.getLong(null));
            }
        } catch (Exception ex) {
        }
        return null;
    }

    
Computes the default serial version UID value for the given class.
    private static long computeDefaultSUID(Class cl) {
        if (!Serializable.class.isAssignableFrom(cl) || Proxy.isProxyClass(cl))
        {
            return 0L;
        }
        try {
            ByteArrayOutputStream bout = new ByteArrayOutputStream();
            DataOutputStream dout = new DataOutputStream(bout);
            dout.writeUTF(cl.getName());
            int classMods = cl.getModifiers() &
                (. | . |
                 . | .);
            /*
             * compensate for javac bug in which ABSTRACT bit was set for an
             * interface only if the interface declared methods
             */
            Method[] methods = cl.getDeclaredMethods();
            if ((classMods & .) != 0) {
                classMods = (methods.length > 0) ?
                    (classMods | .) :
                    (classMods & ~.);
            }
            dout.writeInt(classMods);
            if (!cl.isArray()) {
                /*
                 * compensate for change in 1.2FCS in which
                 * Class.getInterfaces() was modified to return Cloneable and
                 * Serializable for array classes.
                 */
                Class[] interfaces = cl.getInterfaces();
                String[] ifaceNames = new String[interfaces.length];
                for (int i = 0; i < interfaces.lengthi++) {
                    ifaceNames[i] = interfaces[i].getName();
                }
                Arrays.sort(ifaceNames);
                for (int i = 0; i < ifaceNames.lengthi++) {
                    dout.writeUTF(ifaceNames[i]);
                }
            }
            Field[] fields = cl.getDeclaredFields();
            MemberSignature[] fieldSigs = new MemberSignature[fields.length];
            for (int i = 0; i < fields.lengthi++) {
                fieldSigs[i] = new MemberSignature(fields[i]);
            }
            Arrays.sort(fieldSigsnew Comparator() {
                public int compare(Object o1Object o2) {
                    String name1 = ((MemberSignatureo1).;
                    String name2 = ((MemberSignatureo2).;
                    return name1.compareTo(name2);
                }
            });
            for (int i = 0; i < fieldSigs.lengthi++) {
                MemberSignature sig = fieldSigs[i];
                int mods = sig.member.getModifiers() &
                    (. | . | . |
                     . | . | . |
                     .);
                if (((mods & .) == 0) ||
                    ((mods & (. | .)) == 0))
                {
                    dout.writeUTF(sig.name);
                    dout.writeInt(mods);
                    dout.writeUTF(sig.signature);
                }
            }
            if (hasStaticInitializer(cl)) {
                dout.writeUTF("<clinit>");
                dout.writeInt(.);
                dout.writeUTF("()V");
            }
            Constructor[] cons = cl.getDeclaredConstructors();
            MemberSignature[] consSigs = new MemberSignature[cons.length];
            for (int i = 0; i < cons.lengthi++) {
                consSigs[i] = new MemberSignature(cons[i]);
            }
            Arrays.sort(consSigsnew Comparator() {
                public int compare(Object o1Object o2) {
                    String sig1 = ((MemberSignatureo1).;
                    String sig2 = ((MemberSignatureo2).;
                    return sig1.compareTo(sig2);
                }
            });
            for (int i = 0; i < consSigs.lengthi++) {
                MemberSignature sig = consSigs[i];
                int mods = sig.member.getModifiers() &
                    (. | . | . |
                     . | . |
                     . | . |
                     . | .);
                if ((mods & .) == 0) {
                    dout.writeUTF("<init>");
                    dout.writeInt(mods);
                    dout.writeUTF(sig.signature.replace('/''.'));
                }
            }
            MemberSignature[] methSigs = new MemberSignature[methods.length];
            for (int i = 0; i < methods.lengthi++) {
                methSigs[i] = new MemberSignature(methods[i]);
            }
            Arrays.sort(methSigsnew Comparator() {
                public int compare(Object o1Object o2) {
                    MemberSignature ms1 = (MemberSignatureo1;
                    MemberSignature ms2 = (MemberSignatureo2;
                    int comp = ms1.name.compareTo(ms2.name);
                    if (comp == 0) {
                        comp = ms1.signature.compareTo(ms2.signature);
                    }
                    return comp;
                }
            });
            for (int i = 0; i < methSigs.lengthi++) {
                MemberSignature sig = methSigs[i];
                int mods = sig.member.getModifiers() &
                    (. | . | . |
                     . | . |
                     . | . |
                     . | .);
                if ((mods & .) == 0) {
                    dout.writeUTF(sig.name);
                    dout.writeInt(mods);
                    dout.writeUTF(sig.signature.replace('/''.'));
                }
            }
            dout.flush();
            MessageDigest md = MessageDigest.getInstance("SHA");
            byte[] hashBytes = md.digest(bout.toByteArray());
            long hash = 0;
            for (int i = Math.min(hashBytes.length, 8) - 1; i >= 0; i--) {
                hash = (hash << 8) | (hashBytes[i] & 0xFF);
            }
            return hash;
        } catch (IOException ex) {
            throw new InternalError();
        } catch (NoSuchAlgorithmException ex) {
            throw new SecurityException(ex.getMessage());
        }
    }

    
Returns true if the given class defines a static initializer method, false otherwise.
    private native static boolean hasStaticInitializer(Class cl);

    
Class for computing and caching field/constructor/method signatures during serialVersionUID calculation.
    private static class MemberSignature {
        public final Member member;
        public final String name;
        public final String signature;
        public MemberSignature(Field field) {
             = field;
             = field.getName();
             = getClassSignature(field.getType());
        }
        public MemberSignature(Constructor cons) {
             = cons;
             = cons.getName();
             = getMethodSignature(
                cons.getParameterTypes(), .);
        }
        public MemberSignature(Method meth) {
             = meth;
             = meth.getName();
             = getMethodSignature(
                meth.getParameterTypes(), meth.getReturnType());
        }
    }

    
Class for setting and retrieving serializable field values in batch.
    // REMIND: dynamically generate these?
    private static class FieldReflector {

        
handle for performing unsafe operations
        private static final Unsafe unsafe = Unsafe.getUnsafe();

        
fields to operate on
        private final ObjectStreamField[] fields;
        
number of primitive fields
        private final int numPrimFields;
        
unsafe field keys
        private final long[] keys;
        
field data offsets
        private final int[] offsets;
        
field type codes
        private final char[] typeCodes;
        
field types
        private final Class[] types;

        
Constructs FieldReflector capable of setting/getting values from the subset of fields whose ObjectStreamFields contain non-null reflective Field objects. ObjectStreamFields with null Fields are treated as filler, for which get operations return default values and set operations discard given values.
        FieldReflector(ObjectStreamField[] fields) {
            this. = fields;
            int nfields = fields.length;
             = new long[nfields];
             = new int[nfields];
             = new char[nfields];
            ArrayList typeList = new ArrayList();
            for (int i = 0; i < nfieldsi++) {
                ObjectStreamField f = fields[i];
                Field rf = f.getField();
                [i] = (rf != null) ?
                    .objectFieldOffset(rf) : .;
                [i] = f.getOffset();
                [i] = f.getTypeCode();
                if (!f.isPrimitive()) {
                    typeList.add((rf != null) ? rf.getType() : null);
                }
            }
             = (Class[]) typeList.toArray(new Class[typeList.size()]);
             = nfields - .;
        }

        
Returns list of ObjectStreamFields representing fields operated on by this reflector. The shared/unshared values and Field objects contained by ObjectStreamFields in the list reflect their bindings to locally defined serializable fields.
        ObjectStreamField[] getFields() {
            return ;
        }

        
Fetches the serializable primitive field values of object obj and marshals them into byte array buf starting at offset 0. The caller is responsible for ensuring that obj is of the proper type.
        void getPrimFieldValues(Object objbyte[] buf) {
            if (obj == null) {
                throw new NullPointerException();
            }
            /* assuming checkDefaultSerialize() has been called on the class
             * descriptor this FieldReflector was obtained from, no field keys
             * in array should be equal to Unsafe.INVALID_FIELD_OFFSET.
             */
            for (int i = 0; i < i++) {
                long key = [i];
                int off = [i];
                switch ([i]) {
                    case 'Z':
                        Bits.putBoolean(bufoff.getBoolean(objkey));
                        break;
                    case 'B':
                        buf[off] = .getByte(objkey);
                        break;
                    case 'C':
                        Bits.putChar(bufoff.getChar(objkey));
                        break;
                    case 'S':
                        Bits.putShort(bufoff.getShort(objkey));
                        break;
                    case 'I':
                        Bits.putInt(bufoff.getInt(objkey));
                        break;
                    case 'F':
                        Bits.putFloat(bufoff.getFloat(objkey));
                        break;
                    case 'J':
                        Bits.putLong(bufoff.getLong(objkey));
                        break;
                    case 'D':
                        Bits.putDouble(bufoff.getDouble(objkey));
                        break;
                    default:
                        throw new InternalError();
                }
            }
        }

        
Sets the serializable primitive fields of object obj using values unmarshalled from byte array buf starting at offset 0. The caller is responsible for ensuring that obj is of the proper type.
        void setPrimFieldValues(Object objbyte[] buf) {
            if (obj == null) {
                throw new NullPointerException();
            }
            for (int i = 0; i < i++) {
                long key = [i];
                if (key == .) {
                    continue;           // discard value
                }
                int off = [i];
                switch ([i]) {
                    case 'Z':
                        .putBoolean(objkey, Bits.getBoolean(bufoff));
                        break;
                    case 'B':
                        .putByte(objkeybuf[off]);
                        break;
                    case 'C':
                        .putChar(objkey, Bits.getChar(bufoff));
                        break;
                    case 'S':
                        .putShort(objkey, Bits.getShort(bufoff));
                        break;
                    case 'I':
                        .putInt(objkey, Bits.getInt(bufoff));
                        break;
                    case 'F':
                        .putFloat(objkey, Bits.getFloat(bufoff));
                        break;
                    case 'J':
                        .putLong(objkey, Bits.getLong(bufoff));
                        break;
                    case 'D':
                        .putDouble(objkey, Bits.getDouble(bufoff));
                        break;
                    default:
                        throw new InternalError();
                }
            }
        }

        
Fetches the serializable object field values of object obj and stores them in array vals starting at offset 0. The caller is responsible for ensuring that obj is of the proper type.
        void getObjFieldValues(Object objObject[] vals) {
            if (obj == null) {
                throw new NullPointerException();
            }
            /* assuming checkDefaultSerialize() has been called on the class
             * descriptor this FieldReflector was obtained from, no field keys
             * in array should be equal to Unsafe.INVALID_FIELD_OFFSET.
             */
            for (int i = i < .i++) {
                switch ([i]) {
                    case 'L':
                    case '[':
                        vals[[i]] = .getObject(obj[i]);
                        break;
                    default:
                        throw new InternalError();
                }
            }
        }

        
Sets the serializable object fields of object obj using values from array vals starting at offset 0. The caller is responsible for ensuring that obj is of the proper type; however, attempts to set a field with a value of the wrong type will trigger an appropriate ClassCastException.
        void setObjFieldValues(Object objObject[] vals) {
            if (obj == null) {
                throw new NullPointerException();
            }
            for (int i = i < .i++) {
                long key = [i];
                if (key == .) {
                    continue;           // discard value
                }
                switch ([i]) {
                    case 'L':
                    case '[':
                        Object val = vals[[i]];
                        if (val != null &&
                            ![i - ].isInstance(val))
                        {
                            Field f = [i].getField();
                            throw new ClassCastException(
                                "cannot assign instance of " +
                                val.getClass().getName() + " to field " +
                                f.getDeclaringClass().getName() + "." +
                                f.getName() + " of type " +
                                f.getType().getName() + " in instance of " +
                                obj.getClass().getName());
                        }
                        .putObject(objkeyval);
                        break;
                    default:
                        throw new InternalError();
                }
            }
        }
    }

    
Matches given set of serializable fields with serializable fields described by the given local class descriptor, and returns a FieldReflector instance capable of setting/getting values from the subset of fields that match (non-matching fields are treated as filler, for which get operations return default values and set operations discard given values). Throws InvalidClassException if unresolvable type conflicts exist between the two sets of fields.
    private static FieldReflector getReflector(ObjectStreamField[] fields,
                                               ObjectStreamClass localDesc)
        throws InvalidClassException
    {
        // class irrelevant if no fields
        Class cl = (localDesc != null && fields.length > 0) ?
            localDesc.cl : null;
        FieldReflectorKey key = new FieldReflectorKey(clfields,
                                                      .);
        Reference<?> ref = ..get(key);
        Object entry = null;
        if (ref != null) {
            entry = ref.get();
        }
        EntryFuture future = null;
        if (entry == null) {
            EntryFuture newEntry = new EntryFuture();
            Reference<?> newRef = new SoftReference<EntryFuture>(newEntry);
            do {
                if (ref != null) {
                    ..remove(keyref);
                }
                ref = ..putIfAbsent(keynewRef);
                if (ref != null) {
                    entry = ref.get();
                }
            } while (ref != null && entry == null);
            if (entry == null) {
                future = newEntry;
            }
        }
        if (entry instanceof FieldReflector) {  // check common case first
            return (FieldReflectorentry;
        } else if (entry instanceof EntryFuture) {
            entry = ((EntryFutureentry).get();
        } else if (entry == null) {
            try {
                entry = new FieldReflector(matchFields(fieldslocalDesc));
            } catch (Throwable th) {
                entry = th;
            }
            future.set(entry);
            ..put(keynew SoftReference<Object>(entry));
        }
        if (entry instanceof FieldReflector) {
            return (FieldReflectorentry;
        } else if (entry instanceof InvalidClassException) {
            throw (InvalidClassExceptionentry;
        } else if (entry instanceof RuntimeException) {
            throw (RuntimeExceptionentry;
        } else if (entry instanceof Error) {
            throw (Errorentry;
        } else {
            throw new InternalError("unexpected entry: " + entry);
        }
    }

    
FieldReflector cache lookup key. Keys are considered equal if they refer to the same class and equivalent field formats.
    private static class FieldReflectorKey extends WeakReference<Class<?>> {
        private final String sigs;
        private final int hash;
        private final boolean nullClass;
        FieldReflectorKey(Class clObjectStreamField[] fields,
                          ReferenceQueue<Class<?>> queue)
        {
            super(clqueue);
             = (cl == null);
            StringBuilder sbuf = new StringBuilder();
            for (int i = 0; i < fields.lengthi++) {
                ObjectStreamField f = fields[i];
                sbuf.append(f.getName()).append(f.getSignature());
            }
             = sbuf.toString();
             = System.identityHashCode(cl) + .hashCode();
        }
        public int hashCode() {
            return ;
        }
        public boolean equals(Object obj) {
            if (obj == this) {
                return true;
            }
            if (obj instanceof FieldReflectorKey) {
                FieldReflectorKey other = (FieldReflectorKeyobj;
                Class<?> referent;
                return ( ? other.nullClass
                                  : ((referent = get()) != null) &&
                                    (referent == other.get())) &&
                    .equals(other.sigs);
            } else {
                return false;
            }
        }
    }

    
Matches given set of serializable fields with serializable fields obtained from the given local class descriptor (which contain bindings to reflective Field objects). Returns list of ObjectStreamFields in which each ObjectStreamField whose signature matches that of a local field contains a Field object for that field; unmatched ObjectStreamFields contain null Field objects. Shared/unshared settings of the returned ObjectStreamFields also reflect those of matched local ObjectStreamFields. Throws InvalidClassException if unresolvable type conflicts exist between the two sets of fields.
    private static ObjectStreamField[] matchFields(ObjectStreamField[] fields,
                                                   ObjectStreamClass localDesc)
        throws InvalidClassException
    {
        ObjectStreamField[] localFields = (localDesc != null) ?
            localDesc.fields : ;
        /*
         * Even if fields == localFields, we cannot simply return localFields
         * here.  In previous implementations of serialization,
         * ObjectStreamField.getType() returned Object.class if the
         * ObjectStreamField represented a non-primitive field and belonged to
         * a non-local class descriptor.  To preserve this (questionable)
         * behavior, the ObjectStreamField instances returned by matchFields
         * cannot report non-primitive types other than Object.class; hence
         * localFields cannot be returned directly.
         */
        ObjectStreamField[] matches = new ObjectStreamField[fields.length];
        for (int i = 0; i < fields.lengthi++) {
            ObjectStreamField f = fields[i], m = null;
            for (int j = 0; j < localFields.lengthj++) {
                ObjectStreamField lf = localFields[j];
                if (f.getName().equals(lf.getName())) {
                    if ((f.isPrimitive() || lf.isPrimitive()) &&
                        f.getTypeCode() != lf.getTypeCode())
                    {
                        throw new InvalidClassException(localDesc.name,
                            "incompatible types for field " + f.getName());
                    }
                    if (lf.getField() != null) {
                        m = new ObjectStreamField(
                            lf.getField(), lf.isUnshared(), false);
                    } else {
                        m = new ObjectStreamField(
                            lf.getName(), lf.getSignature(), lf.isUnshared());
                    }
                }
            }
            if (m == null) {
                m = new ObjectStreamField(
                    f.getName(), f.getSignature(), false);
            }
            m.setOffset(f.getOffset());
            matches[i] = m;
        }
        return matches;
    }

    
Removes from the specified map any keys that have been enqueued on the specified reference queue.
    static void processQueue(ReferenceQueue<Class<?>> queue,
                             ConcurrentMap<? extends
                             WeakReference<Class<?>>, ?> map)
    {
        Reference<? extends Class<?>> ref;
        while((ref = queue.poll()) != null) {
            map.remove(ref);
        }
    }

    
Weak key for Class objects.
    static class WeakClassKey extends WeakReference<Class<?>> {
        
saved value of the referent's identity hash code, to maintain a consistent hash code after the referent has been cleared
        private final int hash;

        
Create a new WeakClassKey to the given object, registered with a queue.
        WeakClassKey(Class<?> clReferenceQueue<Class<?>> refQueue) {
            super(clrefQueue);
             = System.identityHashCode(cl);
        }

        
Returns the identity hash code of the original referent.
        public int hashCode() {
            return ;
        }

        
Returns true if the given object is this identical WeakClassKey instance, or, if this object's referent has not been cleared, if the given object is another WeakClassKey instance with the identical non-null referent as this one.
        public boolean equals(Object obj) {
            if (obj == this) {
                return true;
            }
            if (obj instanceof WeakClassKey) {
                Object referent = get();
                return (referent != null) &&
                       (referent == ((WeakClassKeyobj).get());
            } else {
                return false;
            }
        }
    }
New to GrepCode? Check out our FAQ X