src/share/classes/java/lang/Class.java

Print this page

        

@@ -2396,10 +2396,49 @@
         }
         return name;
     }
 
     /**
+     * Atomic operations support.
+     */
+    private static class Atomic {
+        // initialize Unsafe machinery here, since we need to call Class.class instance method
+        // and have to avoid calling it in the static initializer of the Class class...
+        private static final Unsafe unsafe = Unsafe.getUnsafe();
+        // offset of Class.reflectionData instance field
+        private static final long reflectionDataOffset;
+        // offset of Class.annotationType instance field
+        private static final long annotationTypeOffset;
+
+        static {
+            Field[] fields = Class.class.getDeclaredFields0(false); // bypass caches
+            reflectionDataOffset = objectFieldOffset(fields, "reflectionData");
+            annotationTypeOffset = objectFieldOffset(fields, "annotationType");
+        }
+
+        private static long objectFieldOffset(Field[] fields, String fieldName) {
+            Field field = searchFields(fields, fieldName);
+            if (field == null) {
+                throw new Error("No " + fieldName + " field found in java.lang.Class");
+            }
+            return unsafe.objectFieldOffset(field);
+        }
+
+        static <T> boolean casReflectionData(Class<?> clazz,
+                                             SoftReference<ReflectionData<T>> oldData,
+                                             SoftReference<ReflectionData<T>> newData) {
+            return unsafe.compareAndSwapObject(clazz, reflectionDataOffset, oldData, newData);
+        }
+
+        static <T> boolean casAnnotationType(Class<?> clazz,
+                                             AnnotationType oldType,
+                                             AnnotationType newType) {
+            return unsafe.compareAndSwapObject(clazz, annotationTypeOffset, oldType, newType);
+        }
+    }
+
+    /**
      * Reflection support.
      */
 
     // Caches for certain reflective results
     private static boolean useCaches = true;

@@ -2421,33 +2460,10 @@
         final int redefinedCount;
 
         ReflectionData(int redefinedCount) {
             this.redefinedCount = redefinedCount;
         }
-
-        // initialize Unsafe machinery here, since we need to call Class.class instance method
-        // and have to avoid calling it in the static initializer of the Class class...
-        private static final Unsafe unsafe;
-        // offset of Class.reflectionData instance field
-        private static final long reflectionDataOffset;
-
-        static {
-            unsafe = Unsafe.getUnsafe();
-            // bypass caches
-            Field reflectionDataField = searchFields(Class.class.getDeclaredFields0(false),
-                                                     "reflectionData");
-            if (reflectionDataField == null) {
-                throw new Error("No reflectionData field found in java.lang.Class");
-            }
-            reflectionDataOffset = unsafe.objectFieldOffset(reflectionDataField);
-        }
-
-        static <T> boolean compareAndSwap(Class<?> clazz,
-                                          SoftReference<ReflectionData<T>> oldData,
-                                          SoftReference<ReflectionData<T>> newData) {
-            return unsafe.compareAndSwapObject(clazz, reflectionDataOffset, oldData, newData);
-        }
     }
 
     private volatile transient SoftReference<ReflectionData<T>> reflectionData;
 
     // Incremented by the VM on each call to JVM TI RedefineClasses()

@@ -2475,11 +2491,11 @@
         if (!useCaches) return null;
 
         while (true) {
             ReflectionData<T> rd = new ReflectionData<>(classRedefinedCount);
             // try to CAS it...
-            if (ReflectionData.compareAndSwap(this, oldReflectionData, new SoftReference<>(rd))) {
+            if (Atomic.casReflectionData(this, oldReflectionData, new SoftReference<>(rd))) {
                 return rd;
             }
             // else retry
             oldReflectionData = this.reflectionData;
             classRedefinedCount = this.classRedefinedCount;

@@ -2518,11 +2534,11 @@
         }
         return (genericInfo != ClassRepository.NONE) ? genericInfo : null;
     }
 
     // Annotations handling
-    private native byte[] getRawAnnotations();
+    native byte[] getRawAnnotations();
     // Since 1.8
     native byte[] getRawTypeAnnotations();
     static byte[] getExecutableTypeAnnotationBytes(Executable ex) {
         return getReflectionFactory().getExecutableTypeAnnotationBytes(ex);
     }

@@ -3248,12 +3264,10 @@
      * {@code Class} objects that it is willing to accept.  A cast would
      * generate a compile-time warning, as the correctness of the cast
      * could not be checked at runtime (because generic types are implemented
      * by erasure).
      *
-     * @param <U> the type to cast this class object to
-     * @param clazz the class of the type to cast this class object to
      * @return this {@code Class} object, cast to represent a subclass of
      *    the specified class object.
      * @throws ClassCastException if this {@code Class} object does not
      *    represent a subclass of the specified class (here "subclass" includes
      *    the class itself).

@@ -3378,14 +3392,15 @@
         }
     }
 
     // Annotation types cache their internal (AnnotationType) form
 
-    private AnnotationType annotationType;
+    @SuppressWarnings("UnusedDeclaration")
+    private volatile transient AnnotationType annotationType;
 
-    void setAnnotationType(AnnotationType type) {
-        annotationType = type;
+    boolean casAnnotationType(AnnotationType oldType, AnnotationType newType) {
+        return Atomic.casAnnotationType(this, oldType, newType);
     }
 
     AnnotationType getAnnotationType() {
         return annotationType;
     }

@@ -3405,11 +3420,10 @@
      * indicate an annotated superclass, the return value is null.
      *
      * If this Class represents either the Object class, an interface type, an
      * array type, a primitive type, or void, the return value is null.
      *
-     * @return an object representing the superclass
      * @since 1.8
      */
     public AnnotatedType getAnnotatedSuperclass() {
          return TypeAnnotationParser.buildAnnotatedSuperclass(getRawTypeAnnotations(), getConstantPool(), this);
 }

@@ -3437,11 +3451,10 @@
      * array of length 0.
      *
      * If this Class represents either the Object class, an array type, a
      * primitive type, or void, the return value is an array of length 0.
      *
-     * @return an array representing the superinterfaces
      * @since 1.8
      */
     public AnnotatedType[] getAnnotatedInterfaces() {
          return TypeAnnotationParser.buildAnnotatedInterfaces(getRawTypeAnnotations(), getConstantPool(), this);
     }