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 + -
显示快捷键?