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);
}