privatestaticclassCaches{ /** cache mapping local classes -> descriptors */ staticfinal ConcurrentMap<ObjectStreamClass.WeakClassKey,Reference<?>> localDescs = new ConcurrentHashMap<>();
/** cache mapping field group/local desc pairs -> field reflectors */ staticfinal ConcurrentMap<ObjectStreamClass.FieldReflectorKey,Reference<?>> reflectors = new ConcurrentHashMap<>();
/** queue for WeakReferences to local classes */ privatestaticfinal ReferenceQueue<Class<?>> localDescsQueue = new ReferenceQueue<>(); /** queue for WeakReferences to field reflectors keys */ privatestaticfinal ReferenceQueue<Class<?>> reflectorsQueue = new ReferenceQueue<>(); }
static ObjectStreamClass lookup(Class<?> cl, boolean all){ if (!(all || Serializable.class.isAssignableFrom(cl))) { returnnull; } processQueue(ObjectStreamClass.Caches.localDescsQueue, ObjectStreamClass.Caches.localDescs); ObjectStreamClass.WeakClassKey key = new ObjectStreamClass.WeakClassKey(cl, ObjectStreamClass.Caches.localDescsQueue); Reference<?> ref = ObjectStreamClass.Caches.localDescs.get(key); Object entry = null; if (ref != null) { entry = ref.get(); } ObjectStreamClass.EntryFuture future = null; if (entry == null) { ObjectStreamClass.EntryFuture newEntry = new ObjectStreamClass.EntryFuture(); Reference<?> newRef = new SoftReference<>(newEntry); do { if (ref != null) { ObjectStreamClass.Caches.localDescs.remove(key, ref); } ref = ObjectStreamClass.Caches.localDescs.putIfAbsent(key, newRef); if (ref != null) { entry = ref.get(); } } while (ref != null && entry == null); if (entry == null) { future = newEntry; } }
if (entry instanceof ObjectStreamClass) { // check common case first return (ObjectStreamClass) entry; } if (entry instanceof ObjectStreamClass.EntryFuture) { future = (ObjectStreamClass.EntryFuture) entry; if (future.getOwner() == Thread.currentThread()) { /* * Handle nested call situation described by 4803747: waiting * for future value to be set by a lookup() call further up the * stack will result in deadlock, so calculate and set the * future value here instead. */ entry = null; } else { entry = future.get(); } } if (entry == null) { try { entry = new ObjectStreamClass(cl); } catch (Throwable th) { entry = th; } if (future.set(entry)) { ObjectStreamClass.Caches.localDescs.put(key, new SoftReference<Object>(entry)); } else { // nested lookup call already set future entry = future.get(); } }