You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@harmony.apache.org by nd...@apache.org on 2008/05/27 00:32:02 UTC

svn commit: r660328 - /harmony/enhanced/drlvm/trunk/vm/vmcore/src/kernel_classes/javasrc/java/lang/Class.java

Author: ndbeyer
Date: Mon May 26 15:31:59 2008
New Revision: 660328

URL: http://svn.apache.org/viewvc?rev=660328&view=rev
Log:
rebuild ReflectionData inner class to be more efficient and thread-safe; pull in some recent serialization data to ReflectionData; this should make the file much more readable in general and easy to maintain

Modified:
    harmony/enhanced/drlvm/trunk/vm/vmcore/src/kernel_classes/javasrc/java/lang/Class.java

Modified: harmony/enhanced/drlvm/trunk/vm/vmcore/src/kernel_classes/javasrc/java/lang/Class.java
URL: http://svn.apache.org/viewvc/harmony/enhanced/drlvm/trunk/vm/vmcore/src/kernel_classes/javasrc/java/lang/Class.java?rev=660328&r1=660327&r2=660328&view=diff
==============================================================================
--- harmony/enhanced/drlvm/trunk/vm/vmcore/src/kernel_classes/javasrc/java/lang/Class.java (original)
+++ harmony/enhanced/drlvm/trunk/vm/vmcore/src/kernel_classes/javasrc/java/lang/Class.java Mon May 26 15:31:59 2008
@@ -222,26 +222,14 @@
      */
     ClassLoader definingLoader;
     
-    // TODO make it soft reference
-    transient ReflectionData reflectionData;
     transient SoftReference<GACache> softCache;
     
+    private transient volatile ReflectionData _reflectionData;
+    
     private transient ProtectionDomain domain;
 
     /** It is required for synchronization in newInstance method. */
