objectstreamclass.java

来自「This is a resource based on j2me embedde」· Java 代码 · 共 2,026 行 · 第 1/5 页

JAVA
2,026
字号
/* * @(#)ObjectStreamClass.java	1.116 06/10/10 * * Copyright  1990-2008 Sun Microsystems, Inc. All Rights Reserved.   * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER   *    * This program 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.    *    * This program 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 at /legal/license.txt).    *    * 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 or visit www.sun.com if you need additional   * information or have any questions.  * */package java.io;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.security.AccessController;import java.security.MessageDigest;import java.security.NoSuchAlgorithmException;import java.security.PrivilegedAction;import java.util.ArrayList;import java.util.Arrays;import java.util.Collections;import java.util.Comparator;import sun.misc.SoftCache;// import sun.misc.Unsafe;  // - Back-ported from JDK 1.4// import sun.reflect.ReflectionFactory;  // - Back-ported from JDK 1.4 /* Back-ported JDK 1.4 implementation  *//** * Serialization's descriptor for classes. * It contains the name and serialVersionUID of the class. * <br> * The ObjectStreamClass for a specific class loaded in this Java VM can * be found/created using the lookup method.<p> * The algorithm to compute the SerialVersionUID is described in  * <a href="../../../guide/serialization/spec/class.doc4.html"> Object Serialization Specification, Section 4.4, Stream Unique Identifiers</a>. * * @author	Mike Warres * @author	Roger Riggs * @version 1.98 02/02/00 * @see ObjectStreamField * @see <a href="../../../guide/serialization/spec/class.doc.html"> Object Serialization Specification, Section 4, Class Descriptors</a> * @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;        /** reflection factory for obtaining serialization constructors */    /* // - Back-ported from JDK 1.4     private static final ReflectionFactory reflFactory = (ReflectionFactory)	AccessController.doPrivileged(	    new ReflectionFactory.GetReflectionFactoryAction());	    */    /** cache mapping local classes -> descriptors */    private static final SoftCache localDescs = new SoftCache(10);    /** cache mapping field group/local desc pairs -> field reflectors */    private static final SoftCache reflectors = new SoftCache(10);    /** 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 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 accomodate 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 be thrown if deserialization attempted */    private InvalidClassException deserializeEx;    /** exception (if any) to be thrown 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; // - Back-ported from JDK 1.4     /** 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;    /** Class to be initialized -- for back-port to J2ME Foundation */    private Class initClass;  // - Back-ported from JDK 1.4     /**     * Initializes native code.     */    private static native void initNative();    static {	initNative();    }    /*     * Get the field IDs associated with the given fields.  The field IDs are     * later passed as arguments to the various ObjectInputStream and     * ObjectOutputStream native methods for setting and getting field values.     */    private static native void getFieldIDs(ObjectStreamField[] fields,	    long[] primFieldIDs, long[] objFieldIDs);    /**      * 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);    }        /**     * The name of the class described by this descriptor.     *     * @return a <code>String</code> representing the fully qualified 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() {	// TODO: synchronize instead of relying on volatile?	if (suid == null) {	    suid = (Long) AccessController.doPrivileged(		new PrivilegedAction() {		    public Object run() {			return new Long(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 <code>Class</code> 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;	}	/*	 * Note: using the class directly as the key for storing entries does	 * not pin the class indefinitely, since SoftCache removes strong refs	 * to keys when the corresponding values are gc'ed.	 */	Object entry;	EntryFuture future = null;	synchronized (localDescs) {	    if ((entry = localDescs.get(cl)) == null) {		localDescs.put(cl, future = new EntryFuture());	    }	}		if (entry instanceof ObjectStreamClass) {  // check common case first	    return (ObjectStreamClass) entry;	} else if (entry instanceof EntryFuture) {	    entry = ((EntryFuture) entry).get();	} else if (entry == null) {	    try {		entry = new ObjectStreamClass(cl);	    } catch (Throwable th) {		entry = th;	    }	    future.set(entry);	    synchronized (localDescs) {		localDescs.put(cl, entry);	    }	}		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 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;	synchronized void set(Object entry) {	    if (this.entry != unset) {		throw new IllegalStateException();	    }	    this.entry = entry;	    notifyAll();	}		synchronized Object get() {	    boolean interrupted = false;	    while (entry == unset) {		try { 		    wait(); 		} catch (InterruptedException ex) {		    interrupted = true;		}	    }	    if (interrupted) {		AccessController.doPrivileged(		    new PrivilegedAction() {			public Object run() {			    Thread.currentThread().interrupt();			    return null;			}		    }		);	    }	    return entry;	}    }    /**     * Creates local class descriptor representing given class.     */    private ObjectStreamClass(final Class cl) {	this.cl = cl;	name = cl.getName();	isProxy = Proxy.isProxyClass(cl);	serializable = Serializable.class.isAssignableFrom(cl);	externalizable = Externalizable.class.isAssignableFrom(cl);	Class superCl = cl.getSuperclass();	superDesc = (superCl != null) ? lookup(superCl, false) : null;	localDesc = this;	if (serializable) {	    AccessController.doPrivileged(new PrivilegedAction() {		public Object run() {		    suid = getDeclaredSUID(cl);		    fields = getSerialFields(cl);		    computeFieldOffsets();		    		    if (externalizable) {                      // Back-ported from JDK 1.4		      // cons = getExternalizableConstructor(cl);		      initClass = cl;		    } else {                        // Back-ported from JDK 1.4		        // cons = getSerializableConstructor(cl);		        initClass = getSerializableInitClass(cl);			writeObjectMethod = getPrivateMethod(cl, "writeObject", 			    new Class[] { ObjectOutputStream.class }, 			    Void.TYPE);			readObjectMethod = getPrivateMethod(cl, "readObject", 			    new Class[] { ObjectInputStream.class }, 			    Void.TYPE);			readObjectNoDataMethod = getPrivateMethod(			    cl, "readObjectNoData", 			    new Class[0], Void.TYPE);			hasWriteObjectData = (writeObjectMethod != null);		    }		    writeReplaceMethod = getInheritableMethod(			cl, "writeReplace", new Class[0], Object.class);		    readResolveMethod = getInheritableMethod(			cl, "readResolve", new Class[0], Object.class);		    return null;		}	    });	} else {	    suid = new Long(0);	    fields = NO_FIELDS;	}	try {	    fieldRefl = getReflector(fields, this);	} catch (InvalidClassException ex) {

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?