While tracking down performance issues in some reflective
checks used inside ConcurrentHashMap, I noticed that
method Class.getGenericInterfaces (as well as methods
getGenericSuperclass and getTypeParameters) entail
an expensive unnecessary recheck on each invocation.

Each relies primarily on (internal) method getGenericInfo, that
uses an instance cached on first invocation (or remains null
if the class is not generic). But these calling methods preface
the call with a call to getGenericSignature which is a
relatively expensive JNI method. This call is unnecessary if
the genericInfo has already been constructed. Reworking to
avoid this makes repeated calls very noticeably faster.

The diffs below show one way to do this.
Could someone who works on reflection check and
sponsor this change?

Thanks!


diff -r 30101f69e66f src/share/classes/java/lang/Class.java
--- a/src/share/classes/java/lang/Class.java    Fri May 17 10:11:35 2013 -0700
+++ b/src/share/classes/java/lang/Class.java    Sat Jun 08 10:33:32 2013 -0400
@@ -707,8 +707,9 @@
      */
     @SuppressWarnings("unchecked")
     public TypeVariable<Class<T>>[] getTypeParameters() {
-        if (getGenericSignature() != null)
-            return 
(TypeVariable<Class<T>>[])getGenericInfo().getTypeParameters();
+        ClassRepository info = getGenericInfo();
+        if (info != null)
+            return (TypeVariable<Class<T>>[])info.getTypeParameters();
         else
             return (TypeVariable<Class<T>>[])new TypeVariable<?>[0];
     }
@@ -758,15 +759,13 @@
      * @since 1.5
      */
     public Type getGenericSuperclass() {
-        if (getGenericSignature() != null) {
-            // Historical irregularity:
-            // Generic signature marks interfaces with superclass = Object
-            // but this API returns null for interfaces
-            if (isInterface())
-                return null;
-            return getGenericInfo().getSuperclass();
-        } else
-            return getSuperclass();
+        // Historical irregularity:
+        // Generic signature marks interfaces with superclass = Object
+        // but this API returns null for interfaces
+        ClassRepository info = getGenericInfo();
+        return (info == null ? getSuperclass() :
+                isInterface() ?  null :
+                info.getSuperclass());
     }

     /**
@@ -881,10 +880,8 @@
      * @since 1.5
      */
     public Type[] getGenericInterfaces() {
-        if (getGenericSignature() != null)
-            return getGenericInfo().getSuperInterfaces();
-        else
-            return getInterfaces();
+        ClassRepository info = getGenericInfo();
+        return (info == null) ?  getInterfaces() : info.getSuperInterfaces();
     }


@@ -2409,12 +2406,11 @@
     // accessor for generic info repository
     private ClassRepository getGenericInfo() {
         // lazily initialize repository if necessary
-        if (genericInfo == null) {
-            // create and cache generic info repository
-            genericInfo = ClassRepository.make(getGenericSignature(),
-                                               getFactory());
-        }
-        return genericInfo; //return cached repository
+        String signature;
+        ClassRepository info = genericInfo;
+        return (info != null ? info :
+                (signature = getGenericSignature()) == null ? null :
+                (genericInfo = ClassRepository.make(signature, getFactory())));
     }

     // Annotations handling

Reply via email to