-    private boolean isDefaultConstructorInitialized;
-    
-    /** 
-     * Indicates whether the following properties have been calculated;
-     * isSerializable, isExternalizable, isPrimitive
-     * 
-     * @see #resolveProperties() 
-     */
-    private transient volatile boolean arePropertiesResolved;
-    
-    private transient boolean isSerializable;
-    private transient boolean isExternalizable;
-    private transient boolean isPrimitive;
+    private volatile boolean isDefaultConstructorInitialized;
 
     /**
      * Only VM can instantiate this class.
@@ -249,6 +237,22 @@
     private Class() {
     }
 
+    /**
+     * Accessor for the reflection data field, which needs to have
+     * minimal thread-safety for consistency; this method encapsulates
+     * that.
+     */
+    private ReflectionData getReflectionData() {
+        // read the volatile field once
+        final ReflectionData localData = _reflectionData;
+        if (localData == null){
+            // if null, construct, write to the field and return
+            return _reflectionData = new ReflectionData();
+        }
+        // else, just return the field
+        return localData;
+    }
+
     private GACache getCache() {
         GACache cache = null;
         if (softCache != null) { 
@@ -322,9 +326,6 @@
      * Java 1.5 API specification doesn't require this check.
      */
     public Class<?>[] getClasses() {
-        if (reflectionData == null) {
-            initReflectionData();
-        }
         checkMemberAccess(Member.PUBLIC);
         Class<?> clss = this;
         ArrayList<Class<?>> classes = null;
@@ -371,11 +372,8 @@
 
     public Constructor<T> getConstructor(Class<?>... argumentTypes)
         throws NoSuchMethodException {
-        if (reflectionData == null) {
-            initReflectionData();
-        }
         checkMemberAccess(Member.PUBLIC);
-        Constructor<T> ctors[] = reflectionData.getPublicConstructors(); 
+        Constructor<T> ctors[] = getReflectionData().getPublicConstructors(); 
         for (int i = 0; i < ctors.length; i++) {
             Constructor<T> c = ctors[i];
             try {
@@ -390,18 +388,12 @@
 
     @SuppressWarnings("unchecked")
     public Constructor[] getConstructors() {
-        if (reflectionData == null) {
-            initReflectionData();
-        }
         checkMemberAccess(Member.PUBLIC);
-        return Reflection.copyConstructors(reflectionData.getPublicConstructors());
+        return Reflection.copyConstructors(getReflectionData().getPublicConstructors());
     }
 
     @SuppressWarnings("unchecked")
     public Class[] getDeclaredClasses() {
-        if (reflectionData == null) {
-            initReflectionData();
-        }
         checkMemberAccess(Member.DECLARED);
         return VMClassRegistry.getDeclaredClasses(this);
     }
@@ -409,9 +401,6 @@
     @SuppressWarnings("unchecked")
     public Constructor<T> getDeclaredConstructor(Class... argumentTypes)
         throws NoSuchMethodException {
-        if (reflectionData == null) {
-            initReflectionData();
-        }
         checkMemberAccess(Member.DECLARED);
         return Reflection
             .copyConstructor(getDeclaredConstructorInternal(argumentTypes));
@@ -419,26 +408,15 @@
 
     @SuppressWarnings("unchecked")
     public Constructor[] getDeclaredConstructors() {
-        if (reflectionData == null) {
-            initReflectionData();
-        }
         checkMemberAccess(Member.DECLARED);
-        if (reflectionData.declaredConstructors == null) {
-            reflectionData.initDeclaredConstructors();
-        }
-        return Reflection.copyConstructors(reflectionData.declaredConstructors);
+        return Reflection.copyConstructors(getReflectionData().getDeclaredConstructors());
     }
 
     public Field getDeclaredField(String fieldName) throws NoSuchFieldException {
-        if (reflectionData == null) {
-            initReflectionData();
-        }
         checkMemberAccess(Member.DECLARED);
-        if (reflectionData.declaredFields == null) {
-            reflectionData.initDeclaredFields();
-        }
-        for (int i = 0; i < reflectionData.declaredFields.length; i++) {
-            Field f = reflectionData.declaredFields[i];
+        final Field[] declaredFields = getReflectionData().getDeclaredFields();
+        for (int i = 0; i < declaredFields.length; i++) {
+            Field f = declaredFields[i];
             if (fieldName.equals(f.getName())) {
                 return Reflection.copyField(f);
             }
@@ -447,40 +425,22 @@
     }
 
     public Field[] getDeclaredFields() {
-        if (reflectionData == null) {
-            initReflectionData();
-        }
         checkMemberAccess(Member.DECLARED);
-        if (reflectionData.declaredFields == null) {
-            reflectionData.initDeclaredFields();
-        }
-        return Reflection.copyFields(reflectionData.declaredFields);
+        return Reflection.copyFields(getReflectionData().getDeclaredFields());
     }
 
     @SuppressWarnings("unchecked")
     public Method getDeclaredMethod(String methodName, Class... argumentTypes)
         throws NoSuchMethodException {
-        if (reflectionData == null) {
-            initReflectionData();
-        }
         checkMemberAccess(Member.DECLARED);
-        if (reflectionData.declaredMethods == null) {
-            reflectionData.initDeclaredMethods();
-        }
         return Reflection
-            .copyMethod(findMatchingMethod(reflectionData.declaredMethods,
+            .copyMethod(findMatchingMethod(getReflectionData().getDeclaredMethods(),
                                            methodName, argumentTypes));
     }
 
     public Method[] getDeclaredMethods() {
-        if (reflectionData == null) {
-            initReflectionData();
-        }
         checkMemberAccess(Member.DECLARED);
-        if (reflectionData.declaredMethods == null) {
-            reflectionData.initDeclaredMethods();
-        }
-        return Reflection.copyMethods(reflectionData.declaredMethods);
+        return Reflection.copyMethods(getReflectionData().getDeclaredMethods());
     }
 
     public Class<?> getDeclaringClass() {
@@ -488,12 +448,9 @@
     }
 
     public Field getField(String fieldName) throws NoSuchFieldException {
-        if (reflectionData == null) {
-            initReflectionData();
-        }
         checkMemberAccess(Member.PUBLIC);
-        Field[] ff = reflectionData.getPublicFields();
-        for (Field f : ff) {
+        final Field[] fields = getReflectionData().getPublicFields();
+        for (Field f : fields) {
             if (fieldName.equals(f.getName())) {
                 return Reflection.copyField(f);
             }
@@ -502,11 +459,8 @@
     }
 
     public Field[] getFields() {
-        if (reflectionData == null) {
-            initReflectionData();
-        }
         checkMemberAccess(Member.PUBLIC);
-        return Reflection.copyFields(reflectionData.getPublicFields());
+        return Reflection.copyFields(getReflectionData().getPublicFields());
     }
 
     @SuppressWarnings("unchecked")
@@ -517,39 +471,23 @@
     @SuppressWarnings("unchecked")
     public Method getMethod(String methodName, Class... argumentTypes)
         throws NoSuchMethodException {
-        if (reflectionData == null) {
-            initReflectionData();
-        }
         checkMemberAccess(Member.PUBLIC);
         return Reflection
-            .copyMethod(findMatchingMethod(reflectionData.getPublicMethods(),
+            .copyMethod(findMatchingMethod(getReflectionData().getPublicMethods(),
                                            methodName, argumentTypes));
     }
 
     public Method[] getMethods() {
-        if (reflectionData == null) {
-            initReflectionData();
-        }
         checkMemberAccess(Member.PUBLIC);
-        return Reflection.copyMethods(reflectionData.getPublicMethods());
+        return Reflection.copyMethods(getReflectionData().getPublicMethods());
     }
 
     public int getModifiers() {
-        if (reflectionData == null) {
-            initReflectionData();
-        }
-        int mods = reflectionData.modifiers;
-        if (mods == -1) {
-            mods = reflectionData.modifiers = VMClassRegistry.getModifiers(this); 
-        }
-        return mods;
+        return getReflectionData().getModifiers();
     }
 
     public String getName() {
-        if (reflectionData == null) {
-            initReflectionData();
-        }
-        return reflectionData.name;
+        return getReflectionData().name;
     }
 
     public Package getPackage() {
@@ -610,34 +548,17 @@
     }
 
     public boolean isArray() {
-        if (reflectionData == null) {
-            initReflectionData();
-        }
-        return reflectionData.isArray;
-    }
-
-    private void resolveProperties() {
-        if (arePropertiesResolved) {
-            return;
-        }
-        isExternalizable = VMClassRegistry.isAssignableFrom(Externalizable.class, this);
-        isSerializable = VMClassRegistry.isAssignableFrom(Serializable.class, this);
-        isPrimitive = VMClassRegistry.isPrimitive(this);
-        arePropertiesResolved = true;
+        return getReflectionData().isArray;
     }
     
     public boolean isAssignableFrom(Class<?> clazz) {
         
         if (Serializable.class.equals(this)) {
-            // assure that props have been resolved
-            clazz.resolveProperties();
-            return clazz.isSerializable;
+            return clazz.getReflectionData().isSerializable();
         }
         
         if (Externalizable.class.equals(this)) {
-            // assure that props have been resolved
-            clazz.resolveProperties();
-            return clazz.isExternalizable;
+            return clazz.getReflectionData().isExternalizable();
         }
         
         return VMClassRegistry.isAssignableFrom(this, clazz);
@@ -652,21 +573,17 @@
     }
 
     public boolean isPrimitive() {
-        // assure that props have been resolved
-        resolveProperties();
-        return isPrimitive;
+        return getReflectionData().isPrimitive;
     }
 
     public T newInstance() throws InstantiationException,
             IllegalAccessException {
         T newInstance = null;
-        if (reflectionData == null) {
-            initReflectionData();
-        }
+        final ReflectionData localReflectionData = getReflectionData();
         SecurityManager sc = System.getSecurityManager();
         if (sc != null) {
             sc.checkMemberAccess(this, Member.PUBLIC);
-            sc.checkPackageAccess(reflectionData.packageName);
+            sc.checkPackageAccess(localReflectionData.packageName);
         }
 
         /*
@@ -681,20 +598,19 @@
          *   the access rights by mistake and IllegalAccessException happens
          */
         while (!isDefaultConstructorInitialized) {
-            synchronized (reflectionData) {
+            synchronized (localReflectionData) {
                 if (isDefaultConstructorInitialized) {
                     break; // non-first threads can be here - nothing to do
                 }
 
                 // only first thread can reach this point & do initialization
+                final Constructor<T> c;
                 try {
-                    reflectionData.initDefaultConstructor();
+                    c = localReflectionData.getDefaultConstructor();
                 } catch (NoSuchMethodException e) {
                     throw new InstantiationException(e.getMessage()
                             + " method not found");
                 }
-                final Constructor<T> c = reflectionData.defaultConstructor;
-
                 try {
                     AccessController.doPrivileged(new PrivilegedAction<Object>() {
                             public Object run() {
@@ -716,15 +632,21 @@
         }
 
         // initialization is done, threads may work from here in any order
+        final Constructor<T> defaultConstructor;
+        try {
+            defaultConstructor = localReflectionData.getDefaultConstructor();
+        } catch (NoSuchMethodException e){
+            throw new AssertionError(e);
+        }
         Reflection.checkMemberAccess(
                 VMStack.getCallerClass(0),
-                reflectionData.defaultConstructor.getDeclaringClass(),
-                reflectionData.defaultConstructor.getDeclaringClass(),
-                reflectionData.defaultConstructor.getModifiers()
+                defaultConstructor.getDeclaringClass(),
+                defaultConstructor.getDeclaringClass(),
+                defaultConstructor.getModifiers()
             );
 
         try {
-            newInstance = reflectionData.defaultConstructor.newInstance();
+            newInstance = defaultConstructor.newInstance();
         } catch (InvocationTargetException e) {
             System.rethrow(e.getCause());
         }
@@ -736,23 +658,8 @@
             : (isInterface() ? "interface " : "class ") + getName();
     }
 
-    /**
-     * This is not time consume operation so we can do syncrhronization on this
-     * class object. Note, this method has package private visibility in order
-     * to increase performance.
-     */
-    synchronized void initReflectionData() {
-        if (reflectionData == null) {
-            reflectionData = new ReflectionData();
-        }
-    }
-
-
     String getPackageName() {
-        if (reflectionData == null) {
-            initReflectionData();
-        }
-        return reflectionData.packageName;
+        return getReflectionData().packageName;
     }
 
     void setProtectionDomain(ProtectionDomain protectionDomain) {
@@ -763,7 +670,7 @@
         SecurityManager sc = System.getSecurityManager();
         if (sc != null) {
             sc.checkMemberAccess(this, accessType);
-            sc.checkPackageAccess(reflectionData.packageName);
+            sc.checkPackageAccess(getReflectionData().packageName);
         }
     }
 
@@ -780,11 +687,9 @@
 
     private Constructor<T> getDeclaredConstructorInternal(Class<?>[] argumentTypes)
         throws NoSuchMethodException {
-        if (reflectionData.declaredConstructors == null) {
-            reflectionData.initDeclaredConstructors();
-        }
-        for (int i = 0; i < reflectionData.declaredConstructors.length; i++) {
-            Constructor<T> c = reflectionData.declaredConstructors[i];
+        final Constructor<T>[] declaredConstructors = getReflectionData().getDeclaredConstructors();
+        for (int i = 0; i < declaredConstructors.length; i++) {
+            Constructor<T> c = declaredConstructors[i];
             if (isTypeMatches(argumentTypes, c.getParameterTypes())) {
                 return c;
             }
@@ -987,82 +892,116 @@
     }
 
     private final class ReflectionData {
-        
-        String name;
-        
-        int modifiers = -1;
-        
-        boolean isArray;
 
-        Constructor<T>[] declaredConstructors;
+        final String packageName;
+        final String name;
+        final boolean isPrimitive;
+        final boolean isArray;
 
-        Field[] declaredFields;
-
-        Method[] declaredMethods;
-
-        Constructor<T> defaultConstructor;
-        
-        String packageName;
-
-        Constructor<T>[] publicConstructors;
-
-        Field[] publicFields;
-
-        Method[] publicMethods;
+        /*
+         * Do no access the following fields directly from enclosing class;
+         * use the accessor methods
+         */
+        private volatile int _modifiers;
+        private volatile Constructor<T>[] _declaredConstructors;
+        private volatile Field[] _declaredFields;
+        private volatile Method[] _declaredMethods;
+        private volatile Constructor<T> _defaultConstructor;
+        private volatile Constructor<T>[] _publicConstructors;
+        private volatile Field[] _publicFields;
+        private volatile Method[] _publicMethods;
+        
+        private volatile boolean _serialPropsResolved;
+        private boolean _isExternalizable;
+        private boolean _isSerializable;
         
-        public ReflectionData() {
+        ReflectionData() {
             name = VMClassRegistry.getName(Class.this);
+            isPrimitive = VMClassRegistry.isPrimitive(Class.this);
             isArray = VMClassRegistry.isArray(Class.this);
             packageName = Class.getParentName(name);
+            _modifiers = -1;
+        }
+        
+        boolean isSerializable(){
+            resolveSerialProps();
+            return _isSerializable;
         }
         
-        public void initDeclaredConstructors() {
-            if (declaredConstructors == null) {
-                declaredConstructors = VMClassRegistry
-                    .getDeclaredConstructors(Class.this);
+        boolean isExternalizable() {
+            resolveSerialProps();
+            return _isExternalizable;
+        }
+        
+        private void resolveSerialProps() {
+            if (!_serialPropsResolved){
+                _isExternalizable = VMClassRegistry.isAssignableFrom(Externalizable.class, Class.this);
+                _isSerializable = VMClassRegistry.isAssignableFrom(Serializable.class, Class.this);
+                _serialPropsResolved = true;
+            }
+        }
+        
+        int getModifiers() {
+            final int localCopy = _modifiers;
+            if (localCopy != -1){
+                return localCopy;
             }
+            return _modifiers = VMClassRegistry.getModifiers(Class.this); 
+        }
+        
+        Constructor<T>[] getDeclaredConstructors() {
+            final Constructor<T>[] localCopy = _declaredConstructors;
+            if (localCopy != null) {
+                return localCopy;
+            }
+            return _declaredConstructors = VMClassRegistry.getDeclaredConstructors(Class.this);
         }
 
-        public void initDeclaredFields() {
-            if (declaredFields == null) {
-                declaredFields = VMClassRegistry
+        Field[] getDeclaredFields() {
+            final Field[] localCopy = _declaredFields;
+            if (localCopy == null) {
+                return _declaredFields = VMClassRegistry
                     .getDeclaredFields(Class.this);
+            } else {
+                return localCopy;
             }
-        }
+       }
 
-        public void initDeclaredMethods() {
-            if (declaredMethods == null) {
-                declaredMethods = VMClassRegistry
-                    .getDeclaredMethods(Class.this);
+        Method[] getDeclaredMethods() {
+            final Method[] localCopy = _declaredMethods;
+            if (localCopy != null) {
+                return localCopy;
             }
+            return _declaredMethods = VMClassRegistry.getDeclaredMethods(Class.this);
         }
 
-        public void initDefaultConstructor()
-            throws NoSuchMethodException {
-            if (defaultConstructor == null) {
-                defaultConstructor = Class.this
-                    .getDeclaredConstructorInternal(null);
+        Constructor<T> getDefaultConstructor() throws NoSuchMethodException {
+            final Constructor<T> localCopy = _defaultConstructor;
+            if (localCopy != null) {
+                return localCopy;
             }
+            return _defaultConstructor = Class.this.getDeclaredConstructorInternal(null);
         }
 
-        @SuppressWarnings("unchecked")
-        public synchronized Constructor<T>[] getPublicConstructors() {
-            if (publicConstructors != null) {
-                return publicConstructors;
+        Constructor<T>[] getPublicConstructors() {
+            final Constructor<T>[] localCopy = _publicConstructors;
+            if (localCopy != null) {
+                return localCopy;
             }
-            if (declaredConstructors == null) {
-                initDeclaredConstructors();
-            }
-            ArrayList<Constructor<T>> constructors = 
-                new ArrayList<Constructor<T>>(declaredConstructors.length);
+
+            final Constructor<T>[] declaredConstructors = getDeclaredConstructors();
+            ArrayList<Constructor<T>> constructors = new ArrayList<Constructor<T>>(
+                    declaredConstructors.length);
             for (int i = 0; i < declaredConstructors.length; i++) {
                 Constructor<T> c = declaredConstructors[i];
                 if (Modifier.isPublic(c.getModifiers())) {
                     constructors.add(c);
                 }
             }
-            return publicConstructors = constructors.toArray(
-                    new Constructor[constructors.size()]);
+            final int size = constructors.size();
+            @SuppressWarnings("unchecked")
+            final Constructor<T>[] tempArray = (Constructor<T>[]) new Constructor[size];
+            return _publicConstructors = constructors.toArray(tempArray);
         }
 
         /**
@@ -1070,22 +1009,20 @@
          * getField(name) method.
          */
         public synchronized Field[] getPublicFields() {
-            if (publicFields != null) {
-                return publicFields;
-            }
-            if (declaredFields == null) {
-                initDeclaredFields();
+            final Field[] localCopy = _publicFields;
+            if (localCopy != null) {
+                return localCopy;
             }
+            
+            final Field[] declaredFields = getDeclaredFields();
 
             // initialize public fields of the super class
             int size = declaredFields.length;
             Class<?> superClass = Class.this.getSuperclass();
             Field[] superFields = null;
             if (superClass != null) {
-                if (superClass.reflectionData == null) {
-                    superClass.initReflectionData();
-                }
-                superFields = superClass.reflectionData.getPublicFields();
+                final Class<?>.ReflectionData superClassRefData = superClass.getReflectionData();
+                superFields = superClassRefData.getPublicFields();
                 size += superFields.length;
             }
 
@@ -1100,10 +1037,8 @@
             // initialize and add fields of the super interfaces
             Class<?>[] interfaces = Class.this.getInterfaces();
             for (Class<?> ci : interfaces) {
-                if (ci.reflectionData == null) {
-                    ci.initReflectionData();
-                }
-                Field[] fi = ci.reflectionData.getPublicFields();
+                final Class<?>.ReflectionData ciRefData = ci.getReflectionData();
+                Field[] fi = ciRefData.getPublicFields();
                 for (Field f : fi) {
                     fields.add(f);
                 }
@@ -1118,28 +1053,24 @@
                 }
             }
             
-            // maybe publicFields better be set atomically 
-            // instead of access synchronization? 
-            return publicFields = fields.toArray(new Field[fields.size()]);
+            return _publicFields = fields.toArray(new Field[fields.size()]);
         }
 
         public synchronized Method[] getPublicMethods() {
-            if (publicMethods != null) {
-                return publicMethods;
-            }
-            if (declaredMethods == null) {
-                initDeclaredMethods();
+            final Method[] localCopy = _publicMethods;
+            if (localCopy != null) {
+                return localCopy;
             }
             
+            final Method[] declaredMethods = getDeclaredMethods();
+            
             // initialize public methods of the super class
             int size = declaredMethods.length;
             Class<?> superClass = Class.this.getSuperclass();
             Method[] superPublic = null;
             if (superClass != null) {
-                if (superClass.reflectionData == null) {
-                    superClass.initReflectionData();
-                }
-                superPublic = superClass.reflectionData.getPublicMethods(); 
+                final Class<?>.ReflectionData superClassRefData = superClass.getReflectionData();
+                superPublic = superClassRefData.getPublicMethods(); 
                 size += superPublic.length;
             }
 
@@ -1150,16 +1081,12 @@
                 intf = new Method[interfaces.length][];
                 for (int i = 0; i < interfaces.length; i++) {
                     Class<?> ci = interfaces[i];
-                    if (ci.reflectionData == null) {
-                        ci.initReflectionData();
-                    }
-                    intf[i] = ci.reflectionData.getPublicMethods();
+                    final Class<?>.ReflectionData ciRefData = ci.getReflectionData();
+                    intf[i] = ciRefData.getPublicMethods();
                     size += intf[i].length; 
                 }
             }
-            // maybe publicMethods better be set atomically 
-            // instead of access synchronization? 
-            return publicMethods = Reflection.mergePublicMethods(declaredMethods, superPublic, intf, size);
+            return _publicMethods = Reflection.mergePublicMethods(declaredMethods, superPublic, intf, size);
         }        
     }