1.1 --- a/emul/compact/src/main/java/java/io/ObjectStreamClass.java Mon Jan 28 18:12:47 2013 +0100
1.2 +++ b/emul/compact/src/main/java/java/io/ObjectStreamClass.java Mon Feb 25 19:00:08 2013 +0100
1.3 @@ -36,20 +36,12 @@
1.4 import java.lang.reflect.Method;
1.5 import java.lang.reflect.Modifier;
1.6 import java.lang.reflect.Proxy;
1.7 -import java.security.AccessController;
1.8 -import java.security.MessageDigest;
1.9 -import java.security.NoSuchAlgorithmException;
1.10 -import java.security.PrivilegedAction;
1.11 import java.util.ArrayList;
1.12 import java.util.Arrays;
1.13 import java.util.Collections;
1.14 import java.util.Comparator;
1.15 import java.util.HashSet;
1.16 import java.util.Set;
1.17 -import java.util.concurrent.ConcurrentHashMap;
1.18 -import java.util.concurrent.ConcurrentMap;
1.19 -import sun.misc.Unsafe;
1.20 -import sun.reflect.ReflectionFactory;
1.21
1.22 /**
1.23 * Serialization's descriptor for classes. It contains the name and
1.24 @@ -76,27 +68,6 @@
1.25 private static final ObjectStreamField[] serialPersistentFields =
1.26 NO_FIELDS;
1.27
1.28 - /** reflection factory for obtaining serialization constructors */
1.29 - private static final ReflectionFactory reflFactory =
1.30 - AccessController.doPrivileged(
1.31 - new ReflectionFactory.GetReflectionFactoryAction());
1.32 -
1.33 - private static class Caches {
1.34 - /** cache mapping local classes -> descriptors */
1.35 - static final ConcurrentMap<WeakClassKey,Reference<?>> localDescs =
1.36 - new ConcurrentHashMap<>();
1.37 -
1.38 - /** cache mapping field group/local desc pairs -> field reflectors */
1.39 - static final ConcurrentMap<FieldReflectorKey,Reference<?>> reflectors =
1.40 - new ConcurrentHashMap<>();
1.41 -
1.42 - /** queue for WeakReferences to local classes */
1.43 - private static final ReferenceQueue<Class<?>> localDescsQueue =
1.44 - new ReferenceQueue<>();
1.45 - /** queue for WeakReferences to field reflectors keys */
1.46 - private static final ReferenceQueue<Class<?>> reflectorsQueue =
1.47 - new ReferenceQueue<>();
1.48 - }
1.49
1.50 /** class associated with this descriptor (if any) */
1.51 private Class<?> cl;
1.52 @@ -139,7 +110,7 @@
1.53 /** number of non-primitive fields */
1.54 private int numObjFields;
1.55 /** reflector for setting/getting serializable field values */
1.56 - private FieldReflector fieldRefl;
1.57 +// private FieldReflector fieldRefl;
1.58 /** data layout of serialized objects described by this class desc */
1.59 private volatile ClassDataSlot[] dataLayout;
1.60
1.61 @@ -216,13 +187,7 @@
1.62 public long getSerialVersionUID() {
1.63 // REMIND: synchronize instead of relying on volatile?
1.64 if (suid == null) {
1.65 - suid = AccessController.doPrivileged(
1.66 - new PrivilegedAction<Long>() {
1.67 - public Long run() {
1.68 - return computeDefaultSUID(cl);
1.69 - }
1.70 - }
1.71 - );
1.72 + return computeDefaultSUID(cl);
1.73 }
1.74 return suid.longValue();
1.75 }
1.76 @@ -280,26 +245,11 @@
1.77 if (!(all || Serializable.class.isAssignableFrom(cl))) {
1.78 return null;
1.79 }
1.80 - processQueue(Caches.localDescsQueue, Caches.localDescs);
1.81 - WeakClassKey key = new WeakClassKey(cl, Caches.localDescsQueue);
1.82 - Reference<?> ref = Caches.localDescs.get(key);
1.83 Object entry = null;
1.84 - if (ref != null) {
1.85 - entry = ref.get();
1.86 - }
1.87 EntryFuture future = null;
1.88 if (entry == null) {
1.89 EntryFuture newEntry = new EntryFuture();
1.90 Reference<?> newRef = new SoftReference<>(newEntry);
1.91 - do {
1.92 - if (ref != null) {
1.93 - Caches.localDescs.remove(key, ref);
1.94 - }
1.95 - ref = Caches.localDescs.putIfAbsent(key, newRef);
1.96 - if (ref != null) {
1.97 - entry = ref.get();
1.98 - }
1.99 - } while (ref != null && entry == null);
1.100 if (entry == null) {
1.101 future = newEntry;
1.102 }
1.103 @@ -310,7 +260,7 @@
1.104 }
1.105 if (entry instanceof EntryFuture) {
1.106 future = (EntryFuture) entry;
1.107 - if (future.getOwner() == Thread.currentThread()) {
1.108 + if (true) {
1.109 /*
1.110 * Handle nested call situation described by 4803747: waiting
1.111 * for future value to be set by a lookup() call further up the
1.112 @@ -328,12 +278,8 @@
1.113 } catch (Throwable th) {
1.114 entry = th;
1.115 }
1.116 - if (future.set(entry)) {
1.117 - Caches.localDescs.put(key, new SoftReference<Object>(entry));
1.118 - } else {
1.119 - // nested lookup call already set future
1.120 - entry = future.get();
1.121 - }
1.122 + // nested lookup call already set future
1.123 + entry = future.get();
1.124 }
1.125
1.126 if (entry instanceof ObjectStreamClass) {
1.127 @@ -358,7 +304,6 @@
1.128 private static class EntryFuture {
1.129
1.130 private static final Object unset = new Object();
1.131 - private final Thread owner = Thread.currentThread();
1.132 private Object entry = unset;
1.133
1.134 /**
1.135 @@ -390,25 +335,8 @@
1.136 interrupted = true;
1.137 }
1.138 }
1.139 - if (interrupted) {
1.140 - AccessController.doPrivileged(
1.141 - new PrivilegedAction<Void>() {
1.142 - public Void run() {
1.143 - Thread.currentThread().interrupt();
1.144 - return null;
1.145 - }
1.146 - }
1.147 - );
1.148 - }
1.149 return entry;
1.150 }
1.151 -
1.152 - /**
1.153 - * Returns the thread that created this EntryFuture.
1.154 - */
1.155 - Thread getOwner() {
1.156 - return owner;
1.157 - }
1.158 }
1.159
1.160 /**
1.161 @@ -426,60 +354,9 @@
1.162 superDesc = (superCl != null) ? lookup(superCl, false) : null;
1.163 localDesc = this;
1.164
1.165 - if (serializable) {
1.166 - AccessController.doPrivileged(new PrivilegedAction<Void>() {
1.167 - public Void run() {
1.168 - if (isEnum) {
1.169 - suid = Long.valueOf(0);
1.170 - fields = NO_FIELDS;
1.171 - return null;
1.172 - }
1.173 - if (cl.isArray()) {
1.174 - fields = NO_FIELDS;
1.175 - return null;
1.176 - }
1.177 + suid = Long.valueOf(0);
1.178 + fields = NO_FIELDS;
1.179
1.180 - suid = getDeclaredSUID(cl);
1.181 - try {
1.182 - fields = getSerialFields(cl);
1.183 - computeFieldOffsets();
1.184 - } catch (InvalidClassException e) {
1.185 - serializeEx = deserializeEx = e;
1.186 - fields = NO_FIELDS;
1.187 - }
1.188 -
1.189 - if (externalizable) {
1.190 - cons = getExternalizableConstructor(cl);
1.191 - } else {
1.192 - cons = getSerializableConstructor(cl);
1.193 - writeObjectMethod = getPrivateMethod(cl, "writeObject",
1.194 - new Class<?>[] { ObjectOutputStream.class },
1.195 - Void.TYPE);
1.196 - readObjectMethod = getPrivateMethod(cl, "readObject",
1.197 - new Class<?>[] { ObjectInputStream.class },
1.198 - Void.TYPE);
1.199 - readObjectNoDataMethod = getPrivateMethod(
1.200 - cl, "readObjectNoData", null, Void.TYPE);
1.201 - hasWriteObjectData = (writeObjectMethod != null);
1.202 - }
1.203 - writeReplaceMethod = getInheritableMethod(
1.204 - cl, "writeReplace", null, Object.class);
1.205 - readResolveMethod = getInheritableMethod(
1.206 - cl, "readResolve", null, Object.class);
1.207 - return null;
1.208 - }
1.209 - });
1.210 - } else {
1.211 - suid = Long.valueOf(0);
1.212 - fields = NO_FIELDS;
1.213 - }
1.214 -
1.215 - try {
1.216 - fieldRefl = getReflector(fields, this);
1.217 - } catch (InvalidClassException ex) {
1.218 - // field mismatches impossible when matching local fields vs. self
1.219 - throw new InternalError();
1.220 - }
1.221
1.222 if (deserializeEx == null) {
1.223 if (isEnum) {
1.224 @@ -533,7 +410,6 @@
1.225 readResolveMethod = localDesc.readResolveMethod;
1.226 deserializeEx = localDesc.deserializeEx;
1.227 }
1.228 - fieldRefl = getReflector(fields, localDesc);
1.229 }
1.230
1.231 /**
1.232 @@ -616,9 +492,8 @@
1.233 deserializeEx = localDesc.deserializeEx;
1.234 }
1.235 }
1.236 - fieldRefl = getReflector(fields, localDesc);
1.237 // reassign to matched fields so as to reflect local unshared settings
1.238 - fields = fieldRefl.getFields();
1.239 + fields = null;
1.240 }
1.241
1.242 /**
1.243 @@ -1197,7 +1072,6 @@
1.244 * non-null.
1.245 */
1.246 void getPrimFieldValues(Object obj, byte[] buf) {
1.247 - fieldRefl.getPrimFieldValues(obj, buf);
1.248 }
1.249
1.250 /**
1.251 @@ -1207,7 +1081,6 @@
1.252 * non-null.
1.253 */
1.254 void setPrimFieldValues(Object obj, byte[] buf) {
1.255 - fieldRefl.setPrimFieldValues(obj, buf);
1.256 }
1.257
1.258 /**
1.259 @@ -1216,7 +1089,6 @@
1.260 * the caller to ensure that obj is of the proper type if non-null.
1.261 */
1.262 void getObjFieldValues(Object obj, Object[] vals) {
1.263 - fieldRefl.getObjFieldValues(obj, vals);
1.264 }
1.265
1.266 /**
1.267 @@ -1225,7 +1097,6 @@
1.268 * to ensure that obj is of the proper type if non-null.
1.269 */
1.270 void setObjFieldValues(Object obj, Object[] vals) {
1.271 - fieldRefl.setObjFieldValues(obj, vals);
1.272 }
1.273
1.274 /**
1.275 @@ -1309,14 +1180,7 @@
1.276 * the defining class may still be non-public.
1.277 */
1.278 private static Constructor getExternalizableConstructor(Class<?> cl) {
1.279 - try {
1.280 - Constructor cons = cl.getDeclaredConstructor((Class<?>[]) null);
1.281 - cons.setAccessible(true);
1.282 - return ((cons.getModifiers() & Modifier.PUBLIC) != 0) ?
1.283 - cons : null;
1.284 - } catch (NoSuchMethodException ex) {
1.285 - return null;
1.286 - }
1.287 + throw new SecurityException();
1.288 }
1.289
1.290 /**
1.291 @@ -1331,21 +1195,7 @@
1.292 return null;
1.293 }
1.294 }
1.295 - try {
1.296 - Constructor cons = initCl.getDeclaredConstructor((Class<?>[]) null);
1.297 - int mods = cons.getModifiers();
1.298 - if ((mods & Modifier.PRIVATE) != 0 ||
1.299 - ((mods & (Modifier.PUBLIC | Modifier.PROTECTED)) == 0 &&
1.300 - !packageEquals(cl, initCl)))
1.301 - {
1.302 - return null;
1.303 - }
1.304 - cons = reflFactory.newConstructorForSerialization(cl, cons);
1.305 - cons.setAccessible(true);
1.306 - return cons;
1.307 - } catch (NoSuchMethodException ex) {
1.308 - return null;
1.309 - }
1.310 + throw new SecurityException();
1.311 }
1.312
1.313 /**
1.314 @@ -1358,31 +1208,7 @@
1.315 Class<?>[] argTypes,
1.316 Class<?> returnType)
1.317 {
1.318 - Method meth = null;
1.319 - Class<?> defCl = cl;
1.320 - while (defCl != null) {
1.321 - try {
1.322 - meth = defCl.getDeclaredMethod(name, argTypes);
1.323 - break;
1.324 - } catch (NoSuchMethodException ex) {
1.325 - defCl = defCl.getSuperclass();
1.326 - }
1.327 - }
1.328 -
1.329 - if ((meth == null) || (meth.getReturnType() != returnType)) {
1.330 - return null;
1.331 - }
1.332 - meth.setAccessible(true);
1.333 - int mods = meth.getModifiers();
1.334 - if ((mods & (Modifier.STATIC | Modifier.ABSTRACT)) != 0) {
1.335 - return null;
1.336 - } else if ((mods & (Modifier.PUBLIC | Modifier.PROTECTED)) != 0) {
1.337 - return meth;
1.338 - } else if ((mods & Modifier.PRIVATE) != 0) {
1.339 - return (cl == defCl) ? meth : null;
1.340 - } else {
1.341 - return packageEquals(cl, defCl) ? meth : null;
1.342 - }
1.343 + throw new SecurityException();
1.344 }
1.345
1.346 /**
1.347 @@ -1394,16 +1220,7 @@
1.348 Class<?>[] argTypes,
1.349 Class<?> returnType)
1.350 {
1.351 - try {
1.352 - Method meth = cl.getDeclaredMethod(name, argTypes);
1.353 - meth.setAccessible(true);
1.354 - int mods = meth.getModifiers();
1.355 - return ((meth.getReturnType() == returnType) &&
1.356 - ((mods & Modifier.STATIC) == 0) &&
1.357 - ((mods & Modifier.PRIVATE) != 0)) ? meth : null;
1.358 - } catch (NoSuchMethodException ex) {
1.359 - return null;
1.360 - }
1.361 + throw new SecurityException();
1.362 }
1.363
1.364 /**
1.365 @@ -1548,52 +1365,7 @@
1.366 private static ObjectStreamField[] getDeclaredSerialFields(Class<?> cl)
1.367 throws InvalidClassException
1.368 {
1.369 - ObjectStreamField[] serialPersistentFields = null;
1.370 - try {
1.371 - Field f = cl.getDeclaredField("serialPersistentFields");
1.372 - int mask = Modifier.PRIVATE | Modifier.STATIC | Modifier.FINAL;
1.373 - if ((f.getModifiers() & mask) == mask) {
1.374 - f.setAccessible(true);
1.375 - serialPersistentFields = (ObjectStreamField[]) f.get(null);
1.376 - }
1.377 - } catch (Exception ex) {
1.378 - }
1.379 - if (serialPersistentFields == null) {
1.380 - return null;
1.381 - } else if (serialPersistentFields.length == 0) {
1.382 - return NO_FIELDS;
1.383 - }
1.384 -
1.385 - ObjectStreamField[] boundFields =
1.386 - new ObjectStreamField[serialPersistentFields.length];
1.387 - Set<String> fieldNames = new HashSet<>(serialPersistentFields.length);
1.388 -
1.389 - for (int i = 0; i < serialPersistentFields.length; i++) {
1.390 - ObjectStreamField spf = serialPersistentFields[i];
1.391 -
1.392 - String fname = spf.getName();
1.393 - if (fieldNames.contains(fname)) {
1.394 - throw new InvalidClassException(
1.395 - "multiple serializable fields named " + fname);
1.396 - }
1.397 - fieldNames.add(fname);
1.398 -
1.399 - try {
1.400 - Field f = cl.getDeclaredField(fname);
1.401 - if ((f.getType() == spf.getType()) &&
1.402 - ((f.getModifiers() & Modifier.STATIC) == 0))
1.403 - {
1.404 - boundFields[i] =
1.405 - new ObjectStreamField(f, spf.isUnshared(), true);
1.406 - }
1.407 - } catch (NoSuchFieldException ex) {
1.408 - }
1.409 - if (boundFields[i] == null) {
1.410 - boundFields[i] = new ObjectStreamField(
1.411 - fname, spf.getType(), spf.isUnshared());
1.412 - }
1.413 - }
1.414 - return boundFields;
1.415 + throw new SecurityException();
1.416 }
1.417
1.418 /**
1.419 @@ -1603,18 +1375,7 @@
1.420 * serializable fields exist, NO_FIELDS is returned.
1.421 */
1.422 private static ObjectStreamField[] getDefaultSerialFields(Class<?> cl) {
1.423 - Field[] clFields = cl.getDeclaredFields();
1.424 - ArrayList<ObjectStreamField> list = new ArrayList<>();
1.425 - int mask = Modifier.STATIC | Modifier.TRANSIENT;
1.426 -
1.427 - for (int i = 0; i < clFields.length; i++) {
1.428 - if ((clFields[i].getModifiers() & mask) == 0) {
1.429 - list.add(new ObjectStreamField(clFields[i], false, true));
1.430 - }
1.431 - }
1.432 - int size = list.size();
1.433 - return (size == 0) ? NO_FIELDS :
1.434 - list.toArray(new ObjectStreamField[size]);
1.435 + throw new SecurityException();
1.436 }
1.437
1.438 /**
1.439 @@ -1622,15 +1383,6 @@
1.440 * null if none.
1.441 */
1.442 private static Long getDeclaredSUID(Class<?> cl) {
1.443 - try {
1.444 - Field f = cl.getDeclaredField("serialVersionUID");
1.445 - int mask = Modifier.STATIC | Modifier.FINAL;
1.446 - if ((f.getModifiers() & mask) == mask) {
1.447 - f.setAccessible(true);
1.448 - return Long.valueOf(f.getLong(null));
1.449 - }
1.450 - } catch (Exception ex) {
1.451 - }
1.452 return null;
1.453 }
1.454
1.455 @@ -1638,667 +1390,7 @@
1.456 * Computes the default serial version UID value for the given class.
1.457 */
1.458 private static long computeDefaultSUID(Class<?> cl) {
1.459 - if (!Serializable.class.isAssignableFrom(cl) || Proxy.isProxyClass(cl))
1.460 - {
1.461 - return 0L;
1.462 - }
1.463 -
1.464 - try {
1.465 - ByteArrayOutputStream bout = new ByteArrayOutputStream();
1.466 - DataOutputStream dout = new DataOutputStream(bout);
1.467 -
1.468 - dout.writeUTF(cl.getName());
1.469 -
1.470 - int classMods = cl.getModifiers() &
1.471 - (Modifier.PUBLIC | Modifier.FINAL |
1.472 - Modifier.INTERFACE | Modifier.ABSTRACT);
1.473 -
1.474 - /*
1.475 - * compensate for javac bug in which ABSTRACT bit was set for an
1.476 - * interface only if the interface declared methods
1.477 - */
1.478 - Method[] methods = cl.getDeclaredMethods();
1.479 - if ((classMods & Modifier.INTERFACE) != 0) {
1.480 - classMods = (methods.length > 0) ?
1.481 - (classMods | Modifier.ABSTRACT) :
1.482 - (classMods & ~Modifier.ABSTRACT);
1.483 - }
1.484 - dout.writeInt(classMods);
1.485 -
1.486 - if (!cl.isArray()) {
1.487 - /*
1.488 - * compensate for change in 1.2FCS in which
1.489 - * Class.getInterfaces() was modified to return Cloneable and
1.490 - * Serializable for array classes.
1.491 - */
1.492 - Class<?>[] interfaces = cl.getInterfaces();
1.493 - String[] ifaceNames = new String[interfaces.length];
1.494 - for (int i = 0; i < interfaces.length; i++) {
1.495 - ifaceNames[i] = interfaces[i].getName();
1.496 - }
1.497 - Arrays.sort(ifaceNames);
1.498 - for (int i = 0; i < ifaceNames.length; i++) {
1.499 - dout.writeUTF(ifaceNames[i]);
1.500 - }
1.501 - }
1.502 -
1.503 - Field[] fields = cl.getDeclaredFields();
1.504 - MemberSignature[] fieldSigs = new MemberSignature[fields.length];
1.505 - for (int i = 0; i < fields.length; i++) {
1.506 - fieldSigs[i] = new MemberSignature(fields[i]);
1.507 - }
1.508 - Arrays.sort(fieldSigs, new Comparator<MemberSignature>() {
1.509 - public int compare(MemberSignature ms1, MemberSignature ms2) {
1.510 - return ms1.name.compareTo(ms2.name);
1.511 - }
1.512 - });
1.513 - for (int i = 0; i < fieldSigs.length; i++) {
1.514 - MemberSignature sig = fieldSigs[i];
1.515 - int mods = sig.member.getModifiers() &
1.516 - (Modifier.PUBLIC | Modifier.PRIVATE | Modifier.PROTECTED |
1.517 - Modifier.STATIC | Modifier.FINAL | Modifier.VOLATILE |
1.518 - Modifier.TRANSIENT);
1.519 - if (((mods & Modifier.PRIVATE) == 0) ||
1.520 - ((mods & (Modifier.STATIC | Modifier.TRANSIENT)) == 0))
1.521 - {
1.522 - dout.writeUTF(sig.name);
1.523 - dout.writeInt(mods);
1.524 - dout.writeUTF(sig.signature);
1.525 - }
1.526 - }
1.527 -
1.528 - if (hasStaticInitializer(cl)) {
1.529 - dout.writeUTF("<clinit>");
1.530 - dout.writeInt(Modifier.STATIC);
1.531 - dout.writeUTF("()V");
1.532 - }
1.533 -
1.534 - Constructor[] cons = cl.getDeclaredConstructors();
1.535 - MemberSignature[] consSigs = new MemberSignature[cons.length];
1.536 - for (int i = 0; i < cons.length; i++) {
1.537 - consSigs[i] = new MemberSignature(cons[i]);
1.538 - }
1.539 - Arrays.sort(consSigs, new Comparator<MemberSignature>() {
1.540 - public int compare(MemberSignature ms1, MemberSignature ms2) {
1.541 - return ms1.signature.compareTo(ms2.signature);
1.542 - }
1.543 - });
1.544 - for (int i = 0; i < consSigs.length; i++) {
1.545 - MemberSignature sig = consSigs[i];
1.546 - int mods = sig.member.getModifiers() &
1.547 - (Modifier.PUBLIC | Modifier.PRIVATE | Modifier.PROTECTED |
1.548 - Modifier.STATIC | Modifier.FINAL |
1.549 - Modifier.SYNCHRONIZED | Modifier.NATIVE |
1.550 - Modifier.ABSTRACT | Modifier.STRICT);
1.551 - if ((mods & Modifier.PRIVATE) == 0) {
1.552 - dout.writeUTF("<init>");
1.553 - dout.writeInt(mods);
1.554 - dout.writeUTF(sig.signature.replace('/', '.'));
1.555 - }
1.556 - }
1.557 -
1.558 - MemberSignature[] methSigs = new MemberSignature[methods.length];
1.559 - for (int i = 0; i < methods.length; i++) {
1.560 - methSigs[i] = new MemberSignature(methods[i]);
1.561 - }
1.562 - Arrays.sort(methSigs, new Comparator<MemberSignature>() {
1.563 - public int compare(MemberSignature ms1, MemberSignature ms2) {
1.564 - int comp = ms1.name.compareTo(ms2.name);
1.565 - if (comp == 0) {
1.566 - comp = ms1.signature.compareTo(ms2.signature);
1.567 - }
1.568 - return comp;
1.569 - }
1.570 - });
1.571 - for (int i = 0; i < methSigs.length; i++) {
1.572 - MemberSignature sig = methSigs[i];
1.573 - int mods = sig.member.getModifiers() &
1.574 - (Modifier.PUBLIC | Modifier.PRIVATE | Modifier.PROTECTED |
1.575 - Modifier.STATIC | Modifier.FINAL |
1.576 - Modifier.SYNCHRONIZED | Modifier.NATIVE |
1.577 - Modifier.ABSTRACT | Modifier.STRICT);
1.578 - if ((mods & Modifier.PRIVATE) == 0) {
1.579 - dout.writeUTF(sig.name);
1.580 - dout.writeInt(mods);
1.581 - dout.writeUTF(sig.signature.replace('/', '.'));
1.582 - }
1.583 - }
1.584 -
1.585 - dout.flush();
1.586 -
1.587 - MessageDigest md = MessageDigest.getInstance("SHA");
1.588 - byte[] hashBytes = md.digest(bout.toByteArray());
1.589 - long hash = 0;
1.590 - for (int i = Math.min(hashBytes.length, 8) - 1; i >= 0; i--) {
1.591 - hash = (hash << 8) | (hashBytes[i] & 0xFF);
1.592 - }
1.593 - return hash;
1.594 - } catch (IOException ex) {
1.595 - throw new InternalError();
1.596 - } catch (NoSuchAlgorithmException ex) {
1.597 - throw new SecurityException(ex.getMessage());
1.598 - }
1.599 + throw new SecurityException();
1.600 }
1.601
1.602 - /**
1.603 - * Returns true if the given class defines a static initializer method,
1.604 - * false otherwise.
1.605 - */
1.606 - private native static boolean hasStaticInitializer(Class<?> cl);
1.607 -
1.608 - /**
1.609 - * Class for computing and caching field/constructor/method signatures
1.610 - * during serialVersionUID calculation.
1.611 - */
1.612 - private static class MemberSignature {
1.613 -
1.614 - public final Member member;
1.615 - public final String name;
1.616 - public final String signature;
1.617 -
1.618 - public MemberSignature(Field field) {
1.619 - member = field;
1.620 - name = field.getName();
1.621 - signature = getClassSignature(field.getType());
1.622 - }
1.623 -
1.624 - public MemberSignature(Constructor cons) {
1.625 - member = cons;
1.626 - name = cons.getName();
1.627 - signature = getMethodSignature(
1.628 - cons.getParameterTypes(), Void.TYPE);
1.629 - }
1.630 -
1.631 - public MemberSignature(Method meth) {
1.632 - member = meth;
1.633 - name = meth.getName();
1.634 - signature = getMethodSignature(
1.635 - meth.getParameterTypes(), meth.getReturnType());
1.636 - }
1.637 - }
1.638 -
1.639 - /**
1.640 - * Class for setting and retrieving serializable field values in batch.
1.641 - */
1.642 - // REMIND: dynamically generate these?
1.643 - private static class FieldReflector {
1.644 -
1.645 - /** handle for performing unsafe operations */
1.646 - private static final Unsafe unsafe = Unsafe.getUnsafe();
1.647 -
1.648 - /** fields to operate on */
1.649 - private final ObjectStreamField[] fields;
1.650 - /** number of primitive fields */
1.651 - private final int numPrimFields;
1.652 - /** unsafe field keys for reading fields - may contain dupes */
1.653 - private final long[] readKeys;
1.654 - /** unsafe fields keys for writing fields - no dupes */
1.655 - private final long[] writeKeys;
1.656 - /** field data offsets */
1.657 - private final int[] offsets;
1.658 - /** field type codes */
1.659 - private final char[] typeCodes;
1.660 - /** field types */
1.661 - private final Class<?>[] types;
1.662 -
1.663 - /**
1.664 - * Constructs FieldReflector capable of setting/getting values from the
1.665 - * subset of fields whose ObjectStreamFields contain non-null
1.666 - * reflective Field objects. ObjectStreamFields with null Fields are
1.667 - * treated as filler, for which get operations return default values
1.668 - * and set operations discard given values.
1.669 - */
1.670 - FieldReflector(ObjectStreamField[] fields) {
1.671 - this.fields = fields;
1.672 - int nfields = fields.length;
1.673 - readKeys = new long[nfields];
1.674 - writeKeys = new long[nfields];
1.675 - offsets = new int[nfields];
1.676 - typeCodes = new char[nfields];
1.677 - ArrayList<Class<?>> typeList = new ArrayList<>();
1.678 - Set<Long> usedKeys = new HashSet<>();
1.679 -
1.680 -
1.681 - for (int i = 0; i < nfields; i++) {
1.682 - ObjectStreamField f = fields[i];
1.683 - Field rf = f.getField();
1.684 - long key = (rf != null) ?
1.685 - unsafe.objectFieldOffset(rf) : Unsafe.INVALID_FIELD_OFFSET;
1.686 - readKeys[i] = key;
1.687 - writeKeys[i] = usedKeys.add(key) ?
1.688 - key : Unsafe.INVALID_FIELD_OFFSET;
1.689 - offsets[i] = f.getOffset();
1.690 - typeCodes[i] = f.getTypeCode();
1.691 - if (!f.isPrimitive()) {
1.692 - typeList.add((rf != null) ? rf.getType() : null);
1.693 - }
1.694 - }
1.695 -
1.696 - types = typeList.toArray(new Class<?>[typeList.size()]);
1.697 - numPrimFields = nfields - types.length;
1.698 - }
1.699 -
1.700 - /**
1.701 - * Returns list of ObjectStreamFields representing fields operated on
1.702 - * by this reflector. The shared/unshared values and Field objects
1.703 - * contained by ObjectStreamFields in the list reflect their bindings
1.704 - * to locally defined serializable fields.
1.705 - */
1.706 - ObjectStreamField[] getFields() {
1.707 - return fields;
1.708 - }
1.709 -
1.710 - /**
1.711 - * Fetches the serializable primitive field values of object obj and
1.712 - * marshals them into byte array buf starting at offset 0. The caller
1.713 - * is responsible for ensuring that obj is of the proper type.
1.714 - */
1.715 - void getPrimFieldValues(Object obj, byte[] buf) {
1.716 - if (obj == null) {
1.717 - throw new NullPointerException();
1.718 - }
1.719 - /* assuming checkDefaultSerialize() has been called on the class
1.720 - * descriptor this FieldReflector was obtained from, no field keys
1.721 - * in array should be equal to Unsafe.INVALID_FIELD_OFFSET.
1.722 - */
1.723 - for (int i = 0; i < numPrimFields; i++) {
1.724 - long key = readKeys[i];
1.725 - int off = offsets[i];
1.726 - switch (typeCodes[i]) {
1.727 - case 'Z':
1.728 - Bits.putBoolean(buf, off, unsafe.getBoolean(obj, key));
1.729 - break;
1.730 -
1.731 - case 'B':
1.732 - buf[off] = unsafe.getByte(obj, key);
1.733 - break;
1.734 -
1.735 - case 'C':
1.736 - Bits.putChar(buf, off, unsafe.getChar(obj, key));
1.737 - break;
1.738 -
1.739 - case 'S':
1.740 - Bits.putShort(buf, off, unsafe.getShort(obj, key));
1.741 - break;
1.742 -
1.743 - case 'I':
1.744 - Bits.putInt(buf, off, unsafe.getInt(obj, key));
1.745 - break;
1.746 -
1.747 - case 'F':
1.748 - Bits.putFloat(buf, off, unsafe.getFloat(obj, key));
1.749 - break;
1.750 -
1.751 - case 'J':
1.752 - Bits.putLong(buf, off, unsafe.getLong(obj, key));
1.753 - break;
1.754 -
1.755 - case 'D':
1.756 - Bits.putDouble(buf, off, unsafe.getDouble(obj, key));
1.757 - break;
1.758 -
1.759 - default:
1.760 - throw new InternalError();
1.761 - }
1.762 - }
1.763 - }
1.764 -
1.765 - /**
1.766 - * Sets the serializable primitive fields of object obj using values
1.767 - * unmarshalled from byte array buf starting at offset 0. The caller
1.768 - * is responsible for ensuring that obj is of the proper type.
1.769 - */
1.770 - void setPrimFieldValues(Object obj, byte[] buf) {
1.771 - if (obj == null) {
1.772 - throw new NullPointerException();
1.773 - }
1.774 - for (int i = 0; i < numPrimFields; i++) {
1.775 - long key = writeKeys[i];
1.776 - if (key == Unsafe.INVALID_FIELD_OFFSET) {
1.777 - continue; // discard value
1.778 - }
1.779 - int off = offsets[i];
1.780 - switch (typeCodes[i]) {
1.781 - case 'Z':
1.782 - unsafe.putBoolean(obj, key, Bits.getBoolean(buf, off));
1.783 - break;
1.784 -
1.785 - case 'B':
1.786 - unsafe.putByte(obj, key, buf[off]);
1.787 - break;
1.788 -
1.789 - case 'C':
1.790 - unsafe.putChar(obj, key, Bits.getChar(buf, off));
1.791 - break;
1.792 -
1.793 - case 'S':
1.794 - unsafe.putShort(obj, key, Bits.getShort(buf, off));
1.795 - break;
1.796 -
1.797 - case 'I':
1.798 - unsafe.putInt(obj, key, Bits.getInt(buf, off));
1.799 - break;
1.800 -
1.801 - case 'F':
1.802 - unsafe.putFloat(obj, key, Bits.getFloat(buf, off));
1.803 - break;
1.804 -
1.805 - case 'J':
1.806 - unsafe.putLong(obj, key, Bits.getLong(buf, off));
1.807 - break;
1.808 -
1.809 - case 'D':
1.810 - unsafe.putDouble(obj, key, Bits.getDouble(buf, off));
1.811 - break;
1.812 -
1.813 - default:
1.814 - throw new InternalError();
1.815 - }
1.816 - }
1.817 - }
1.818 -
1.819 - /**
1.820 - * Fetches the serializable object field values of object obj and
1.821 - * stores them in array vals starting at offset 0. The caller is
1.822 - * responsible for ensuring that obj is of the proper type.
1.823 - */
1.824 - void getObjFieldValues(Object obj, Object[] vals) {
1.825 - if (obj == null) {
1.826 - throw new NullPointerException();
1.827 - }
1.828 - /* assuming checkDefaultSerialize() has been called on the class
1.829 - * descriptor this FieldReflector was obtained from, no field keys
1.830 - * in array should be equal to Unsafe.INVALID_FIELD_OFFSET.
1.831 - */
1.832 - for (int i = numPrimFields; i < fields.length; i++) {
1.833 - switch (typeCodes[i]) {
1.834 - case 'L':
1.835 - case '[':
1.836 - vals[offsets[i]] = unsafe.getObject(obj, readKeys[i]);
1.837 - break;
1.838 -
1.839 - default:
1.840 - throw new InternalError();
1.841 - }
1.842 - }
1.843 - }
1.844 -
1.845 - /**
1.846 - * Sets the serializable object fields of object obj using values from
1.847 - * array vals starting at offset 0. The caller is responsible for
1.848 - * ensuring that obj is of the proper type; however, attempts to set a
1.849 - * field with a value of the wrong type will trigger an appropriate
1.850 - * ClassCastException.
1.851 - */
1.852 - void setObjFieldValues(Object obj, Object[] vals) {
1.853 - if (obj == null) {
1.854 - throw new NullPointerException();
1.855 - }
1.856 - for (int i = numPrimFields; i < fields.length; i++) {
1.857 - long key = writeKeys[i];
1.858 - if (key == Unsafe.INVALID_FIELD_OFFSET) {
1.859 - continue; // discard value
1.860 - }
1.861 - switch (typeCodes[i]) {
1.862 - case 'L':
1.863 - case '[':
1.864 - Object val = vals[offsets[i]];
1.865 - if (val != null &&
1.866 - !types[i - numPrimFields].isInstance(val))
1.867 - {
1.868 - Field f = fields[i].getField();
1.869 - throw new ClassCastException(
1.870 - "cannot assign instance of " +
1.871 - val.getClass().getName() + " to field " +
1.872 - f.getDeclaringClass().getName() + "." +
1.873 - f.getName() + " of type " +
1.874 - f.getType().getName() + " in instance of " +
1.875 - obj.getClass().getName());
1.876 - }
1.877 - unsafe.putObject(obj, key, val);
1.878 - break;
1.879 -
1.880 - default:
1.881 - throw new InternalError();
1.882 - }
1.883 - }
1.884 - }
1.885 - }
1.886 -
1.887 - /**
1.888 - * Matches given set of serializable fields with serializable fields
1.889 - * described by the given local class descriptor, and returns a
1.890 - * FieldReflector instance capable of setting/getting values from the
1.891 - * subset of fields that match (non-matching fields are treated as filler,
1.892 - * for which get operations return default values and set operations
1.893 - * discard given values). Throws InvalidClassException if unresolvable
1.894 - * type conflicts exist between the two sets of fields.
1.895 - */
1.896 - private static FieldReflector getReflector(ObjectStreamField[] fields,
1.897 - ObjectStreamClass localDesc)
1.898 - throws InvalidClassException
1.899 - {
1.900 - // class irrelevant if no fields
1.901 - Class<?> cl = (localDesc != null && fields.length > 0) ?
1.902 - localDesc.cl : null;
1.903 - processQueue(Caches.reflectorsQueue, Caches.reflectors);
1.904 - FieldReflectorKey key = new FieldReflectorKey(cl, fields,
1.905 - Caches.reflectorsQueue);
1.906 - Reference<?> ref = Caches.reflectors.get(key);
1.907 - Object entry = null;
1.908 - if (ref != null) {
1.909 - entry = ref.get();
1.910 - }
1.911 - EntryFuture future = null;
1.912 - if (entry == null) {
1.913 - EntryFuture newEntry = new EntryFuture();
1.914 - Reference<?> newRef = new SoftReference<>(newEntry);
1.915 - do {
1.916 - if (ref != null) {
1.917 - Caches.reflectors.remove(key, ref);
1.918 - }
1.919 - ref = Caches.reflectors.putIfAbsent(key, newRef);
1.920 - if (ref != null) {
1.921 - entry = ref.get();
1.922 - }
1.923 - } while (ref != null && entry == null);
1.924 - if (entry == null) {
1.925 - future = newEntry;
1.926 - }
1.927 - }
1.928 -
1.929 - if (entry instanceof FieldReflector) { // check common case first
1.930 - return (FieldReflector) entry;
1.931 - } else if (entry instanceof EntryFuture) {
1.932 - entry = ((EntryFuture) entry).get();
1.933 - } else if (entry == null) {
1.934 - try {
1.935 - entry = new FieldReflector(matchFields(fields, localDesc));
1.936 - } catch (Throwable th) {
1.937 - entry = th;
1.938 - }
1.939 - future.set(entry);
1.940 - Caches.reflectors.put(key, new SoftReference<Object>(entry));
1.941 - }
1.942 -
1.943 - if (entry instanceof FieldReflector) {
1.944 - return (FieldReflector) entry;
1.945 - } else if (entry instanceof InvalidClassException) {
1.946 - throw (InvalidClassException) entry;
1.947 - } else if (entry instanceof RuntimeException) {
1.948 - throw (RuntimeException) entry;
1.949 - } else if (entry instanceof Error) {
1.950 - throw (Error) entry;
1.951 - } else {
1.952 - throw new InternalError("unexpected entry: " + entry);
1.953 - }
1.954 - }
1.955 -
1.956 - /**
1.957 - * FieldReflector cache lookup key. Keys are considered equal if they
1.958 - * refer to the same class and equivalent field formats.
1.959 - */
1.960 - private static class FieldReflectorKey extends WeakReference<Class<?>> {
1.961 -
1.962 - private final String sigs;
1.963 - private final int hash;
1.964 - private final boolean nullClass;
1.965 -
1.966 - FieldReflectorKey(Class<?> cl, ObjectStreamField[] fields,
1.967 - ReferenceQueue<Class<?>> queue)
1.968 - {
1.969 - super(cl, queue);
1.970 - nullClass = (cl == null);
1.971 - StringBuilder sbuf = new StringBuilder();
1.972 - for (int i = 0; i < fields.length; i++) {
1.973 - ObjectStreamField f = fields[i];
1.974 - sbuf.append(f.getName()).append(f.getSignature());
1.975 - }
1.976 - sigs = sbuf.toString();
1.977 - hash = System.identityHashCode(cl) + sigs.hashCode();
1.978 - }
1.979 -
1.980 - public int hashCode() {
1.981 - return hash;
1.982 - }
1.983 -
1.984 - public boolean equals(Object obj) {
1.985 - if (obj == this) {
1.986 - return true;
1.987 - }
1.988 -
1.989 - if (obj instanceof FieldReflectorKey) {
1.990 - FieldReflectorKey other = (FieldReflectorKey) obj;
1.991 - Class<?> referent;
1.992 - return (nullClass ? other.nullClass
1.993 - : ((referent = get()) != null) &&
1.994 - (referent == other.get())) &&
1.995 - sigs.equals(other.sigs);
1.996 - } else {
1.997 - return false;
1.998 - }
1.999 - }
1.1000 - }
1.1001 -
1.1002 - /**
1.1003 - * Matches given set of serializable fields with serializable fields
1.1004 - * obtained from the given local class descriptor (which contain bindings
1.1005 - * to reflective Field objects). Returns list of ObjectStreamFields in
1.1006 - * which each ObjectStreamField whose signature matches that of a local
1.1007 - * field contains a Field object for that field; unmatched
1.1008 - * ObjectStreamFields contain null Field objects. Shared/unshared settings
1.1009 - * of the returned ObjectStreamFields also reflect those of matched local
1.1010 - * ObjectStreamFields. Throws InvalidClassException if unresolvable type
1.1011 - * conflicts exist between the two sets of fields.
1.1012 - */
1.1013 - private static ObjectStreamField[] matchFields(ObjectStreamField[] fields,
1.1014 - ObjectStreamClass localDesc)
1.1015 - throws InvalidClassException
1.1016 - {
1.1017 - ObjectStreamField[] localFields = (localDesc != null) ?
1.1018 - localDesc.fields : NO_FIELDS;
1.1019 -
1.1020 - /*
1.1021 - * Even if fields == localFields, we cannot simply return localFields
1.1022 - * here. In previous implementations of serialization,
1.1023 - * ObjectStreamField.getType() returned Object.class if the
1.1024 - * ObjectStreamField represented a non-primitive field and belonged to
1.1025 - * a non-local class descriptor. To preserve this (questionable)
1.1026 - * behavior, the ObjectStreamField instances returned by matchFields
1.1027 - * cannot report non-primitive types other than Object.class; hence
1.1028 - * localFields cannot be returned directly.
1.1029 - */
1.1030 -
1.1031 - ObjectStreamField[] matches = new ObjectStreamField[fields.length];
1.1032 - for (int i = 0; i < fields.length; i++) {
1.1033 - ObjectStreamField f = fields[i], m = null;
1.1034 - for (int j = 0; j < localFields.length; j++) {
1.1035 - ObjectStreamField lf = localFields[j];
1.1036 - if (f.getName().equals(lf.getName())) {
1.1037 - if ((f.isPrimitive() || lf.isPrimitive()) &&
1.1038 - f.getTypeCode() != lf.getTypeCode())
1.1039 - {
1.1040 - throw new InvalidClassException(localDesc.name,
1.1041 - "incompatible types for field " + f.getName());
1.1042 - }
1.1043 - if (lf.getField() != null) {
1.1044 - m = new ObjectStreamField(
1.1045 - lf.getField(), lf.isUnshared(), false);
1.1046 - } else {
1.1047 - m = new ObjectStreamField(
1.1048 - lf.getName(), lf.getSignature(), lf.isUnshared());
1.1049 - }
1.1050 - }
1.1051 - }
1.1052 - if (m == null) {
1.1053 - m = new ObjectStreamField(
1.1054 - f.getName(), f.getSignature(), false);
1.1055 - }
1.1056 - m.setOffset(f.getOffset());
1.1057 - matches[i] = m;
1.1058 - }
1.1059 - return matches;
1.1060 - }
1.1061 -
1.1062 - /**
1.1063 - * Removes from the specified map any keys that have been enqueued
1.1064 - * on the specified reference queue.
1.1065 - */
1.1066 - static void processQueue(ReferenceQueue<Class<?>> queue,
1.1067 - ConcurrentMap<? extends
1.1068 - WeakReference<Class<?>>, ?> map)
1.1069 - {
1.1070 - Reference<? extends Class<?>> ref;
1.1071 - while((ref = queue.poll()) != null) {
1.1072 - map.remove(ref);
1.1073 - }
1.1074 - }
1.1075 -
1.1076 - /**
1.1077 - * Weak key for Class objects.
1.1078 - *
1.1079 - **/
1.1080 - static class WeakClassKey extends WeakReference<Class<?>> {
1.1081 - /**
1.1082 - * saved value of the referent's identity hash code, to maintain
1.1083 - * a consistent hash code after the referent has been cleared
1.1084 - */
1.1085 - private final int hash;
1.1086 -
1.1087 - /**
1.1088 - * Create a new WeakClassKey to the given object, registered
1.1089 - * with a queue.
1.1090 - */
1.1091 - WeakClassKey(Class<?> cl, ReferenceQueue<Class<?>> refQueue) {
1.1092 - super(cl, refQueue);
1.1093 - hash = System.identityHashCode(cl);
1.1094 - }
1.1095 -
1.1096 - /**
1.1097 - * Returns the identity hash code of the original referent.
1.1098 - */
1.1099 - public int hashCode() {
1.1100 - return hash;
1.1101 - }
1.1102 -
1.1103 - /**
1.1104 - * Returns true if the given object is this identical
1.1105 - * WeakClassKey instance, or, if this object's referent has not
1.1106 - * been cleared, if the given object is another WeakClassKey
1.1107 - * instance with the identical non-null referent as this one.
1.1108 - */
1.1109 - public boolean equals(Object obj) {
1.1110 - if (obj == this) {
1.1111 - return true;
1.1112 - }
1.1113 -
1.1114 - if (obj instanceof WeakClassKey) {
1.1115 - Object referent = get();
1.1116 - return (referent != null) &&
1.1117 - (referent == ((WeakClassKey) obj).get());
1.1118 - } else {
1.1119 - return false;
1.1120 - }
1.1121 - }
1.1122 - }
1.1123 }