8016236: Class.getGenericInterfaces performance improvement
authorshade
Mon, 17 Jun 2013 16:28:22 +0400
changeset 18179 9b6ad451b521
parent 18178 ee71c923891d
child 18180 e0b8c923f35d
8016236: Class.getGenericInterfaces performance improvement Summary: cache more reflective data and lookup results. Reviewed-by: alanb, plevart, psandoz, dl Contributed-by: Doug Lea <dl@cs.oswego.edu>, Aleksey Shipilev <aleksey.shipilev@oracle.com>
jdk/src/share/classes/java/lang/Class.java
jdk/src/share/classes/sun/reflect/generics/repository/ClassRepository.java
jdk/src/share/native/java/lang/Class.c
--- a/jdk/src/share/classes/java/lang/Class.java	Mon Jun 17 14:09:25 2013 +0100
+++ b/jdk/src/share/classes/java/lang/Class.java	Mon Jun 17 16:28:22 2013 +0400
@@ -708,8 +708,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];
     }
@@ -759,15 +760,19 @@
      * @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
+        ClassRepository info = getGenericInfo();
+        if (info == null) {
             return getSuperclass();
+        }
+
+        // Historical irregularity:
+        // Generic signature marks interfaces with superclass = Object
+        // but this API returns null for interfaces
+        if (isInterface()) {
+            return null;
+        }
+
+        return info.getSuperclass();
     }
 
     /**
@@ -830,7 +835,23 @@
      *
      * @return an array of interfaces implemented by this class.
      */
-    public native Class<?>[] getInterfaces();
+    public Class<?>[] getInterfaces() {
+        ReflectionData<T> rd = reflectionData();
+        if (rd == null) {
+            // no cloning required
+            return getInterfaces0();
+        } else {
+            Class<?>[] interfaces = rd.interfaces;
+            if (interfaces == null) {
+                interfaces = getInterfaces0();
+                rd.interfaces = interfaces;
+            }
+            // defensively copy before handing over to user code
+            return interfaces.clone();
+        }
+    }
+
+    private native Class<?>[] getInterfaces0();
 
     /**
      * Returns the {@code Type}s representing the interfaces
@@ -882,10 +903,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();
     }
 
 
@@ -2313,6 +2332,8 @@
         // Intermediate results for getFields and getMethods
         volatile Field[] declaredPublicFields;
         volatile Method[] declaredPublicMethods;
+        volatile Class<?>[] interfaces;
+
         // Value of classRedefinedCount when we created this ReflectionData instance
         final int redefinedCount;
 
@@ -2388,10 +2409,10 @@
     }
 
     // Generic signature handling
-    private native String getGenericSignature();
+    private native String getGenericSignature0();
 
     // Generic info repository; lazily initialized
-    private transient ClassRepository genericInfo;
+    private volatile transient ClassRepository genericInfo;
 
     // accessor for factory
     private GenericsFactory getFactory() {
@@ -2399,15 +2420,20 @@
         return CoreReflectionFactory.make(this, ClassScope.make(this));
     }
 
-    // accessor for generic info repository
+    // accessor for generic info repository;
+    // generic info is lazily initialized
     private ClassRepository getGenericInfo() {
-        // lazily initialize repository if necessary
+        ClassRepository genericInfo = this.genericInfo;
         if (genericInfo == null) {
-            // create and cache generic info repository
-            genericInfo = ClassRepository.make(getGenericSignature(),
-                                               getFactory());
+            String signature = getGenericSignature0();
+            if (signature == null) {
+                genericInfo = ClassRepository.NONE;
+            } else {
+                genericInfo = ClassRepository.make(signature, getFactory());
+            }
+            this.genericInfo = genericInfo;
         }
-        return genericInfo; //return cached repository
+        return (genericInfo != ClassRepository.NONE) ? genericInfo : null;
     }
 
     // Annotations handling
--- a/jdk/src/share/classes/sun/reflect/generics/repository/ClassRepository.java	Mon Jun 17 14:09:25 2013 +0100
+++ b/jdk/src/share/classes/sun/reflect/generics/repository/ClassRepository.java	Mon Jun 17 16:28:22 2013 +0400
@@ -40,6 +40,8 @@
  */
 public class ClassRepository extends GenericDeclRepository<ClassSignature> {
 
+    public static final ClassRepository NONE = ClassRepository.make("Ljava/lang/Object;", null);
+
     private Type superclass; // caches the generic superclass info
     private Type[] superInterfaces; // caches the generic superinterface info
 
--- a/jdk/src/share/native/java/lang/Class.c	Mon Jun 17 14:09:25 2013 +0100
+++ b/jdk/src/share/native/java/lang/Class.c	Mon Jun 17 16:28:22 2013 +0400
@@ -55,7 +55,7 @@
 static JNINativeMethod methods[] = {
     {"getName0",         "()" STR,          (void *)&JVM_GetClassName},
     {"getSuperclass",    "()" CLS,          NULL},
-    {"getInterfaces",    "()[" CLS,         (void *)&JVM_GetClassInterfaces},
+    {"getInterfaces0",   "()[" CLS,         (void *)&JVM_GetClassInterfaces},
     {"getClassLoader0",  "()" JCL,          (void *)&JVM_GetClassLoader},
     {"isInterface",      "()Z",             (void *)&JVM_IsInterface},
     {"getSigners",       "()[" OBJ,         (void *)&JVM_GetClassSigners},
@@ -70,7 +70,7 @@
     {"getProtectionDomain0", "()" PD,       (void *)&JVM_GetProtectionDomain},
     {"getDeclaredClasses0",  "()[" CLS,      (void *)&JVM_GetDeclaredClasses},
     {"getDeclaringClass",   "()" CLS,      (void *)&JVM_GetDeclaringClass},
-    {"getGenericSignature", "()" STR,       (void *)&JVM_GetClassSignature},
+    {"getGenericSignature0", "()" STR,      (void *)&JVM_GetClassSignature},
     {"getRawAnnotations",      "()" BA,        (void *)&JVM_GetClassAnnotations},
     {"getConstantPool",     "()" CPL,       (void *)&JVM_GetClassConstantPool},
     {"desiredAssertionStatus0","("CLS")Z",(void *)&JVM_DesiredAssertionStatus},