Source Home >> Java Source 1.6.0 >> java.io.ObjectStreamClass V 0.09
  • 0001/*
  • 0002 * @(#)ObjectStreamClass.java 1.152 06/04/21
  • 0003 *
  • 0004 * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
  • 0005 * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
  • 0006 */
  • 0007
  • 0008package java.io;
  • 0009
  • 0010import java.lang.ref.Reference;
  • 0011import java.lang.ref.ReferenceQueue;
  • 0012import java.lang.ref.SoftReference;
  • 0013import java.lang.ref.WeakReference;
  • 0014import java.lang.reflect.Constructor;
  • 0015import java.lang.reflect.Field;
  • 0016import java.lang.reflect.InvocationTargetException;
  • 0017import java.lang.reflect.Member;
  • 0018import java.lang.reflect.Method;
  • 0019import java.lang.reflect.Modifier;
  • 0020import java.lang.reflect.Proxy;
  • 0021import java.security.AccessController;
  • 0022import java.security.MessageDigest;
  • 0023import java.security.NoSuchAlgorithmException;
  • 0024import java.security.PrivilegedAction;
  • 0025import java.util.ArrayList;
  • 0026import java.util.Arrays;
  • 0027import java.util.Collections;
  • 0028import java.util.Comparator;
  • 0029import java.util.HashSet;
  • 0030import java.util.Set;
  • 0031import java.util.concurrent.ConcurrentHashMap;
  • 0032import java.util.concurrent.ConcurrentMap;
  • 0033import sun.misc.Unsafe;
  • 0034import sun.reflect.ReflectionFactory;
  • 0035
  • 0036/**
  • 0037 * Serialization's descriptor for classes. It contains the name and
  • 0038 * serialVersionUID of the class. The ObjectStreamClass for a specific class
  • 0039 * loaded in this Java VM can be found/created using the lookup method.
  • 0040 *
  • 0041 * <p>The algorithm to compute the SerialVersionUID is described in
  • 0042 * <a href="../../../platform/serialization/spec/class.html#4100">Object
  • 0043 * Serialization Specification, Section 4.6, Stream Unique Identifiers</a>.
  • 0044 *
  • 0045 * @author Mike Warres
  • 0046 * @author Roger Riggs
  • 0047 * @version 1.152, 04/21/06
  • 0048 * @see ObjectStreamField
  • 0049 * @see <a href="../../../platform/serialization/spec/class.html">Object Serialization Specification, Section 4, Class Descriptors</a>
  • 0050 * @since JDK1.1
  • 0051 */
  • 0052public class ObjectStreamClass implements Serializable {
  • 0053
  • 0054 /** serialPersistentFields value indicating no serializable fields */
  • 0055 public static final ObjectStreamField[] NO_FIELDS =
  • 0056 new ObjectStreamField[0];
  • 0057
  • 0058 private static final long serialVersionUID = -6120832682080437368L;
  • 0059 private static final ObjectStreamField[] serialPersistentFields =
  • 0060 NO_FIELDS;
  • 0061
  • 0062 /** reflection factory for obtaining serialization constructors */
  • 0063 private static final ReflectionFactory reflFactory = (ReflectionFactory)
  • 0064 AccessController.doPrivileged(
  • 0065 new ReflectionFactory.GetReflectionFactoryAction());
  • 0066
  • 0067 private static class Caches {
  • 0068 /** cache mapping local classes -> descriptors */
  • 0069 static final ConcurrentMap<WeakClassKey,Reference<?>> localDescs =
  • 0070 new ConcurrentHashMap<WeakClassKey,Reference<?>>();
  • 0071
  • 0072 /** cache mapping field group/local desc pairs -> field reflectors */
  • 0073 static final ConcurrentMap<FieldReflectorKey,Reference<?>> reflectors =
  • 0074 new ConcurrentHashMap<FieldReflectorKey,Reference<?>>();
  • 0075
  • 0076 /** queue for WeakReferences to local classes */
  • 0077 private static final ReferenceQueue<Class<?>> localDescsQueue =
  • 0078 new ReferenceQueue<Class<?>>();
  • 0079 /** queue for WeakReferences to field reflectors keys */
  • 0080 private static final ReferenceQueue<Class<?>> reflectorsQueue =
  • 0081 new ReferenceQueue<Class<?>>();
  • 0082 }
  • 0083
  • 0084 /** class associated with this descriptor (if any) */
  • 0085 private Class cl;
  • 0086 /** name of class represented by this descriptor */
  • 0087 private String name;
  • 0088 /** serialVersionUID of represented class (null if not computed yet) */
  • 0089 private volatile Long suid;
  • 0090
  • 0091 /** true if represents dynamic proxy class */
  • 0092 private boolean isProxy;
  • 0093 /** true if represents enum type */
  • 0094 private boolean isEnum;
  • 0095 /** true if represented class implements Serializable */
  • 0096 private boolean serializable;
  • 0097 /** true if represented class implements Externalizable */
  • 0098 private boolean externalizable;
  • 0099 /** true if desc has data written by class-defined writeObject method */
  • 0100 private boolean hasWriteObjectData;
  • 0101 /**
  • 0102 * true if desc has externalizable data written in block data format; this
  • 0103 * must be true by default to accommodate ObjectInputStream subclasses which
  • 0104 * override readClassDescriptor() to return class descriptors obtained from
  • 0105 * ObjectStreamClass.lookup() (see 4461737)
  • 0106 */
  • 0107 private boolean hasBlockExternalData = true;
  • 0108
  • 0109 /** exception (if any) thrown while attempting to resolve class */
  • 0110 private ClassNotFoundException resolveEx;
  • 0111 /** exception (if any) to throw if non-enum deserialization attempted */
  • 0112 private InvalidClassException deserializeEx;
  • 0113 /** exception (if any) to throw if non-enum serialization attempted */
  • 0114 private InvalidClassException serializeEx;
  • 0115 /** exception (if any) to throw if default serialization attempted */
  • 0116 private InvalidClassException defaultSerializeEx;
  • 0117
  • 0118 /** serializable fields */
  • 0119 private ObjectStreamField[] fields;
  • 0120 /** aggregate marshalled size of primitive fields */
  • 0121 private int primDataSize;
  • 0122 /** number of non-primitive fields */
  • 0123 private int numObjFields;
  • 0124 /** reflector for setting/getting serializable field values */
  • 0125 private FieldReflector fieldRefl;
  • 0126 /** data layout of serialized objects described by this class desc */
  • 0127 private volatile ClassDataSlot[] dataLayout;
  • 0128
  • 0129 /** serialization-appropriate constructor, or null if none */
  • 0130 private Constructor cons;
  • 0131 /** class-defined writeObject method, or null if none */
  • 0132 private Method writeObjectMethod;
  • 0133 /** class-defined readObject method, or null if none */
  • 0134 private Method readObjectMethod;
  • 0135 /** class-defined readObjectNoData method, or null if none */
  • 0136 private Method readObjectNoDataMethod;
  • 0137 /** class-defined writeReplace method, or null if none */
  • 0138 private Method writeReplaceMethod;
  • 0139 /** class-defined readResolve method, or null if none */
  • 0140 private Method readResolveMethod;
  • 0141
  • 0142 /** local class descriptor for represented class (may point to self) */
  • 0143 private ObjectStreamClass localDesc;
  • 0144 /** superclass descriptor appearing in stream */
  • 0145 private ObjectStreamClass superDesc;
  • 0146
  • 0147 /**
  • 0148 * Initializes native code.
  • 0149 */
  • 0150 private static native void initNative();
  • 0151 static {
  • 0152 initNative();
  • 0153 }
  • 0154
  • 0155 /**
  • 0156 * Find the descriptor for a class that can be serialized. Creates an
  • 0157 * ObjectStreamClass instance if one does not exist yet for class. Null is
  • 0158 * returned if the specified class does not implement java.io.Serializable
  • 0159 * or java.io.Externalizable.
  • 0160 *
  • 0161 * @param cl class for which to get the descriptor
  • 0162 * @return the class descriptor for the specified class
  • 0163 */
  • 0164 public static ObjectStreamClass lookup(Class<?> cl) {
  • 0165 return lookup(cl, false);
  • 0166 }
  • 0167
  • 0168 /**
  • 0169 * Returns the descriptor for any class, regardless of whether it
  • 0170 * implements {@link Serializable}.
  • 0171 *
  • 0172 * @param cl class for which to get the descriptor
  • 0173 * @return the class descriptor for the specified class
  • 0174 * @since 1.6
  • 0175 */
  • 0176 public static ObjectStreamClass lookupAny(Class<?> cl) {
  • 0177 return lookup(cl, true);
  • 0178 }
  • 0179
  • 0180 /**
  • 0181 * Returns the name of the class described by this descriptor.
  • 0182 * This method returns the name of the class in the format that
  • 0183 * is used by the {@link Class#getName} method.
  • 0184 *
  • 0185 * @return a string representing the name of the class
  • 0186 */
  • 0187 public String getName() {
  • 0188 return name;
  • 0189 }
  • 0190
  • 0191 /**
  • 0192 * Return the serialVersionUID for this class. The serialVersionUID
  • 0193 * defines a set of classes all with the same name that have evolved from a
  • 0194 * common root class and agree to be serialized and deserialized using a
  • 0195 * common format. NonSerializable classes have a serialVersionUID of 0L.
  • 0196 *
  • 0197 * @return the SUID of the class described by this descriptor
  • 0198 */
  • 0199 public long getSerialVersionUID() {
  • 0200 // REMIND: synchronize instead of relying on volatile?
  • 0201 if (suid == null) {
  • 0202 suid = (Long) AccessController.doPrivileged(
  • 0203 new PrivilegedAction() {
  • 0204 public Object run() {
  • 0205 return Long.valueOf(computeDefaultSUID(cl));
  • 0206 }
  • 0207 }
  • 0208 );
  • 0209 }
  • 0210 return suid.longValue();
  • 0211 }
  • 0212
  • 0213 /**
  • 0214 * Return the class in the local VM that this version is mapped to. Null
  • 0215 * is returned if there is no corresponding local class.
  • 0216 *
  • 0217 * @return the <code>Class</code> instance that this descriptor represents
  • 0218 */
  • 0219 public Class<?> forClass() {
  • 0220 return cl;
  • 0221 }
  • 0222
  • 0223 /**
  • 0224 * Return an array of the fields of this serializable class.
  • 0225 *
  • 0226 * @return an array containing an element for each persistent field of
  • 0227 * this class. Returns an array of length zero if there are no
  • 0228 * fields.
  • 0229 * @since 1.2
  • 0230 */
  • 0231 public ObjectStreamField[] getFields() {
  • 0232 return getFields(true);
  • 0233 }
  • 0234
  • 0235 /**
  • 0236 * Get the field of this class by name.
  • 0237 *
  • 0238 * @param name the name of the data field to look for
  • 0239 * @return The ObjectStreamField object of the named field or null if
  • 0240 * there is no such named field.
  • 0241 */
  • 0242 public ObjectStreamField getField(String name) {
  • 0243 return getField(name, null);
  • 0244 }
  • 0245
  • 0246 /**
  • 0247 * Return a string describing this ObjectStreamClass.
  • 0248 */
  • 0249 public String toString() {
  • 0250 return name + ": static final long serialVersionUID = " +
  • 0251 getSerialVersionUID() + "L;";
  • 0252 }
  • 0253
  • 0254 /**
  • 0255 * Looks up and returns class descriptor for given class, or null if class
  • 0256 * is non-serializable and "all" is set to false.
  • 0257 *
  • 0258 * @param cl class to look up
  • 0259 * @param all if true, return descriptors for all classes; if false, only
  • 0260 * return descriptors for serializable classes
  • 0261 */
  • 0262 static ObjectStreamClass lookup(Class cl, boolean all) {
  • 0263 if (!(all || Serializable.class.isAssignableFrom(cl))) {
  • 0264 return null;
  • 0265 }
  • 0266 processQueue(Caches.localDescsQueue, Caches.localDescs);
  • 0267 WeakClassKey key = new WeakClassKey(cl, Caches.localDescsQueue);
  • 0268 Reference<?> ref = Caches.localDescs.get(key);
  • 0269 Object entry = null;
  • 0270 if (ref != null) {
  • 0271 entry = ref.get();
  • 0272 }
  • 0273 EntryFuture future = null;
  • 0274 if (entry == null) {
  • 0275 EntryFuture newEntry = new EntryFuture();
  • 0276 Reference<?> newRef = new SoftReference<EntryFuture>(newEntry);
  • 0277 do {
  • 0278 if (ref != null) {
  • 0279 Caches.localDescs.remove(key, ref);
  • 0280 }
  • 0281 ref = Caches.localDescs.putIfAbsent(key, newRef);
  • 0282 if (ref != null) {
  • 0283 entry = ref.get();
  • 0284 }
  • 0285 } while (ref != null && entry == null);
  • 0286 if (entry == null) {
  • 0287 future = newEntry;
  • 0288 }
  • 0289 }
  • 0290
  • 0291 if (entry instanceof ObjectStreamClass) { // check common case first
  • 0292 return (ObjectStreamClass) entry;
  • 0293 }
  • 0294 if (entry instanceof EntryFuture) {
  • 0295 future = (EntryFuture) entry;
  • 0296 if (future.getOwner() == Thread.currentThread()) {
  • 0297 /*
  • 0298 * Handle nested call situation described by 4803747: waiting
  • 0299 * for future value to be set by a lookup() call further up the
  • 0300 * stack will result in deadlock, so calculate and set the
  • 0301 * future value here instead.
  • 0302 */
  • 0303 entry = null;
  • 0304 } else {
  • 0305 entry = future.get();
  • 0306 }
  • 0307 }
  • 0308 if (entry == null) {
  • 0309 try {
  • 0310 entry = new ObjectStreamClass(cl);
  • 0311 } catch (Throwable th) {
  • 0312 entry = th;
  • 0313 }
  • 0314 if (future.set(entry)) {
  • 0315 Caches.localDescs.put(key, new SoftReference<Object>(entry));
  • 0316 } else {
  • 0317 // nested lookup call already set future
  • 0318 entry = future.get();
  • 0319 }
  • 0320 }
  • 0321
  • 0322 if (entry instanceof ObjectStreamClass) {
  • 0323 return (ObjectStreamClass) entry;
  • 0324 } else if (entry instanceof RuntimeException) {
  • 0325 throw (RuntimeException) entry;
  • 0326 } else if (entry instanceof Error) {
  • 0327 throw (Error) entry;
  • 0328 } else {
  • 0329 throw new InternalError("unexpected entry: " + entry);
  • 0330 }
  • 0331 }
  • 0332
  • 0333 /**
  • 0334 * Placeholder used in class descriptor and field reflector lookup tables
  • 0335 * for an entry in the process of being initialized. (Internal) callers
  • 0336 * which receive an EntryFuture belonging to another thread as the result
  • 0337 * of a lookup should call the get() method of the EntryFuture; this will
  • 0338 * return the actual entry once it is ready for use and has been set(). To
  • 0339 * conserve objects, EntryFutures synchronize on themselves.
  • 0340 */
  • 0341 private static class EntryFuture {
  • 0342
  • 0343 private static final Object unset = new Object();
  • 0344 private final Thread owner = Thread.currentThread();
  • 0345 private Object entry = unset;
  • 0346
  • 0347 /**
  • 0348 * Attempts to set the value contained by this EntryFuture. If the
  • 0349 * EntryFuture's value has not been set already, then the value is
  • 0350 * saved, any callers blocked in the get() method are notified, and
  • 0351 * true is returned. If the value has already been set, then no saving
  • 0352 * or notification occurs, and false is returned.
  • 0353 */
  • 0354 synchronized boolean set(Object entry) {
  • 0355 if (this.entry != unset) {
  • 0356 return false;
  • 0357 }
  • 0358 this.entry = entry;
  • 0359 notifyAll();
  • 0360 return true;
  • 0361 }
  • 0362
  • 0363 /**
  • 0364 * Returns the value contained by this EntryFuture, blocking if
  • 0365 * necessary until a value is set.
  • 0366 */
  • 0367 synchronized Object get() {
  • 0368 boolean interrupted = false;
  • 0369 while (entry == unset) {
  • 0370 try {
  • 0371 wait();
  • 0372 } catch (InterruptedException ex) {
  • 0373 interrupted = true;
  • 0374 }
  • 0375 }
  • 0376 if (interrupted) {
  • 0377 AccessController.doPrivileged(
  • 0378 new PrivilegedAction() {
  • 0379 public Object run() {
  • 0380 Thread.currentThread().interrupt();
  • 0381 return null;
  • 0382 }
  • 0383 }
  • 0384 );
  • 0385 }
  • 0386 return entry;
  • 0387 }
  • 0388
  • 0389 /**
  • 0390 * Returns the thread that created this EntryFuture.
  • 0391 */
  • 0392 Thread getOwner() {
  • 0393 return owner;
  • 0394 }
  • 0395 }
  • 0396
  • 0397 /**
  • 0398 * Creates local class descriptor representing given class.
  • 0399 */
  • 0400 private ObjectStreamClass(final Class cl) {
  • 0401 this.cl = cl;
  • 0402 name = cl.getName();
  • 0403 isProxy = Proxy.isProxyClass(cl);
  • 0404 isEnum = Enum.class.isAssignableFrom(cl);
  • 0405 serializable = Serializable.class.isAssignableFrom(cl);
  • 0406 externalizable = Externalizable.class.isAssignableFrom(cl);
  • 0407
  • 0408 Class superCl = cl.getSuperclass();
  • 0409 superDesc = (superCl != null) ? lookup(superCl, false) : null;
  • 0410 localDesc = this;
  • 0411
  • 0412 if (serializable) {
  • 0413 AccessController.doPrivileged(new PrivilegedAction() {
  • 0414 public Object run() {
  • 0415 if (isEnum) {
  • 0416 suid = Long.valueOf(0);
  • 0417 fields = NO_FIELDS;
  • 0418 return null;
  • 0419 }
  • 0420 if (cl.isArray()) {
  • 0421 fields = NO_FIELDS;
  • 0422 return null;
  • 0423 }
  • 0424
  • 0425 suid = getDeclaredSUID(cl);
  • 0426 try {
  • 0427 fields = getSerialFields(cl);
  • 0428 computeFieldOffsets();
  • 0429 } catch (InvalidClassException e) {
  • 0430 serializeEx = deserializeEx = e;
  • 0431 fields = NO_FIELDS;
  • 0432 }
  • 0433
  • 0434 if (externalizable) {
  • 0435 cons = getExternalizableConstructor(cl);
  • 0436 } else {
  • 0437 cons = getSerializableConstructor(cl);
  • 0438 writeObjectMethod = getPrivateMethod(cl, "writeObject",
  • 0439 new Class[] { ObjectOutputStream.class },
  • 0440 Void.TYPE);
  • 0441 readObjectMethod = getPrivateMethod(cl, "readObject",
  • 0442 new Class[] { ObjectInputStream.class },
  • 0443 Void.TYPE);
  • 0444 readObjectNoDataMethod = getPrivateMethod(
  • 0445 cl, "readObjectNoData", null, Void.TYPE);
  • 0446 hasWriteObjectData = (writeObjectMethod != null);
  • 0447 }
  • 0448 writeReplaceMethod = getInheritableMethod(
  • 0449 cl, "writeReplace", null, Object.class);
  • 0450 readResolveMethod = getInheritableMethod(
  • 0451 cl, "readResolve", null, Object.class);
  • 0452 return null;
  • 0453 }
  • 0454 });
  • 0455 } else {
  • 0456 suid = Long.valueOf(0);
  • 0457 fields = NO_FIELDS;
  • 0458 }
  • 0459
  • 0460 try {
  • 0461 fieldRefl = getReflector(fields, this);
  • 0462 } catch (InvalidClassException ex) {
  • 0463 // field mismatches impossible when matching local fields vs. self
  • 0464 throw new InternalError();
  • 0465 }
  • 0466
  • 0467 if (deserializeEx == null) {
  • 0468 if (isEnum) {
  • 0469 deserializeEx = new InvalidClassException(name, "enum type");
  • 0470 } else if (cons == null) {
  • 0471 deserializeEx = new InvalidClassException(
  • 0472 name, "no valid constructor");
  • 0473 }
  • 0474 }
  • 0475 for (int i = 0; i < fields.length; i++) {
  • 0476 if (fields[i].getField() == null) {
  • 0477 defaultSerializeEx = new InvalidClassException(
  • 0478 name, "unmatched serializable field(s) declared");
  • 0479 }
  • 0480 }
  • 0481 }
  • 0482
  • 0483 /**
  • 0484 * Creates blank class descriptor which should be initialized via a
  • 0485 * subsequent call to initProxy(), initNonProxy() or readNonProxy().
  • 0486 */
  • 0487 ObjectStreamClass() {
  • 0488 }
  • 0489
  • 0490 /**
  • 0491 * Initializes class descriptor representing a proxy class.
  • 0492 */
  • 0493 void initProxy(Class cl,
  • 0494 ClassNotFoundException resolveEx,
  • 0495 ObjectStreamClass superDesc)
  • 0496 throws InvalidClassException
  • 0497 {
  • 0498 this.cl = cl;
  • 0499 this.resolveEx = resolveEx;
  • 0500 this.superDesc = superDesc;
  • 0501 isProxy = true;
  • 0502 serializable = true;
  • 0503 suid = Long.valueOf(0);
  • 0504 fields = NO_FIELDS;
  • 0505
  • 0506 if (cl != null) {
  • 0507 localDesc = lookup(cl, true);
  • 0508 if (!localDesc.isProxy) {
  • 0509 throw new InvalidClassException(
  • 0510 "cannot bind proxy descriptor to a non-proxy class");
  • 0511 }
  • 0512 name = localDesc.name;
  • 0513 externalizable = localDesc.externalizable;
  • 0514 cons = localDesc.cons;
  • 0515 writeReplaceMethod = localDesc.writeReplaceMethod;
  • 0516 readResolveMethod = localDesc.readResolveMethod;
  • 0517 deserializeEx = localDesc.deserializeEx;
  • 0518 }
  • 0519 fieldRefl = getReflector(fields, localDesc);
  • 0520 }
  • 0521
  • 0522 /**
  • 0523 * Initializes class descriptor representing a non-proxy class.
  • 0524 */
  • 0525 void initNonProxy(ObjectStreamClass model,
  • 0526 Class cl,
  • 0527 ClassNotFoundException resolveEx,
  • 0528 ObjectStreamClass superDesc)
  • 0529 throws InvalidClassException
  • 0530 {
  • 0531 this.cl = cl;
  • 0532 this.resolveEx = resolveEx;
  • 0533 this.superDesc = superDesc;
  • 0534 name = model.name;
  • 0535 suid = Long.valueOf(model.getSerialVersionUID());
  • 0536 isProxy = false;
  • 0537 isEnum = model.isEnum;
  • 0538 serializable = model.serializable;
  • 0539 externalizable = model.externalizable;
  • 0540 hasBlockExternalData = model.hasBlockExternalData;
  • 0541 hasWriteObjectData = model.hasWriteObjectData;
  • 0542 fields = model.fields;
  • 0543 primDataSize = model.primDataSize;
  • 0544 numObjFields = model.numObjFields;
  • 0545
  • 0546 if (cl != null) {
  • 0547 localDesc = lookup(cl, true);
  • 0548 if (localDesc.isProxy) {
  • 0549 throw new InvalidClassException(
  • 0550 "cannot bind non-proxy descriptor to a proxy class");
  • 0551 }
  • 0552 if (isEnum != localDesc.isEnum) {
  • 0553 throw new InvalidClassException(isEnum ?
  • 0554 "cannot bind enum descriptor to a non-enum class" :
  • 0555 "cannot bind non-enum descriptor to an enum class");
  • 0556 }
  • 0557
  • 0558 if (serializable == localDesc.serializable &&
  • 0559 !cl.isArray() &&
  • 0560 suid.longValue() != localDesc.getSerialVersionUID())
  • 0561 {
  • 0562 throw new InvalidClassException(localDesc.name,
  • 0563 "local class incompatible: " +
  • 0564 "stream classdesc serialVersionUID = " + suid +
  • 0565 ", local class serialVersionUID = " +
  • 0566 localDesc.getSerialVersionUID());
  • 0567 }
  • 0568
  • 0569 if (!classNamesEqual(name, localDesc.name)) {
  • 0570 throw new InvalidClassException(localDesc.name,
  • 0571 "local class name incompatible with stream class " +
  • 0572 "name \"" + name + "\"");
  • 0573 }
  • 0574
  • 0575 if (!isEnum) {
  • 0576 if ((serializable == localDesc.serializable) &&
  • 0577 (externalizable != localDesc.externalizable))
  • 0578 {
  • 0579 throw new InvalidClassException(localDesc.name,
  • 0580 "Serializable incompatible with Externalizable");
  • 0581 }
  • 0582
  • 0583 if ((serializable != localDesc.serializable) ||
  • 0584 (externalizable != localDesc.externalizable) ||
  • 0585 !(serializable || externalizable))
  • 0586 {
  • 0587 deserializeEx = new InvalidClassException(localDesc.name,
  • 0588 "class invalid for deserialization");
  • 0589 }
  • 0590 }
  • 0591
  • 0592 cons = localDesc.cons;
  • 0593 writeObjectMethod = localDesc.writeObjectMethod;
  • 0594 readObjectMethod = localDesc.readObjectMethod;
  • 0595 readObjectNoDataMethod = localDesc.readObjectNoDataMethod;
  • 0596 writeReplaceMethod = localDesc.writeReplaceMethod;
  • 0597 readResolveMethod = localDesc.readResolveMethod;
  • 0598 if (deserializeEx == null) {
  • 0599 deserializeEx = localDesc.deserializeEx;
  • 0600 }
  • 0601 }
  • 0602 fieldRefl = getReflector(fields, localDesc);
  • 0603 // reassign to matched fields so as to reflect local unshared settings
  • 0604 fields = fieldRefl.getFields();
  • 0605 }
  • 0606
  • 0607 /**
  • 0608 * Reads non-proxy class descriptor information from given input stream.
  • 0609 * The resulting class descriptor is not fully functional; it can only be
  • 0610 * used as input to the ObjectInputStream.resolveClass() and
  • 0611 * ObjectStreamClass.initNonProxy() methods.
  • 0612 */
  • 0613 void readNonProxy(ObjectInputStream in)
  • 0614 throws IOException, ClassNotFoundException
  • 0615 {
  • 0616 name = in.readUTF();
  • 0617 suid = Long.valueOf(in.readLong());
  • 0618 isProxy = false;
  • 0619
  • 0620 byte flags = in.readByte();
  • 0621 hasWriteObjectData =
  • 0622 ((flags & ObjectStreamConstants.SC_WRITE_METHOD) != 0);
  • 0623 hasBlockExternalData =
  • 0624 ((flags & ObjectStreamConstants.SC_BLOCK_DATA) != 0);
  • 0625 externalizable =
  • 0626 ((flags & ObjectStreamConstants.SC_EXTERNALIZABLE) != 0);
  • 0627 boolean sflag =
  • 0628 ((flags & ObjectStreamConstants.SC_SERIALIZABLE) != 0);
  • 0629 if (externalizable && sflag) {
  • 0630 throw new InvalidClassException(
  • 0631 name, "serializable and externalizable flags conflict");
  • 0632 }
  • 0633 serializable = externalizable || sflag;
  • 0634 isEnum = ((flags & ObjectStreamConstants.SC_ENUM) != 0);
  • 0635 if (isEnum && suid.longValue() != 0L) {
  • 0636 throw new InvalidClassException(name,
  • 0637 "enum descriptor has non-zero serialVersionUID: " + suid);
  • 0638 }
  • 0639
  • 0640 int numFields = in.readShort();
  • 0641 if (isEnum && numFields != 0) {
  • 0642 throw new InvalidClassException(name,
  • 0643 "enum descriptor has non-zero field count: " + numFields);
  • 0644 }
  • 0645 fields = (numFields > 0) ?
  • 0646 new ObjectStreamField[numFields] : NO_FIELDS;
  • 0647 for (int i = 0; i < numFields; i++) {
  • 0648 char tcode = (char) in.readByte();
  • 0649 String fname = in.readUTF();
  • 0650 String signature = ((tcode == 'L') || (tcode == '[')) ?
  • 0651 in.readTypeString() : new String(new char[] { tcode });
  • 0652 try {
  • 0653 fields[i] = new ObjectStreamField(fname, signature, false);
  • 0654 } catch (RuntimeException e) {
  • 0655 throw (IOException) new InvalidClassException(name,
  • 0656 "invalid descriptor for field " + fname).initCause(e);
  • 0657 }
  • 0658 }
  • 0659 computeFieldOffsets();
  • 0660 }
  • 0661
  • 0662 /**
  • 0663 * Writes non-proxy class descriptor information to given output stream.
  • 0664 */
  • 0665 void writeNonProxy(ObjectOutputStream out) throws IOException {
  • 0666 out.writeUTF(name);
  • 0667 out.writeLong(getSerialVersionUID());
  • 0668
  • 0669 byte flags = 0;
  • 0670 if (externalizable) {
  • 0671 flags |= ObjectStreamConstants.SC_EXTERNALIZABLE;
  • 0672 int protocol = out.getProtocolVersion();
  • 0673 if (protocol != ObjectStreamConstants.PROTOCOL_VERSION_1) {
  • 0674 flags |= ObjectStreamConstants.SC_BLOCK_DATA;
  • 0675 }
  • 0676 } else if (serializable) {
  • 0677 flags |= ObjectStreamConstants.SC_SERIALIZABLE;
  • 0678 }
  • 0679 if (hasWriteObjectData) {
  • 0680 flags |= ObjectStreamConstants.SC_WRITE_METHOD;
  • 0681 }
  • 0682 if (isEnum) {
  • 0683 flags |= ObjectStreamConstants.SC_ENUM;
  • 0684 }
  • 0685 out.writeByte(flags);
  • 0686
  • 0687 out.writeShort(fields.length);
  • 0688 for (int i = 0; i < fields.length; i++) {
  • 0689 ObjectStreamField f = fields[i];
  • 0690 out.writeByte(f.getTypeCode());
  • 0691 out.writeUTF(f.getName());
  • 0692 if (!f.isPrimitive()) {
  • 0693 out.writeTypeString(f.getTypeString());
  • 0694 }
  • 0695 }
  • 0696 }
  • 0697
  • 0698 /**
  • 0699 * Returns ClassNotFoundException (if any) thrown while attempting to
  • 0700 * resolve local class corresponding to this class descriptor.
  • 0701 */
  • 0702 ClassNotFoundException getResolveException() {
  • 0703 return resolveEx;
  • 0704 }
  • 0705
  • 0706 /**
  • 0707 * Throws an InvalidClassException if object instances referencing this
  • 0708 * class descriptor should not be allowed to deserialize. This method does
  • 0709 * not apply to deserialization of enum constants.
  • 0710 */
  • 0711 void checkDeserialize() throws InvalidClassException {
  • 0712 if (deserializeEx != null) {
  • 0713 InvalidClassException ice =
  • 0714 new InvalidClassException(deserializeEx.classname,
  • 0715 deserializeEx.getMessage());
  • 0716 ice.initCause(deserializeEx);
  • 0717 throw ice;
  • 0718 }
  • 0719 }
  • 0720
  • 0721 /**
  • 0722 * Throws an InvalidClassException if objects whose class is represented by
  • 0723 * this descriptor should not be allowed to serialize. This method does
  • 0724 * not apply to serialization of enum constants.
  • 0725 */
  • 0726 void checkSerialize() throws InvalidClassException {
  • 0727 if (serializeEx != null) {
  • 0728 InvalidClassException ice =
  • 0729 new InvalidClassException(serializeEx.classname,
  • 0730 serializeEx.getMessage());
  • 0731 ice.initCause(serializeEx);
  • 0732 throw ice;
  • 0733 }
  • 0734 }
  • 0735
  • 0736 /**
  • 0737 * Throws an InvalidClassException if objects whose class is represented by
  • 0738 * this descriptor should not be permitted to use default serialization
  • 0739 * (e.g., if the class declares serializable fields that do not correspond
  • 0740 * to actual fields, and hence must use the GetField API). This method
  • 0741 * does not apply to deserialization of enum constants.
  • 0742 */
  • 0743 void checkDefaultSerialize() throws InvalidClassException {
  • 0744 if (defaultSerializeEx != null) {
  • 0745 InvalidClassException ice =
  • 0746 new InvalidClassException(defaultSerializeEx.classname,
  • 0747 defaultSerializeEx.getMessage());
  • 0748 ice.initCause(defaultSerializeEx);
  • 0749 throw ice;
  • 0750 }
  • 0751 }
  • 0752
  • 0753 /**
  • 0754 * Returns superclass descriptor. Note that on the receiving side, the
  • 0755 * superclass descriptor may be bound to a class that is not a superclass
  • 0756 * of the subclass descriptor's bound class.
  • 0757 */
  • 0758 ObjectStreamClass getSuperDesc() {
  • 0759 return superDesc;
  • 0760 }
  • 0761
  • 0762 /**
  • 0763 * Returns the "local" class descriptor for the class associated with this
  • 0764 * class descriptor (i.e., the result of
  • 0765 * ObjectStreamClass.lookup(this.forClass())) or null if there is no class
  • 0766 * associated with this descriptor.
  • 0767 */
  • 0768 ObjectStreamClass getLocalDesc() {
  • 0769 return localDesc;
  • 0770 }
  • 0771
  • 0772 /**
  • 0773 * Returns arrays of ObjectStreamFields representing the serializable
  • 0774 * fields of the represented class. If copy is true, a clone of this class
  • 0775 * descriptor's field array is returned, otherwise the array itself is
  • 0776 * returned.
  • 0777 */
  • 0778 ObjectStreamField[] getFields(boolean copy) {
  • 0779 return copy ? (ObjectStreamField[]) fields.clone() : fields;
  • 0780 }
  • 0781
  • 0782 /**
  • 0783 * Looks up a serializable field of the represented class by name and type.
  • 0784 * A specified type of null matches all types, Object.class matches all
  • 0785 * non-primitive types, and any other non-null type matches assignable
  • 0786 * types only. Returns matching field, or null if no match found.
  • 0787 */
  • 0788 ObjectStreamField getField(String name, Class type) {
  • 0789 for (int i = 0; i < fields.length; i++) {
  • 0790 ObjectStreamField f = fields[i];
  • 0791 if (f.getName().equals(name)) {
  • 0792 if (type == null ||
  • 0793 (type == Object.class && !f.isPrimitive()))
  • 0794 {
  • 0795 return f;
  • 0796 }
  • 0797 Class ftype = f.getType();
  • 0798 if (ftype != null && type.isAssignableFrom(ftype)) {
  • 0799 return f;
  • 0800 }
  • 0801 }
  • 0802 }
  • 0803 return null;
  • 0804 }
  • 0805
  • 0806 /**
  • 0807 * Returns true if class descriptor represents a dynamic proxy class, false
  • 0808 * otherwise.
  • 0809 */
  • 0810 boolean isProxy() {
  • 0811 return isProxy;
  • 0812 }
  • 0813
  • 0814 /**
  • 0815 * Returns true if class descriptor represents an enum type, false
  • 0816 * otherwise.
  • 0817 */
  • 0818 boolean isEnum() {
  • 0819 return isEnum;
  • 0820 }
  • 0821
  • 0822 /**
  • 0823 * Returns true if represented class implements Externalizable, false
  • 0824 * otherwise.
  • 0825 */
  • 0826 boolean isExternalizable() {
  • 0827 return externalizable;
  • 0828 }
  • 0829
  • 0830 /**
  • 0831 * Returns true if represented class implements Serializable, false
  • 0832 * otherwise.
  • 0833 */
  • 0834 boolean isSerializable() {
  • 0835 return serializable;
  • 0836 }
  • 0837
  • 0838 /**
  • 0839 * Returns true if class descriptor represents externalizable class that
  • 0840 * has written its data in 1.2 (block data) format, false otherwise.
  • 0841 */
  • 0842 boolean hasBlockExternalData() {
  • 0843 return hasBlockExternalData;
  • 0844 }
  • 0845
  • 0846 /**
  • 0847 * Returns true if class descriptor represents serializable (but not
  • 0848 * externalizable) class which has written its data via a custom
  • 0849 * writeObject() method, false otherwise.
  • 0850 */
  • 0851 boolean hasWriteObjectData() {
  • 0852 return hasWriteObjectData;
  • 0853 }
  • 0854
  • 0855 /**
  • 0856 * Returns true if represented class is serializable/externalizable and can
  • 0857 * be instantiated by the serialization runtime--i.e., if it is
  • 0858 * externalizable and defines a public no-arg constructor, or if it is
  • 0859 * non-externalizable and its first non-serializable superclass defines an
  • 0860 * accessible no-arg constructor. Otherwise, returns false.
  • 0861 */
  • 0862 boolean isInstantiable() {
  • 0863 return (cons != null);
  • 0864 }
  • 0865
  • 0866 /**
  • 0867 * Returns true if represented class is serializable (but not
  • 0868 * externalizable) and defines a conformant writeObject method. Otherwise,
  • 0869 * returns false.
  • 0870 */
  • 0871 boolean hasWriteObjectMethod() {
  • 0872 return (writeObjectMethod != null);
  • 0873 }
  • 0874
  • 0875 /**
  • 0876 * Returns true if represented class is serializable (but not
  • 0877 * externalizable) and defines a conformant readObject method. Otherwise,
  • 0878 * returns false.
  • 0879 */
  • 0880 boolean hasReadObjectMethod() {
  • 0881 return (readObjectMethod != null);
  • 0882 }
  • 0883
  • 0884 /**
  • 0885 * Returns true if represented class is serializable (but not
  • 0886 * externalizable) and defines a conformant readObjectNoData method.
  • 0887 * Otherwise, returns false.
  • 0888 */
  • 0889 boolean hasReadObjectNoDataMethod() {
  • 0890 return (readObjectNoDataMethod != null);
  • 0891 }
  • 0892
  • 0893 /**
  • 0894 * Returns true if represented class is serializable or externalizable and
  • 0895 * defines a conformant writeReplace method. Otherwise, returns false.
  • 0896 */
  • 0897 boolean hasWriteReplaceMethod() {
  • 0898 return (writeReplaceMethod != null);
  • 0899 }
  • 0900
  • 0901 /**
  • 0902 * Returns true if represented class is serializable or externalizable and
  • 0903 * defines a conformant readResolve method. Otherwise, returns false.
  • 0904 */
  • 0905 boolean hasReadResolveMethod() {
  • 0906 return (readResolveMethod != null);
  • 0907 }
  • 0908
  • 0909 /**
  • 0910 * Creates a new instance of the represented class. If the class is
  • 0911 * externalizable, invokes its public no-arg constructor; otherwise, if the
  • 0912 * class is serializable, invokes the no-arg constructor of the first
  • 0913 * non-serializable superclass. Throws UnsupportedOperationException if
  • 0914 * this class descriptor is not associated with a class, if the associated
  • 0915 * class is non-serializable or if the appropriate no-arg constructor is
  • 0916 * inaccessible/unavailable.
  • 0917 */
  • 0918 Object newInstance()
  • 0919 throws InstantiationException, InvocationTargetException,
  • 0920 UnsupportedOperationException
  • 0921 {
  • 0922 if (cons != null) {
  • 0923 try {
  • 0924 return cons.newInstance();
  • 0925 } catch (IllegalAccessException ex) {
  • 0926 // should not occur, as access checks have been suppressed
  • 0927 throw new InternalError();
  • 0928 }
  • 0929 } else {
  • 0930 throw new UnsupportedOperationException();
  • 0931 }
  • 0932 }
  • 0933
  • 0934 /**
  • 0935 * Invokes the writeObject method of the represented serializable class.
  • 0936 * Throws UnsupportedOperationException if this class descriptor is not
  • 0937 * associated with a class, or if the class is externalizable,
  • 0938 * non-serializable or does not define writeObject.
  • 0939 */
  • 0940 void invokeWriteObject(Object obj, ObjectOutputStream out)
  • 0941 throws IOException, UnsupportedOperationException
  • 0942 {
  • 0943 if (writeObjectMethod != null) {
  • 0944 try {
  • 0945 writeObjectMethod.invoke(obj, new Object[]{ out });
  • 0946 } catch (InvocationTargetException ex) {
  • 0947 Throwable th = ex.getTargetException();
  • 0948 if (th instanceof IOException) {
  • 0949 throw (IOException) th;
  • 0950 } else {
  • 0951 throwMiscException(th);
  • 0952 }
  • 0953 } catch (IllegalAccessException ex) {
  • 0954 // should not occur, as access checks have been suppressed
  • 0955 throw new InternalError();
  • 0956 }
  • 0957 } else {
  • 0958 throw new UnsupportedOperationException();
  • 0959 }
  • 0960 }
  • 0961
  • 0962 /**
  • 0963 * Invokes the readObject method of the represented serializable class.
  • 0964 * Throws UnsupportedOperationException if this class descriptor is not
  • 0965 * associated with a class, or if the class is externalizable,
  • 0966 * non-serializable or does not define readObject.
  • 0967 */
  • 0968 void invokeReadObject(Object obj, ObjectInputStream in)
  • 0969 throws ClassNotFoundException, IOException,
  • 0970 UnsupportedOperationException
  • 0971 {
  • 0972 if (readObjectMethod != null) {
  • 0973 try {
  • 0974 readObjectMethod.invoke(obj, new Object[]{ in });
  • 0975 } catch (InvocationTargetException ex) {
  • 0976 Throwable th = ex.getTargetException();
  • 0977 if (th instanceof ClassNotFoundException) {
  • 0978 throw (ClassNotFoundException) th;
  • 0979 } else if (th instanceof IOException) {
  • 0980 throw (IOException) th;
  • 0981 } else {
  • 0982 throwMiscException(th);
  • 0983 }
  • 0984 } catch (IllegalAccessException ex) {
  • 0985 // should not occur, as access checks have been suppressed
  • 0986 throw new InternalError();
  • 0987 }
  • 0988 } else {
  • 0989 throw new UnsupportedOperationException();
  • 0990 }
  • 0991 }
  • 0992
  • 0993 /**
  • 0994 * Invokes the readObjectNoData method of the represented serializable
  • 0995 * class. Throws UnsupportedOperationException if this class descriptor is
  • 0996 * not associated with a class, or if the class is externalizable,
  • 0997 * non-serializable or does not define readObjectNoData.
  • 0998 */
  • 0999 void invokeReadObjectNoData(Object obj)
  • 1000 throws IOException, UnsupportedOperationException
  • 1001 {
  • 1002 if (readObjectNoDataMethod != null) {
  • 1003 try {
  • 1004 readObjectNoDataMethod.invoke(obj, (Object[]) null);
  • 1005 } catch (InvocationTargetException ex) {
  • 1006 Throwable th = ex.getTargetException();
  • 1007 if (th instanceof ObjectStreamException) {
  • 1008 throw (ObjectStreamException) th;
  • 1009 } else {
  • 1010 throwMiscException(th);
  • 1011 }
  • 1012 } catch (IllegalAccessException ex) {
  • 1013 // should not occur, as access checks have been suppressed
  • 1014 throw new InternalError();
  • 1015 }
  • 1016 } else {
  • 1017 throw new UnsupportedOperationException();
  • 1018 }
  • 1019 }
  • 1020
  • 1021 /**
  • 1022 * Invokes the writeReplace method of the represented serializable class and
  • 1023 * returns the result. Throws UnsupportedOperationException if this class
  • 1024 * descriptor is not associated with a class, or if the class is
  • 1025 * non-serializable or does not define writeReplace.
  • 1026 */
  • 1027 Object invokeWriteReplace(Object obj)
  • 1028 throws IOException, UnsupportedOperationException
  • 1029 {
  • 1030 if (writeReplaceMethod != null) {
  • 1031 try {
  • 1032 return writeReplaceMethod.invoke(obj, (Object[]) null);
  • 1033 } catch (InvocationTargetException ex) {
  • 1034 Throwable th = ex.getTargetException();
  • 1035 if (th instanceof ObjectStreamException) {
  • 1036 throw (ObjectStreamException) th;
  • 1037 } else {
  • 1038 throwMiscException(th);
  • 1039 throw new InternalError(); // never reached
  • 1040 }
  • 1041 } catch (IllegalAccessException ex) {
  • 1042 // should not occur, as access checks have been suppressed
  • 1043 throw new InternalError();
  • 1044 }
  • 1045 } else {
  • 1046 throw new UnsupportedOperationException();
  • 1047 }
  • 1048 }
  • 1049
  • 1050 /**
  • 1051 * Invokes the readResolve method of the represented serializable class and
  • 1052 * returns the result. Throws UnsupportedOperationException if this class
  • 1053 * descriptor is not associated with a class, or if the class is
  • 1054 * non-serializable or does not define readResolve.
  • 1055 */
  • 1056 Object invokeReadResolve(Object obj)
  • 1057 throws IOException, UnsupportedOperationException
  • 1058 {
  • 1059 if (readResolveMethod != null) {
  • 1060 try {
  • 1061 return readResolveMethod.invoke(obj, (Object[]) null);
  • 1062 } catch (InvocationTargetException ex) {
  • 1063 Throwable th = ex.getTargetException();
  • 1064 if (th instanceof ObjectStreamException) {
  • 1065 throw (ObjectStreamException) th;
  • 1066 } else {
  • 1067 throwMiscException(th);
  • 1068 throw new InternalError(); // never reached
  • 1069 }
  • 1070 } catch (IllegalAccessException ex) {
  • 1071 // should not occur, as access checks have been suppressed
  • 1072 throw new InternalError();
  • 1073 }
  • 1074 } else {
  • 1075 throw new UnsupportedOperationException();
  • 1076 }
  • 1077 }
  • 1078
  • 1079 /**
  • 1080 * Class representing the portion of an object's serialized form allotted
  • 1081 * to data described by a given class descriptor. If "hasData" is false,
  • 1082 * the object's serialized form does not contain data associated with the
  • 1083 * class descriptor.
  • 1084 */
  • 1085 static class ClassDataSlot {
  • 1086
  • 1087 /** class descriptor "occupying" this slot */
  • 1088 final ObjectStreamClass desc;
  • 1089 /** true if serialized form includes data for this slot's descriptor */
  • 1090 final boolean hasData;
  • 1091
  • 1092 ClassDataSlot(ObjectStreamClass desc, boolean hasData) {
  • 1093 this.desc = desc;
  • 1094 this.hasData = hasData;
  • 1095 }
  • 1096 }
  • 1097
  • 1098 /**
  • 1099 * Returns array of ClassDataSlot instances representing the data layout
  • 1100 * (including superclass data) for serialized objects described by this
  • 1101 * class descriptor. ClassDataSlots are ordered by inheritance with those
  • 1102 * containing "higher" superclasses appearing first. The final
  • 1103 * ClassDataSlot contains a reference to this descriptor.
  • 1104 */
  • 1105 ClassDataSlot[] getClassDataLayout() throws InvalidClassException {
  • 1106 // REMIND: synchronize instead of relying on volatile?
  • 1107 if (dataLayout == null) {
  • 1108 dataLayout = getClassDataLayout0();
  • 1109 }
  • 1110 return dataLayout;
  • 1111 }
  • 1112
  • 1113 private ClassDataSlot[] getClassDataLayout0()
  • 1114 throws InvalidClassException
  • 1115 {
  • 1116 ArrayList slots = new ArrayList();
  • 1117 Class start = cl, end = cl;
  • 1118
  • 1119 // locate closest non-serializable superclass
  • 1120 while (end != null && Serializable.class.isAssignableFrom(end)) {
  • 1121 end = end.getSuperclass();
  • 1122 }
  • 1123
  • 1124 for (ObjectStreamClass d = this; d != null; d = d.superDesc) {
  • 1125
  • 1126 // search up inheritance hierarchy for class with matching name
  • 1127 String searchName = (d.cl != null) ? d.cl.getName() : d.name;
  • 1128 Class match = null;
  • 1129 for (Class c = start; c != end; c = c.getSuperclass()) {
  • 1130 if (searchName.equals(c.getName())) {
  • 1131 match = c;
  • 1132 break;
  • 1133 }
  • 1134 }
  • 1135
  • 1136 // add "no data" slot for each unmatched class below match
  • 1137 if (match != null) {
  • 1138 for (Class c = start; c != match; c = c.getSuperclass()) {
  • 1139 slots.add(new ClassDataSlot(
  • 1140 ObjectStreamClass.lookup(c, true), false));
  • 1141 }
  • 1142 start = match.getSuperclass();
  • 1143 }
  • 1144
  • 1145 // record descriptor/class pairing
  • 1146 slots.add(new ClassDataSlot(d.getVariantFor(match), true));
  • 1147 }
  • 1148
  • 1149 // add "no data" slot for any leftover unmatched classes
  • 1150 for (Class c = start; c != end; c = c.getSuperclass()) {
  • 1151 slots.add(new ClassDataSlot(
  • 1152 ObjectStreamClass.lookup(c, true), false));
  • 1153 }
  • 1154
  • 1155 // order slots from superclass -> subclass
  • 1156 Collections.reverse(slots);
  • 1157 return (ClassDataSlot[])
  • 1158 slots.toArray(new ClassDataSlot[slots.size()]);
  • 1159 }
  • 1160
  • 1161 /**
  • 1162 * Returns aggregate size (in bytes) of marshalled primitive field values
  • 1163 * for represented class.
  • 1164 */
  • 1165 int getPrimDataSize() {
  • 1166 return primDataSize;
  • 1167 }
  • 1168
  • 1169 /**
  • 1170 * Returns number of non-primitive serializable fields of represented
  • 1171 * class.
  • 1172 */
  • 1173 int getNumObjFields() {
  • 1174 return numObjFields;
  • 1175 }
  • 1176
  • 1177 /**
  • 1178 * Fetches the serializable primitive field values of object obj and
  • 1179 * marshals them into byte array buf starting at offset 0. It is the
  • 1180 * responsibility of the caller to ensure that obj is of the proper type if
  • 1181 * non-null.
  • 1182 */
  • 1183 void getPrimFieldValues(Object obj, byte[] buf) {
  • 1184 fieldRefl.getPrimFieldValues(obj, buf);
  • 1185 }
  • 1186
  • 1187 /**
  • 1188 * Sets the serializable primitive fields of object obj using values
  • 1189 * unmarshalled from byte array buf starting at offset 0. It is the
  • 1190 * responsibility of the caller to ensure that obj is of the proper type if
  • 1191 * non-null.
  • 1192 */
  • 1193 void setPrimFieldValues(Object obj, byte[] buf) {
  • 1194 fieldRefl.setPrimFieldValues(obj, buf);
  • 1195 }
  • 1196
  • 1197 /**
  • 1198 * Fetches the serializable object field values of object obj and stores
  • 1199 * them in array vals starting at offset 0. It is the responsibility of
  • 1200 * the caller to ensure that obj is of the proper type if non-null.
  • 1201 */
  • 1202 void getObjFieldValues(Object obj, Object[] vals) {
  • 1203 fieldRefl.getObjFieldValues(obj, vals);
  • 1204 }
  • 1205
  • 1206 /**
  • 1207 * Sets the serializable object fields of object obj using values from
  • 1208 * array vals starting at offset 0. It is the responsibility of the caller
  • 1209 * to ensure that obj is of the proper type if non-null.
  • 1210 */
  • 1211 void setObjFieldValues(Object obj, Object[] vals) {
  • 1212 fieldRefl.setObjFieldValues(obj, vals);
  • 1213 }
  • 1214
  • 1215 /**
  • 1216 * Calculates and sets serializable field offsets, as well as primitive
  • 1217 * data size and object field count totals. Throws InvalidClassException
  • 1218 * if fields are illegally ordered.
  • 1219 */
  • 1220 private void computeFieldOffsets() throws InvalidClassException {
  • 1221 primDataSize = 0;
  • 1222 numObjFields = 0;
  • 1223 int firstObjIndex = -1;
  • 1224
  • 1225 for (int i = 0; i < fields.length; i++) {
  • 1226 ObjectStreamField f = fields[i];
  • 1227 switch (f.getTypeCode()) {
  • 1228 case 'Z':
  • 1229 case 'B':
  • 1230 f.setOffset(primDataSize++);
  • 1231 break;
  • 1232
  • 1233 case 'C':
  • 1234 case 'S':
  • 1235 f.setOffset(primDataSize);
  • 1236 primDataSize += 2;
  • 1237 break;
  • 1238
  • 1239 case 'I':
  • 1240 case 'F':
  • 1241 f.setOffset(primDataSize);
  • 1242 primDataSize += 4;
  • 1243 break;
  • 1244
  • 1245 case 'J':
  • 1246 case 'D':
  • 1247 f.setOffset(primDataSize);
  • 1248 primDataSize += 8;
  • 1249 break;
  • 1250
  • 1251 case '[':
  • 1252 case 'L':
  • 1253 f.setOffset(numObjFields++);
  • 1254 if (firstObjIndex == -1) {
  • 1255 firstObjIndex = i;
  • 1256 }
  • 1257 break;
  • 1258
  • 1259 default:
  • 1260 throw new InternalError();
  • 1261 }
  • 1262 }
  • 1263 if (firstObjIndex != -1 &&
  • 1264 firstObjIndex + numObjFields != fields.length)
  • 1265 {
  • 1266 throw new InvalidClassException(name, "illegal field order");
  • 1267 }
  • 1268 }
  • 1269
  • 1270 /**
  • 1271 * If given class is the same as the class associated with this class
  • 1272 * descriptor, returns reference to this class descriptor. Otherwise,
  • 1273 * returns variant of this class descriptor bound to given class.
  • 1274 */
  • 1275 private ObjectStreamClass getVariantFor(Class cl)
  • 1276 throws InvalidClassException
  • 1277 {
  • 1278 if (this.cl == cl) {
  • 1279 return this;
  • 1280 }
  • 1281 ObjectStreamClass desc = new ObjectStreamClass();
  • 1282 if (isProxy) {
  • 1283 desc.initProxy(cl, null, superDesc);
  • 1284 } else {
  • 1285 desc.initNonProxy(this, cl, null, superDesc);
  • 1286 }
  • 1287 return desc;
  • 1288 }
  • 1289
  • 1290 /**
  • 1291 * Returns public no-arg constructor of given class, or null if none found.
  • 1292 * Access checks are disabled on the returned constructor (if any), since
  • 1293 * the defining class may still be non-public.
  • 1294 */
  • 1295 private static Constructor getExternalizableConstructor(Class cl) {
  • 1296 try {
  • 1297 Constructor cons = cl.getDeclaredConstructor((Class[]) null);
  • 1298 cons.setAccessible(true);
  • 1299 return ((cons.getModifiers() & Modifier.PUBLIC) != 0) ?
  • 1300 cons : null;
  • 1301 } catch (NoSuchMethodException ex) {
  • 1302 return null;
  • 1303 }
  • 1304 }
  • 1305
  • 1306 /**
  • 1307 * Returns subclass-accessible no-arg constructor of first non-serializable
  • 1308 * superclass, or null if none found. Access checks are disabled on the
  • 1309 * returned constructor (if any).
  • 1310 */
  • 1311 private static Constructor getSerializableConstructor(Class cl) {
  • 1312 Class initCl = cl;
  • 1313 while (Serializable.class.isAssignableFrom(initCl)) {
  • 1314 if ((initCl = initCl.getSuperclass()) == null) {
  • 1315 return null;
  • 1316 }
  • 1317 }
  • 1318 try {
  • 1319 Constructor cons = initCl.getDeclaredConstructor((Class[]) null);
  • 1320 int mods = cons.getModifiers();
  • 1321 if ((mods & Modifier.PRIVATE) != 0 ||
  • 1322 ((mods & (Modifier.PUBLIC | Modifier.PROTECTED)) == 0 &&
  • 1323 !packageEquals(cl, initCl)))
  • 1324 {
  • 1325 return null;
  • 1326 }
  • 1327 cons = reflFactory.newConstructorForSerialization(cl, cons);
  • 1328 cons.setAccessible(true);
  • 1329 return cons;
  • 1330 } catch (NoSuchMethodException ex) {
  • 1331 return null;
  • 1332 }
  • 1333 }
  • 1334
  • 1335 /**
  • 1336 * Returns non-static, non-abstract method with given signature provided it
  • 1337 * is defined by or accessible (via inheritance) by the given class, or
  • 1338 * null if no match found. Access checks are disabled on the returned
  • 1339 * method (if any).
  • 1340 */
  • 1341 private static Method getInheritableMethod(Class cl, String name,
  • 1342 Class[] argTypes,
  • 1343 Class returnType)
  • 1344 {
  • 1345 Method meth = null;
  • 1346 Class defCl = cl;
  • 1347 while (defCl != null) {
  • 1348 try {
  • 1349 meth = defCl.getDeclaredMethod(name, argTypes);
  • 1350 break;
  • 1351 } catch (NoSuchMethodException ex) {
  • 1352 defCl = defCl.getSuperclass();
  • 1353 }
  • 1354 }
  • 1355
  • 1356 if ((meth == null) || (meth.getReturnType() != returnType)) {
  • 1357 return null;
  • 1358 }
  • 1359 meth.setAccessible(true);
  • 1360 int mods = meth.getModifiers();
  • 1361 if ((mods & (Modifier.STATIC | Modifier.ABSTRACT)) != 0) {
  • 1362 return null;
  • 1363 } else if ((mods & (Modifier.PUBLIC | Modifier.PROTECTED)) != 0) {
  • 1364 return meth;
  • 1365 } else if ((mods & Modifier.PRIVATE) != 0) {
  • 1366 return (cl == defCl) ? meth : null;
  • 1367 } else {
  • 1368 return packageEquals(cl, defCl) ? meth : null;
  • 1369 }
  • 1370 }
  • 1371
  • 1372 /**
  • 1373 * Returns non-static private method with given signature defined by given
  • 1374 * class, or null if none found. Access checks are disabled on the
  • 1375 * returned method (if any).
  • 1376 */
  • 1377 private static Method getPrivateMethod(Class cl, String name,
  • 1378 Class[] argTypes,
  • 1379 Class returnType)
  • 1380 {
  • 1381 try {
  • 1382 Method meth = cl.getDeclaredMethod(name, argTypes);
  • 1383 meth.setAccessible(true);
  • 1384 int mods = meth.getModifiers();
  • 1385 return ((meth.getReturnType() == returnType) &&
  • 1386 ((mods & Modifier.STATIC) == 0) &&
  • 1387 ((mods & Modifier.PRIVATE) != 0)) ? meth : null;
  • 1388 } catch (NoSuchMethodException ex) {
  • 1389 return null;
  • 1390 }
  • 1391 }
  • 1392
  • 1393 /**
  • 1394 * Returns true if classes are defined in the same runtime package, false
  • 1395 * otherwise.
  • 1396 */
  • 1397 private static boolean packageEquals(Class cl1, Class cl2) {
  • 1398 return (cl1.getClassLoader() == cl2.getClassLoader() &&
  • 1399 getPackageName(cl1).equals(getPackageName(cl2)));
  • 1400 }
  • 1401
  • 1402 /**
  • 1403 * Returns package name of given class.
  • 1404 */
  • 1405 private static String getPackageName(Class cl) {
  • 1406 String s = cl.getName();
  • 1407 int i = s.lastIndexOf('[');
  • 1408 if (i >= 0) {
  • 1409 s = s.substring(i + 2);
  • 1410 }
  • 1411 i = s.lastIndexOf('.');
  • 1412 return (i >= 0) ? s.substring(0, i) : "";
  • 1413 }
  • 1414
  • 1415 /**
  • 1416 * Compares class names for equality, ignoring package names. Returns true
  • 1417 * if class names equal, false otherwise.
  • 1418 */
  • 1419 private static boolean classNamesEqual(String name1, String name2) {
  • 1420 name1 = name1.substring(name1.lastIndexOf('.') + 1);
  • 1421 name2 = name2.substring(name2.lastIndexOf('.') + 1);
  • 1422 return name1.equals(name2);
  • 1423 }
  • 1424
  • 1425 /**
  • 1426 * Returns JVM type signature for given class.
  • 1427 */
  • 1428 static String getClassSignature(Class cl) {
  • 1429 StringBuilder sbuf = new StringBuilder();
  • 1430 while (cl.isArray()) {
  • 1431 sbuf.append('[');
  • 1432 cl = cl.getComponentType();
  • 1433 }
  • 1434 if (cl.isPrimitive()) {
  • 1435 if (cl == Integer.TYPE) {
  • 1436 sbuf.append('I');
  • 1437 } else if (cl == Byte.TYPE) {
  • 1438 sbuf.append('B');
  • 1439 } else if (cl == Long.TYPE) {
  • 1440 sbuf.append('J');
  • 1441 } else if (cl == Float.TYPE) {
  • 1442 sbuf.append('F');
  • 1443 } else if (cl == Double.TYPE) {
  • 1444 sbuf.append('D');
  • 1445 } else if (cl == Short.TYPE) {
  • 1446 sbuf.append('S');
  • 1447 } else if (cl == Character.TYPE) {
  • 1448 sbuf.append('C');
  • 1449 } else if (cl == Boolean.TYPE) {
  • 1450 sbuf.append('Z');
  • 1451 } else if (cl == Void.TYPE) {
  • 1452 sbuf.append('V');
  • 1453 } else {
  • 1454 throw new InternalError();
  • 1455 }
  • 1456 } else {
  • 1457 sbuf.append('L' + cl.getName().replace('.', '/') + ';');
  • 1458 }
  • 1459 return sbuf.toString();
  • 1460 }
  • 1461
  • 1462 /**
  • 1463 * Returns JVM type signature for given list of parameters and return type.
  • 1464 */
  • 1465 private static String getMethodSignature(Class[] paramTypes,
  • 1466 Class retType)
  • 1467 {
  • 1468 StringBuilder sbuf = new StringBuilder();
  • 1469 sbuf.append('(');
  • 1470 for (int i = 0; i < paramTypes.length; i++) {
  • 1471 sbuf.append(getClassSignature(paramTypes[i]));
  • 1472 }
  • 1473 sbuf.append(')');
  • 1474 sbuf.append(getClassSignature(retType));
  • 1475 return sbuf.toString();
  • 1476 }
  • 1477
  • 1478 /**
  • 1479 * Convenience method for throwing an exception that is either a
  • 1480 * RuntimeException, Error, or of some unexpected type (in which case it is
  • 1481 * wrapped inside an IOException).
  • 1482 */
  • 1483 private static void throwMiscException(Throwable th) throws IOException {
  • 1484 if (th instanceof RuntimeException) {
  • 1485 throw (RuntimeException) th;
  • 1486 } else if (th instanceof Error) {
  • 1487 throw (Error) th;
  • 1488 } else {
  • 1489 IOException ex = new IOException("unexpected exception type");
  • 1490 ex.initCause(th);
  • 1491 throw ex;
  • 1492 }
  • 1493 }
  • 1494
  • 1495 /**
  • 1496 * Returns ObjectStreamField array describing the serializable fields of
  • 1497 * the given class. Serializable fields backed by an actual field of the
  • 1498 * class are represented by ObjectStreamFields with corresponding non-null
  • 1499 * Field objects. Throws InvalidClassException if the (explicitly
  • 1500 * declared) serializable fields are invalid.
  • 1501 */
  • 1502 private static ObjectStreamField[] getSerialFields(Class cl)
  • 1503 throws InvalidClassException
  • 1504 {
  • 1505 ObjectStreamField[] fields;
  • 1506 if (Serializable.class.isAssignableFrom(cl) &&
  • 1507 !Externalizable.class.isAssignableFrom(cl) &&
  • 1508 !Proxy.isProxyClass(cl) &&
  • 1509 !cl.isInterface())
  • 1510 {
  • 1511 if ((fields = getDeclaredSerialFields(cl)) == null) {
  • 1512 fields = getDefaultSerialFields(cl);
  • 1513 }
  • 1514 Arrays.sort(fields);
  • 1515 } else {
  • 1516 fields = NO_FIELDS;
  • 1517 }
  • 1518 return fields;
  • 1519 }
  • 1520
  • 1521 /**
  • 1522 * Returns serializable fields of given class as defined explicitly by a
  • 1523 * "serialPersistentFields" field, or null if no appropriate
  • 1524 * "serialPersistentFields" field is defined. Serializable fields backed
  • 1525 * by an actual field of the class are represented by ObjectStreamFields
  • 1526 * with corresponding non-null Field objects. For compatibility with past
  • 1527 * releases, a "serialPersistentFields" field with a null value is
  • 1528 * considered equivalent to not declaring "serialPersistentFields". Throws
  • 1529 * InvalidClassException if the declared serializable fields are
  • 1530 * invalid--e.g., if multiple fields share the same name.
  • 1531 */
  • 1532 private static ObjectStreamField[] getDeclaredSerialFields(Class cl)
  • 1533 throws InvalidClassException
  • 1534 {
  • 1535 ObjectStreamField[] serialPersistentFields = null;
  • 1536 try {
  • 1537 Field f = cl.getDeclaredField("serialPersistentFields");
  • 1538 int mask = Modifier.PRIVATE | Modifier.STATIC | Modifier.FINAL;
  • 1539 if ((f.getModifiers() & mask) == mask) {
  • 1540 f.setAccessible(true);
  • 1541 serialPersistentFields = (ObjectStreamField[]) f.get(null);
  • 1542 }
  • 1543 } catch (Exception ex) {
  • 1544 }
  • 1545 if (serialPersistentFields == null) {
  • 1546 return null;
  • 1547 } else if (serialPersistentFields.length == 0) {
  • 1548 return NO_FIELDS;
  • 1549 }
  • 1550
  • 1551 ObjectStreamField[] boundFields =
  • 1552 new ObjectStreamField[serialPersistentFields.length];
  • 1553 Set fieldNames = new HashSet(serialPersistentFields.length);
  • 1554
  • 1555 for (int i = 0; i < serialPersistentFields.length; i++) {
  • 1556 ObjectStreamField spf = serialPersistentFields[i];
  • 1557
  • 1558 String fname = spf.getName();
  • 1559 if (fieldNames.contains(fname)) {
  • 1560 throw new InvalidClassException(
  • 1561 "multiple serializable fields named " + fname);
  • 1562 }
  • 1563 fieldNames.add(fname);
  • 1564
  • 1565 try {
  • 1566 Field f = cl.getDeclaredField(fname);
  • 1567 if ((f.getType() == spf.getType()) &&
  • 1568 ((f.getModifiers() & Modifier.STATIC) == 0))
  • 1569 {
  • 1570 boundFields[i] =
  • 1571 new ObjectStreamField(f, spf.isUnshared(), true);
  • 1572 }
  • 1573 } catch (NoSuchFieldException ex) {
  • 1574 }
  • 1575 if (boundFields[i] == null) {
  • 1576 boundFields[i] = new ObjectStreamField(
  • 1577 fname, spf.getType(), spf.isUnshared());
  • 1578 }
  • 1579 }
  • 1580 return boundFields;
  • 1581 }
  • 1582
  • 1583 /**
  • 1584 * Returns array of ObjectStreamFields corresponding to all non-static
  • 1585 * non-transient fields declared by given class. Each ObjectStreamField
  • 1586 * contains a Field object for the field it represents. If no default
  • 1587 * serializable fields exist, NO_FIELDS is returned.
  • 1588 */
  • 1589 private static ObjectStreamField[] getDefaultSerialFields(Class cl) {
  • 1590 Field[] clFields = cl.getDeclaredFields();
  • 1591 ArrayList list = new ArrayList();
  • 1592 int mask = Modifier.STATIC | Modifier.TRANSIENT;
  • 1593
  • 1594 for (int i = 0; i < clFields.length; i++) {
  • 1595 if ((clFields[i].getModifiers() & mask) == 0) {
  • 1596 list.add(new ObjectStreamField(clFields[i], false, true));
  • 1597 }
  • 1598 }
  • 1599 int size = list.size();
  • 1600 return (size == 0) ? NO_FIELDS :
  • 1601 (ObjectStreamField[]) list.toArray(new ObjectStreamField[size]);
  • 1602 }
  • 1603
  • 1604 /**
  • 1605 * Returns explicit serial version UID value declared by given class, or
  • 1606 * null if none.
  • 1607 */
  • 1608 private static Long getDeclaredSUID(Class cl) {
  • 1609 try {
  • 1610 Field f = cl.getDeclaredField("serialVersionUID");
  • 1611 int mask = Modifier.STATIC | Modifier.FINAL;
  • 1612 if ((f.getModifiers() & mask) == mask) {
  • 1613 f.setAccessible(true);
  • 1614 return Long.valueOf(f.getLong(null));
  • 1615 }
  • 1616 } catch (Exception ex) {
  • 1617 }
  • 1618 return null;
  • 1619 }
  • 1620
  • 1621 /**
  • 1622 * Computes the default serial version UID value for the given class.
  • 1623 */
  • 1624 private static long computeDefaultSUID(Class cl) {
  • 1625 if (!Serializable.class.isAssignableFrom(cl) || Proxy.isProxyClass(cl))
  • 1626 {
  • 1627 return 0L;
  • 1628 }
  • 1629
  • 1630 try {
  • 1631 ByteArrayOutputStream bout = new ByteArrayOutputStream();
  • 1632 DataOutputStream dout = new DataOutputStream(bout);
  • 1633
  • 1634 dout.writeUTF(cl.getName());
  • 1635
  • 1636 int classMods = cl.getModifiers() &
  • 1637 (Modifier.PUBLIC | Modifier.FINAL |
  • 1638 Modifier.INTERFACE | Modifier.ABSTRACT);
  • 1639
  • 1640 /*
  • 1641 * compensate for javac bug in which ABSTRACT bit was set for an
  • 1642 * interface only if the interface declared methods
  • 1643 */
  • 1644 Method[] methods = cl.getDeclaredMethods();
  • 1645 if ((classMods & Modifier.INTERFACE) != 0) {
  • 1646 classMods = (methods.length > 0) ?
  • 1647 (classMods | Modifier.ABSTRACT) :
  • 1648 (classMods & ~Modifier.ABSTRACT);
  • 1649 }
  • 1650 dout.writeInt(classMods);
  • 1651
  • 1652 if (!cl.isArray()) {
  • 1653 /*
  • 1654 * compensate for change in 1.2FCS in which
  • 1655 * Class.getInterfaces() was modified to return Cloneable and
  • 1656 * Serializable for array classes.
  • 1657 */
  • 1658 Class[] interfaces = cl.getInterfaces();
  • 1659 String[] ifaceNames = new String[interfaces.length];
  • 1660 for (int i = 0; i < interfaces.length; i++) {
  • 1661 ifaceNames[i] = interfaces[i].getName();
  • 1662 }
  • 1663 Arrays.sort(ifaceNames);
  • 1664 for (int i = 0; i < ifaceNames.length; i++) {
  • 1665 dout.writeUTF(ifaceNames[i]);
  • 1666 }
  • 1667 }
  • 1668
  • 1669 Field[] fields = cl.getDeclaredFields();
  • 1670 MemberSignature[] fieldSigs = new MemberSignature[fields.length];
  • 1671 for (int i = 0; i < fields.length; i++) {
  • 1672 fieldSigs[i] = new MemberSignature(fields[i]);
  • 1673 }
  • 1674 Arrays.sort(fieldSigs, new Comparator() {
  • 1675 public int compare(Object o1, Object o2) {
  • 1676 String name1 = ((MemberSignature) o1).name;
  • 1677 String name2 = ((MemberSignature) o2).name;
  • 1678 return name1.compareTo(name2);
  • 1679 }
  • 1680 });
  • 1681 for (int i = 0; i < fieldSigs.length; i++) {
  • 1682 MemberSignature sig = fieldSigs[i];
  • 1683 int mods = sig.member.getModifiers() &
  • 1684 (Modifier.PUBLIC | Modifier.PRIVATE | Modifier.PROTECTED |
  • 1685 Modifier.STATIC | Modifier.FINAL | Modifier.VOLATILE |
  • 1686 Modifier.TRANSIENT);
  • 1687 if (((mods & Modifier.PRIVATE) == 0) ||
  • 1688 ((mods & (Modifier.STATIC | Modifier.TRANSIENT)) == 0))
  • 1689 {
  • 1690 dout.writeUTF(sig.name);
  • 1691 dout.writeInt(mods);
  • 1692 dout.writeUTF(sig.signature);
  • 1693 }
  • 1694 }
  • 1695
  • 1696 if (hasStaticInitializer(cl)) {
  • 1697 dout.writeUTF("<clinit>");
  • 1698 dout.writeInt(Modifier.STATIC);
  • 1699 dout.writeUTF("()V");
  • 1700 }
  • 1701
  • 1702 Constructor[] cons = cl.getDeclaredConstructors();
  • 1703 MemberSignature[] consSigs = new MemberSignature[cons.length];
  • 1704 for (int i = 0; i < cons.length; i++) {
  • 1705 consSigs[i] = new MemberSignature(cons[i]);
  • 1706 }
  • 1707 Arrays.sort(consSigs, new Comparator() {
  • 1708 public int compare(Object o1, Object o2) {
  • 1709 String sig1 = ((MemberSignature) o1).signature;
  • 1710 String sig2 = ((MemberSignature) o2).signature;
  • 1711 return sig1.compareTo(sig2);
  • 1712 }
  • 1713 });
  • 1714 for (int i = 0; i < consSigs.length; i++) {
  • 1715 MemberSignature sig = consSigs[i];
  • 1716 int mods = sig.member.getModifiers() &
  • 1717 (Modifier.PUBLIC | Modifier.PRIVATE | Modifier.PROTECTED |
  • 1718 Modifier.STATIC | Modifier.FINAL |
  • 1719 Modifier.SYNCHRONIZED | Modifier.NATIVE |
  • 1720 Modifier.ABSTRACT | Modifier.STRICT);
  • 1721 if ((mods & Modifier.PRIVATE) == 0) {
  • 1722 dout.writeUTF("<init>");
  • 1723 dout.writeInt(mods);
  • 1724 dout.writeUTF(sig.signature.replace('/', '.'));
  • 1725 }
  • 1726 }
  • 1727
  • 1728 MemberSignature[] methSigs = new MemberSignature[methods.length];
  • 1729 for (int i = 0; i < methods.length; i++) {
  • 1730 methSigs[i] = new MemberSignature(methods[i]);
  • 1731 }
  • 1732 Arrays.sort(methSigs, new Comparator() {
  • 1733 public int compare(Object o1, Object o2) {
  • 1734 MemberSignature ms1 = (MemberSignature) o1;
  • 1735 MemberSignature ms2 = (MemberSignature) o2;
  • 1736 int comp = ms1.name.compareTo(ms2.name);
  • 1737 if (comp == 0) {
  • 1738 comp = ms1.signature.compareTo(ms2.signature);
  • 1739 }
  • 1740 return comp;
  • 1741 }
  • 1742 });
  • 1743 for (int i = 0; i < methSigs.length; i++) {
  • 1744 MemberSignature sig = methSigs[i];
  • 1745 int mods = sig.member.getModifiers() &
  • 1746 (Modifier.PUBLIC | Modifier.PRIVATE | Modifier.PROTECTED |
  • 1747 Modifier.STATIC | Modifier.FINAL |
  • 1748 Modifier.SYNCHRONIZED | Modifier.NATIVE |
  • 1749 Modifier.ABSTRACT | Modifier.STRICT);
  • 1750 if ((mods & Modifier.PRIVATE) == 0) {
  • 1751 dout.writeUTF(sig.name);
  • 1752 dout.writeInt(mods);
  • 1753 dout.writeUTF(sig.signature.replace('/', '.'));
  • 1754 }
  • 1755 }
  • 1756
  • 1757 dout.flush();
  • 1758
  • 1759 MessageDigest md = MessageDigest.getInstance("SHA");
  • 1760 byte[] hashBytes = md.digest(bout.toByteArray());
  • 1761 long hash = 0;
  • 1762 for (int i = Math.min(hashBytes.length, 8) - 1; i >= 0; i--) {
  • 1763 hash = (hash << 8) | (hashBytes[i] & 0xFF);
  • 1764 }
  • 1765 return hash;
  • 1766 } catch (IOException ex) {
  • 1767 throw new InternalError();
  • 1768 } catch (NoSuchAlgorithmException ex) {
  • 1769 throw new SecurityException(ex.getMessage());
  • 1770 }
  • 1771 }
  • 1772
  • 1773 /**
  • 1774 * Returns true if the given class defines a static initializer method,
  • 1775 * false otherwise.
  • 1776 */
  • 1777 private native static boolean hasStaticInitializer(Class cl);
  • 1778
  • 1779 /**
  • 1780 * Class for computing and caching field/constructor/method signatures
  • 1781 * during serialVersionUID calculation.
  • 1782 */
  • 1783 private static class MemberSignature {
  • 1784
  • 1785 public final Member member;
  • 1786 public final String name;
  • 1787 public final String signature;
  • 1788
  • 1789 public MemberSignature(Field field) {
  • 1790 member = field;
  • 1791 name = field.getName();
  • 1792 signature = getClassSignature(field.getType());
  • 1793 }
  • 1794
  • 1795 public MemberSignature(Constructor cons) {
  • 1796 member = cons;
  • 1797 name = cons.getName();
  • 1798 signature = getMethodSignature(
  • 1799 cons.getParameterTypes(), Void.TYPE);
  • 1800 }
  • 1801
  • 1802 public MemberSignature(Method meth) {
  • 1803 member = meth;
  • 1804 name = meth.getName();
  • 1805 signature = getMethodSignature(
  • 1806 meth.getParameterTypes(), meth.getReturnType());
  • 1807 }
  • 1808 }
  • 1809
  • 1810 /**
  • 1811 * Class for setting and retrieving serializable field values in batch.
  • 1812 */
  • 1813 // REMIND: dynamically generate these?
  • 1814 private static class FieldReflector {
  • 1815
  • 1816 /** handle for performing unsafe operations */
  • 1817 private static final Unsafe unsafe = Unsafe.getUnsafe();
  • 1818
  • 1819 /** fields to operate on */
  • 1820 private final ObjectStreamField[] fields;
  • 1821 /** number of primitive fields */
  • 1822 private final int numPrimFields;
  • 1823 /** unsafe field keys */
  • 1824 private final long[] keys;
  • 1825 /** field data offsets */
  • 1826 private final int[] offsets;
  • 1827 /** field type codes */
  • 1828 private final char[] typeCodes;
  • 1829 /** field types */
  • 1830 private final Class[] types;
  • 1831
  • 1832 /**
  • 1833 * Constructs FieldReflector capable of setting/getting values from the
  • 1834 * subset of fields whose ObjectStreamFields contain non-null
  • 1835 * reflective Field objects. ObjectStreamFields with null Fields are
  • 1836 * treated as filler, for which get operations return default values
  • 1837 * and set operations discard given values.
  • 1838 */
  • 1839 FieldReflector(ObjectStreamField[] fields) {
  • 1840 this.fields = fields;
  • 1841 int nfields = fields.length;
  • 1842 keys = new long[nfields];
  • 1843 offsets = new int[nfields];
  • 1844 typeCodes = new char[nfields];
  • 1845 ArrayList typeList = new ArrayList();
  • 1846
  • 1847 for (int i = 0; i < nfields; i++) {
  • 1848 ObjectStreamField f = fields[i];
  • 1849 Field rf = f.getField();
  • 1850 keys[i] = (rf != null) ?
  • 1851 unsafe.objectFieldOffset(rf) : Unsafe.INVALID_FIELD_OFFSET;
  • 1852 offsets[i] = f.getOffset();
  • 1853 typeCodes[i] = f.getTypeCode();
  • 1854 if (!f.isPrimitive()) {
  • 1855 typeList.add((rf != null) ? rf.getType() : null);
  • 1856 }
  • 1857 }
  • 1858
  • 1859 types = (Class[]) typeList.toArray(new Class[typeList.size()]);
  • 1860 numPrimFields = nfields - types.length;
  • 1861 }
  • 1862
  • 1863 /**
  • 1864 * Returns list of ObjectStreamFields representing fields operated on
  • 1865 * by this reflector. The shared/unshared values and Field objects
  • 1866 * contained by ObjectStreamFields in the list reflect their bindings
  • 1867 * to locally defined serializable fields.
  • 1868 */
  • 1869 ObjectStreamField[] getFields() {
  • 1870 return fields;
  • 1871 }
  • 1872
  • 1873 /**
  • 1874 * Fetches the serializable primitive field values of object obj and
  • 1875 * marshals them into byte array buf starting at offset 0. The caller
  • 1876 * is responsible for ensuring that obj is of the proper type.
  • 1877 */
  • 1878 void getPrimFieldValues(Object obj, byte[] buf) {
  • 1879 if (obj == null) {
  • 1880 throw new NullPointerException();
  • 1881 }
  • 1882 /* assuming checkDefaultSerialize() has been called on the class
  • 1883 * descriptor this FieldReflector was obtained from, no field keys
  • 1884 * in array should be equal to Unsafe.INVALID_FIELD_OFFSET.
  • 1885 */
  • 1886 for (int i = 0; i < numPrimFields; i++) {
  • 1887 long key = keys[i];
  • 1888 int off = offsets[i];
  • 1889 switch (typeCodes[i]) {
  • 1890 case 'Z':
  • 1891 Bits.putBoolean(buf, off, unsafe.getBoolean(obj, key));
  • 1892 break;
  • 1893
  • 1894 case 'B':
  • 1895 buf[off] = unsafe.getByte(obj, key);
  • 1896 break;
  • 1897
  • 1898 case 'C':
  • 1899 Bits.putChar(buf, off, unsafe.getChar(obj, key));
  • 1900 break;
  • 1901
  • 1902 case 'S':
  • 1903 Bits.putShort(buf, off, unsafe.getShort(obj, key));
  • 1904 break;
  • 1905
  • 1906 case 'I':
  • 1907 Bits.putInt(buf, off, unsafe.getInt(obj, key));
  • 1908 break;
  • 1909
  • 1910 case 'F':
  • 1911 Bits.putFloat(buf, off, unsafe.getFloat(obj, key));
  • 1912 break;
  • 1913
  • 1914 case 'J':
  • 1915 Bits.putLong(buf, off, unsafe.getLong(obj, key));
  • 1916 break;
  • 1917
  • 1918 case 'D':
  • 1919 Bits.putDouble(buf, off, unsafe.getDouble(obj, key));
  • 1920 break;
  • 1921
  • 1922 default:
  • 1923 throw new InternalError();
  • 1924 }
  • 1925 }
  • 1926 }
  • 1927
  • 1928 /**
  • 1929 * Sets the serializable primitive fields of object obj using values
  • 1930 * unmarshalled from byte array buf starting at offset 0. The caller
  • 1931 * is responsible for ensuring that obj is of the proper type.
  • 1932 */
  • 1933 void setPrimFieldValues(Object obj, byte[] buf) {
  • 1934 if (obj == null) {
  • 1935 throw new NullPointerException();
  • 1936 }
  • 1937 for (int i = 0; i < numPrimFields; i++) {
  • 1938 long key = keys[i];
  • 1939 if (key == Unsafe.INVALID_FIELD_OFFSET) {
  • 1940 continue; // discard value
  • 1941 }
  • 1942 int off = offsets[i];
  • 1943 switch (typeCodes[i]) {
  • 1944 case 'Z':
  • 1945 unsafe.putBoolean(obj, key, Bits.getBoolean(buf, off));
  • 1946 break;
  • 1947
  • 1948 case 'B':
  • 1949 unsafe.putByte(obj, key, buf[off]);
  • 1950 break;
  • 1951
  • 1952 case 'C':
  • 1953 unsafe.putChar(obj, key, Bits.getChar(buf, off));
  • 1954 break;
  • 1955
  • 1956 case 'S':
  • 1957 unsafe.putShort(obj, key, Bits.getShort(buf, off));
  • 1958 break;
  • 1959
  • 1960 case 'I':
  • 1961 unsafe.putInt(obj, key, Bits.getInt(buf, off));
  • 1962 break;
  • 1963
  • 1964 case 'F':
  • 1965 unsafe.putFloat(obj, key, Bits.getFloat(buf, off));
  • 1966 break;
  • 1967
  • 1968 case 'J':
  • 1969 unsafe.putLong(obj, key, Bits.getLong(buf, off));
  • 1970 break;
  • 1971
  • 1972 case 'D':
  • 1973 unsafe.putDouble(obj, key, Bits.getDouble(buf, off));
  • 1974 break;
  • 1975
  • 1976 default:
  • 1977 throw new InternalError();
  • 1978 }
  • 1979 }
  • 1980 }
  • 1981
  • 1982 /**
  • 1983 * Fetches the serializable object field values of object obj and
  • 1984 * stores them in array vals starting at offset 0. The caller is
  • 1985 * responsible for ensuring that obj is of the proper type.
  • 1986 */
  • 1987 void getObjFieldValues(Object obj, Object[] vals) {
  • 1988 if (obj == null) {
  • 1989 throw new NullPointerException();
  • 1990 }
  • 1991 /* assuming checkDefaultSerialize() has been called on the class
  • 1992 * descriptor this FieldReflector was obtained from, no field keys
  • 1993 * in array should be equal to Unsafe.INVALID_FIELD_OFFSET.
  • 1994 */
  • 1995 for (int i = numPrimFields; i < fields.length; i++) {
  • 1996 switch (typeCodes[i]) {
  • 1997 case 'L':
  • 1998 case '[':
  • 1999 vals[offsets[i]] = unsafe.getObject(obj, keys[i]);
  • 2000 break;
  • 2001
  • 2002 default:
  • 2003 throw new InternalError();
  • 2004 }
  • 2005 }
  • 2006 }
  • 2007
  • 2008 /**
  • 2009 * Sets the serializable object fields of object obj using values from
  • 2010 * array vals starting at offset 0. The caller is responsible for
  • 2011 * ensuring that obj is of the proper type; however, attempts to set a
  • 2012 * field with a value of the wrong type will trigger an appropriate
  • 2013 * ClassCastException.
  • 2014 */
  • 2015 void setObjFieldValues(Object obj, Object[] vals) {
  • 2016 if (obj == null) {
  • 2017 throw new NullPointerException();
  • 2018 }
  • 2019 for (int i = numPrimFields; i < fields.length; i++) {
  • 2020 long key = keys[i];
  • 2021 if (key == Unsafe.INVALID_FIELD_OFFSET) {
  • 2022 continue; // discard value
  • 2023 }
  • 2024 switch (typeCodes[i]) {
  • 2025 case 'L':
  • 2026 case '[':
  • 2027 Object val = vals[offsets[i]];
  • 2028 if (val != null &&
  • 2029 !types[i - numPrimFields].isInstance(val))
  • 2030 {
  • 2031 Field f = fields[i].getField();
  • 2032 throw new ClassCastException(
  • 2033 "cannot assign instance of " +
  • 2034 val.getClass().getName() + " to field " +
  • 2035 f.getDeclaringClass().getName() + "." +
  • 2036 f.getName() + " of type " +
  • 2037 f.getType().getName() + " in instance of " +
  • 2038 obj.getClass().getName());
  • 2039 }
  • 2040 unsafe.putObject(obj, key, val);
  • 2041 break;
  • 2042
  • 2043 default:
  • 2044 throw new InternalError();
  • 2045 }
  • 2046 }
  • 2047 }
  • 2048 }
  • 2049
  • 2050 /**
  • 2051 * Matches given set of serializable fields with serializable fields
  • 2052 * described by the given local class descriptor, and returns a
  • 2053 * FieldReflector instance capable of setting/getting values from the
  • 2054 * subset of fields that match (non-matching fields are treated as filler,
  • 2055 * for which get operations return default values and set operations
  • 2056 * discard given values). Throws InvalidClassException if unresolvable
  • 2057 * type conflicts exist between the two sets of fields.
  • 2058 */
  • 2059 private static FieldReflector getReflector(ObjectStreamField[] fields,
  • 2060 ObjectStreamClass localDesc)
  • 2061 throws InvalidClassException
  • 2062 {
  • 2063 // class irrelevant if no fields
  • 2064 Class cl = (localDesc != null && fields.length > 0) ?
  • 2065 localDesc.cl : null;
  • 2066 processQueue(Caches.reflectorsQueue, Caches.reflectors);
  • 2067 FieldReflectorKey key = new FieldReflectorKey(cl, fields,
  • 2068 Caches.reflectorsQueue);
  • 2069 Reference<?> ref = Caches.reflectors.get(key);
  • 2070 Object entry = null;
  • 2071 if (ref != null) {
  • 2072 entry = ref.get();
  • 2073 }
  • 2074 EntryFuture future = null;
  • 2075 if (entry == null) {
  • 2076 EntryFuture newEntry = new EntryFuture();
  • 2077 Reference<?> newRef = new SoftReference<EntryFuture>(newEntry);
  • 2078 do {
  • 2079 if (ref != null) {
  • 2080 Caches.reflectors.remove(key, ref);
  • 2081 }
  • 2082 ref = Caches.reflectors.putIfAbsent(key, newRef);
  • 2083 if (ref != null) {
  • 2084 entry = ref.get();
  • 2085 }
  • 2086 } while (ref != null && entry == null);
  • 2087 if (entry == null) {
  • 2088 future = newEntry;
  • 2089 }
  • 2090 }
  • 2091
  • 2092 if (entry instanceof FieldReflector) { // check common case first
  • 2093 return (FieldReflector) entry;
  • 2094 } else if (entry instanceof EntryFuture) {
  • 2095 entry = ((EntryFuture) entry).get();
  • 2096 } else if (entry == null) {
  • 2097 try {
  • 2098 entry = new FieldReflector(matchFields(fields, localDesc));
  • 2099 } catch (Throwable th) {
  • 2100 entry = th;
  • 2101 }
  • 2102 future.set(entry);
  • 2103 Caches.reflectors.put(key, new SoftReference<Object>(entry));
  • 2104 }
  • 2105
  • 2106 if (entry instanceof FieldReflector) {
  • 2107 return (FieldReflector) entry;
  • 2108 } else if (entry instanceof InvalidClassException) {
  • 2109 throw (InvalidClassException) entry;
  • 2110 } else if (entry instanceof RuntimeException) {
  • 2111 throw (RuntimeException) entry;
  • 2112 } else if (entry instanceof Error) {
  • 2113 throw (Error) entry;
  • 2114 } else {
  • 2115 throw new InternalError("unexpected entry: " + entry);
  • 2116 }
  • 2117 }
  • 2118
  • 2119 /**
  • 2120 * FieldReflector cache lookup key. Keys are considered equal if they
  • 2121 * refer to the same class and equivalent field formats.
  • 2122 */
  • 2123 private static class FieldReflectorKey extends WeakReference<Class<?>> {
  • 2124
  • 2125 private final String sigs;
  • 2126 private final int hash;
  • 2127 private final boolean nullClass;
  • 2128
  • 2129 FieldReflectorKey(Class cl, ObjectStreamField[] fields,
  • 2130 ReferenceQueue<Class<?>> queue)
  • 2131 {
  • 2132 super(cl, queue);
  • 2133 nullClass = (cl == null);
  • 2134 StringBuilder sbuf = new StringBuilder();
  • 2135 for (int i = 0; i < fields.length; i++) {
  • 2136 ObjectStreamField f = fields[i];
  • 2137 sbuf.append(f.getName()).append(f.getSignature());
  • 2138 }
  • 2139 sigs = sbuf.toString();
  • 2140 hash = System.identityHashCode(cl) + sigs.hashCode();
  • 2141 }
  • 2142
  • 2143 public int hashCode() {
  • 2144 return hash;
  • 2145 }
  • 2146
  • 2147 public boolean equals(Object obj) {
  • 2148 if (obj == this) {
  • 2149 return true;
  • 2150 }
  • 2151
  • 2152 if (obj instanceof FieldReflectorKey) {
  • 2153 FieldReflectorKey other = (FieldReflectorKey) obj;
  • 2154 Class<?> referent;
  • 2155 return (nullClass ? other.nullClass
  • 2156 : ((referent = get()) != null) &&
  • 2157 (referent == other.get())) &&
  • 2158 sigs.equals(other.sigs);
  • 2159 } else {
  • 2160 return false;
  • 2161 }
  • 2162 }
  • 2163 }
  • 2164
  • 2165 /**
  • 2166 * Matches given set of serializable fields with serializable fields
  • 2167 * obtained from the given local class descriptor (which contain bindings
  • 2168 * to reflective Field objects). Returns list of ObjectStreamFields in
  • 2169 * which each ObjectStreamField whose signature matches that of a local
  • 2170 * field contains a Field object for that field; unmatched
  • 2171 * ObjectStreamFields contain null Field objects. Shared/unshared settings
  • 2172 * of the returned ObjectStreamFields also reflect those of matched local
  • 2173 * ObjectStreamFields. Throws InvalidClassException if unresolvable type
  • 2174 * conflicts exist between the two sets of fields.
  • 2175 */
  • 2176 private static ObjectStreamField[] matchFields(ObjectStreamField[] fields,
  • 2177 ObjectStreamClass localDesc)
  • 2178 throws InvalidClassException
  • 2179 {
  • 2180 ObjectStreamField[] localFields = (localDesc != null) ?
  • 2181 localDesc.fields : NO_FIELDS;
  • 2182
  • 2183 /*
  • 2184 * Even if fields == localFields, we cannot simply return localFields
  • 2185 * here. In previous implementations of serialization,
  • 2186 * ObjectStreamField.getType() returned Object.class if the
  • 2187 * ObjectStreamField represented a non-primitive field and belonged to
  • 2188 * a non-local class descriptor. To preserve this (questionable)
  • 2189 * behavior, the ObjectStreamField instances returned by matchFields
  • 2190 * cannot report non-primitive types other than Object.class; hence
  • 2191 * localFields cannot be returned directly.
  • 2192 */
  • 2193
  • 2194 ObjectStreamField[] matches = new ObjectStreamField[fields.length];
  • 2195 for (int i = 0; i < fields.length; i++) {
  • 2196 ObjectStreamField f = fields[i], m = null;
  • 2197 for (int j = 0; j < localFields.length; j++) {
  • 2198 ObjectStreamField lf = localFields[j];
  • 2199 if (f.getName().equals(lf.getName())) {
  • 2200 if ((f.isPrimitive() || lf.isPrimitive()) &&
  • 2201 f.getTypeCode() != lf.getTypeCode())
  • 2202 {
  • 2203 throw new InvalidClassException(localDesc.name,
  • 2204 "incompatible types for field " + f.getName());
  • 2205 }
  • 2206 if (lf.getField() != null) {
  • 2207 m = new ObjectStreamField(
  • 2208 lf.getField(), lf.isUnshared(), false);
  • 2209 } else {
  • 2210 m = new ObjectStreamField(
  • 2211 lf.getName(), lf.getSignature(), lf.isUnshared());
  • 2212 }
  • 2213 }
  • 2214 }
  • 2215 if (m == null) {
  • 2216 m = new ObjectStreamField(
  • 2217 f.getName(), f.getSignature(), false);
  • 2218 }
  • 2219 m.setOffset(f.getOffset());
  • 2220 matches[i] = m;
  • 2221 }
  • 2222 return matches;
  • 2223 }
  • 2224
  • 2225 /**
  • 2226 * Removes from the specified map any keys that have been enqueued
  • 2227 * on the specified reference queue.
  • 2228 */
  • 2229 static void processQueue(ReferenceQueue<Class<?>> queue,
  • 2230 ConcurrentMap<? extends
  • 2231 WeakReference<Class<?>>, ?> map)
  • 2232 {
  • 2233 Reference<? extends Class<?>> ref;
  • 2234 while((ref = queue.poll()) != null) {
  • 2235 map.remove(ref);
  • 2236 }
  • 2237 }
  • 2238
  • 2239 /**
  • 2240 * Weak key for Class objects.
  • 2241 *
  • 2242 **/
  • 2243 static class WeakClassKey extends WeakReference<Class<?>> {
  • 2244 /**
  • 2245 * saved value of the referent's identity hash code, to maintain
  • 2246 * a consistent hash code after the referent has been cleared
  • 2247 */
  • 2248 private final int hash;
  • 2249
  • 2250 /**
  • 2251 * Create a new WeakClassKey to the given object, registered
  • 2252 * with a queue.
  • 2253 */
  • 2254 WeakClassKey(Class<?> cl, ReferenceQueue<Class<?>> refQueue) {
  • 2255 super(cl, refQueue);
  • 2256 hash = System.identityHashCode(cl);
  • 2257 }
  • 2258
  • 2259 /**
  • 2260 * Returns the identity hash code of the original referent.
  • 2261 */
  • 2262 public int hashCode() {
  • 2263 return hash;
  • 2264 }
  • 2265
  • 2266 /**
  • 2267 * Returns true if the given object is this identical
  • 2268 * WeakClassKey instance, or, if this object's referent has not
  • 2269 * been cleared, if the given object is another WeakClassKey
  • 2270 * instance with the identical non-null referent as this one.
  • 2271 */
  • 2272 public boolean equals(Object obj) {
  • 2273 if (obj == this) {
  • 2274 return true;
  • 2275 }
  • 2276
  • 2277 if (obj instanceof WeakClassKey) {
  • 2278 Object referent = get();
  • 2279 return (referent != null) &&
  • 2280 (referent == ((WeakClassKey) obj).get());
  • 2281 } else {
  • 2282 return false;
  • 2283 }
  • 2284 }
  • 2285 }
  • 2286}

文件:ObjectStreamClass.java
包名:java.io
类名:ObjectStreamClass
继承:
接口:[Serializable]