8279917: Refactor subclassAudits in Thread to use ClassValue

Reviewed-by: alanb, rriggs
This commit is contained in:
Roman Kennke 2022-02-02 14:56:52 +00:00
parent 4ea6037ea5
commit ce71e8b281

View file

@ -25,16 +25,11 @@
package java.lang; package java.lang;
import java.lang.ref.Reference;
import java.lang.ref.ReferenceQueue;
import java.lang.ref.WeakReference;
import java.security.AccessController; import java.security.AccessController;
import java.security.AccessControlContext; import java.security.AccessControlContext;
import java.security.PrivilegedAction; import java.security.PrivilegedAction;
import java.util.Map; import java.util.Map;
import java.util.HashMap; import java.util.HashMap;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.LockSupport; import java.util.concurrent.locks.LockSupport;
@ -1672,16 +1667,15 @@ public class Thread implements Runnable {
} }
/** cache of subclass security audit results */ /** cache of subclass security audit results */
/* Replace with ConcurrentReferenceHashMap when/if it appears in a future
* release */
private static class Caches { private static class Caches {
/** cache of subclass security audit results */ /** cache of subclass security audit results */
static final ConcurrentMap<WeakClassKey,Boolean> subclassAudits = static final ClassValue<Boolean> subclassAudits =
new ConcurrentHashMap<>(); new ClassValue<>() {
@Override
/** queue for WeakReferences to audited subclasses */ protected Boolean computeValue(Class<?> type) {
static final ReferenceQueue<Class<?>> subclassAuditsQueue = return auditSubclass(type);
new ReferenceQueue<>(); }
};
} }
/** /**
@ -1694,15 +1688,7 @@ public class Thread implements Runnable {
if (cl == Thread.class) if (cl == Thread.class)
return false; return false;
processQueue(Caches.subclassAuditsQueue, Caches.subclassAudits); return Caches.subclassAudits.get(cl);
WeakClassKey key = new WeakClassKey(cl, Caches.subclassAuditsQueue);
Boolean result = Caches.subclassAudits.get(key);
if (result == null) {
result = Boolean.valueOf(auditSubclass(cl));
Caches.subclassAudits.putIfAbsent(key, result);
}
return result.booleanValue();
} }
/** /**
@ -2008,69 +1994,6 @@ public class Thread implements Runnable {
getUncaughtExceptionHandler().uncaughtException(this, e); getUncaughtExceptionHandler().uncaughtException(this, e);
} }
/**
* Removes from the specified map any keys that have been enqueued
* on the specified reference queue.
*/
static void processQueue(ReferenceQueue<Class<?>> queue,
ConcurrentMap<? extends
WeakReference<Class<?>>, ?> map)
{
Reference<? extends Class<?>> ref;
while((ref = queue.poll()) != null) {
map.remove(ref);
}
}
/**
* Weak key for Class objects.
**/
static class WeakClassKey extends WeakReference<Class<?>> {
/**
* saved value of the referent's identity hash code, to maintain
* a consistent hash code after the referent has been cleared
*/
private final int hash;
/**
* Create a new WeakClassKey to the given object, registered
* with a queue.
*/
WeakClassKey(Class<?> cl, ReferenceQueue<Class<?>> refQueue) {
super(cl, refQueue);
hash = System.identityHashCode(cl);
}
/**
* Returns the identity hash code of the original referent.
*/
@Override
public int hashCode() {
return hash;
}
/**
* Returns true if the given object is this identical
* WeakClassKey instance, or, if this object's referent has not
* been cleared, if the given object is another WeakClassKey
* instance with the identical non-null referent as this one.
*/
@Override
public boolean equals(Object obj) {
if (obj == this)
return true;
if (obj instanceof WeakClassKey) {
Class<?> referent = get();
return (referent != null) &&
(((WeakClassKey) obj).refersTo(referent));
} else {
return false;
}
}
}
// The following three initially uninitialized fields are exclusively // The following three initially uninitialized fields are exclusively
// managed by class java.util.concurrent.ThreadLocalRandom. These // managed by class java.util.concurrent.ThreadLocalRandom. These
// fields are used to build the high-performance PRNGs in the // fields are used to build the high-performance PRNGs in the