OpenJDK / jdk / hs
changeset 2069:2cd4a0aa917f
6806649: synchronization bottleneck when constructing Thread subclasses
Summary: Replace subclass audits synchronization with ConcurrentHashMap with weakly referenced Class keys
Reviewed-by: peterjones, dholmes, martin
author | chegar |
---|---|
date | Mon, 23 Feb 2009 10:36:19 +0000 |
parents | cdbc5929b91e |
children | 6e9972fbd965 5e6af6d106cb |
files | jdk/src/share/classes/java/lang/Thread.java |
diffstat | 1 files changed, 85 insertions(+), 14 deletions(-) [+] |
line wrap: on
line diff
--- a/jdk/src/share/classes/java/lang/Thread.java Mon Feb 23 17:32:52 2009 +0800 +++ b/jdk/src/share/classes/java/lang/Thread.java Mon Feb 23 10:36:19 2009 +0000 @@ -25,13 +25,17 @@ 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.AccessControlContext; import java.security.PrivilegedAction; import java.util.Map; import java.util.HashMap; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.ConcurrentMap; import java.util.concurrent.locks.LockSupport; -import sun.misc.SoftCache; import sun.nio.ch.Interruptible; import sun.security.util.SecurityConstants; @@ -1640,8 +1644,17 @@ new RuntimePermission("enableContextClassLoaderOverride"); /** cache of subclass security audit results */ - private static final SoftCache subclassAudits = new SoftCache(10); + /* Replace with ConcurrentReferenceHashMap when/if it appears in a future + * release */ + private static class Caches { + /** cache of subclass security audit results */ + static final ConcurrentMap<WeakClassKey,Boolean> subclassAudits = + new ConcurrentHashMap<WeakClassKey,Boolean>(); + /** queue for WeakReferences to audited subclasses */ + static final ReferenceQueue<Class<?>> subclassAuditsQueue = + new ReferenceQueue<Class<?>>(); + } /** * Verifies that this (possibly subclass) instance can be constructed @@ -1652,19 +1665,15 @@ private static boolean isCCLOverridden(Class cl) { if (cl == Thread.class) return false; - Boolean result = null; - synchronized (subclassAudits) { - result = (Boolean) subclassAudits.get(cl); - if (result == null) { - /* - * Note: only new Boolean instances (i.e., not Boolean.TRUE or - * Boolean.FALSE) must be used as cache values, otherwise cache - * entry will pin associated class. - */ - result = new Boolean(auditSubclass(cl)); - subclassAudits.put(cl, result); - } + + processQueue(Caches.subclassAuditsQueue, Caches.subclassAudits); + 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(); } @@ -1967,6 +1976,68 @@ 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) { + Object referent = get(); + return (referent != null) && + (referent == ((WeakClassKey) obj).get()); + } else { + return false; + } + } + } + /* Some private helper methods */ private native void setPriority0(int newPriority); private native void stop0(Object o);