src/share/classes/java/lang/Class.java
Index
Unified diffs
Context diffs
Sdiffs
Wdiffs
Patch
New
Old
Previous File
Next File
*** old/src/share/classes/java/lang/Class.java Sun Jan 6 17:36:18 2013
--- new/src/share/classes/java/lang/Class.java Sun Jan 6 17:36:16 2013
*** 1,7 ****
--- 1,7 ----
/*
! * Copyright (c) 1994, 2012, Oracle and/or its affiliates. All rights reserved.
! * Copyright (c) 1994, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
*** 2212,2256 ****
--- 2212,2306 ----
* Reflection support.
*/
// Caches for certain reflective results
private static boolean useCaches = true;
private volatile transient SoftReference<Field[]> declaredFields;
private volatile transient SoftReference<Field[]> publicFields;
private volatile transient SoftReference<Method[]> declaredMethods;
! private volatile transient SoftReference<Method[]> publicMethods;
! private volatile transient SoftReference<Constructor<T>[]> declaredConstructors;
! private volatile transient SoftReference<Constructor<T>[]> publicConstructors;
+
+ // reflection data that might get invalidated when JVM TI RedefineClasses() is called
+ static class ReflectionData<T> {
! volatile Field[] declaredFields;
! volatile Field[] publicFields;
! volatile Method[] declaredMethods;
+ volatile Method[] publicMethods;
+ volatile Constructor<T>[] declaredConstructors;
+ volatile Constructor<T>[] publicConstructors;
// Intermediate results for getFields and getMethods
! private volatile transient SoftReference<Field[]> declaredPublicFields;
! private volatile transient SoftReference<Method[]> declaredPublicMethods;
! volatile Field[] declaredPublicFields;
! volatile Method[] declaredPublicMethods;
+ // Value of classRedefinedCount when we created this ReflectionData instance
+ 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()
// that redefines this class or a superclass.
private volatile transient int classRedefinedCount = 0;
// Value of classRedefinedCount when we last cleared the cached values
// that are sensitive to class redefinition.
! private volatile transient int lastRedefinedCount = 0;
+ // Lazily create and cache ReflectionData
+ private ReflectionData<T> reflectionData() {
! SoftReference<ReflectionData<T>> reflectionData = this.reflectionData;
+ int classRedefinedCount = this.classRedefinedCount;
+ ReflectionData<T> rd;
+ if (useCaches &&
+ reflectionData != null &&
+ (rd = reflectionData.get()) != null &&
+ rd.redefinedCount == classRedefinedCount) {
+ return rd;
+ }
+ // else no SoftReference or cleared SoftReference or stale ReflectionData
+ // -> create and replace new instance
+ return newReflectionData(reflectionData, classRedefinedCount);
+ }
// Clears cached values that might possibly have been obsoleted by
// a class redefinition.
private void clearCachesOnClassRedefinition() {
if (lastRedefinedCount != classRedefinedCount) {
declaredFields = publicFields = declaredPublicFields = null;
declaredMethods = publicMethods = declaredPublicMethods = null;
declaredConstructors = publicConstructors = null;
annotations = declaredAnnotations = null;
+ private ReflectionData<T> newReflectionData(SoftReference<ReflectionData<T>> oldReflectionData,
+ int classRedefinedCount) {
+ if (!useCaches) return null;
// Use of "volatile" (and synchronization by caller in the case
// of annotations) ensures that no thread sees the update to
! // lastRedefinedCount before seeing the caches cleared.
// We do not guard against brief windows during which multiple
// threads might redundantly work to fill an empty cache.
lastRedefinedCount = classRedefinedCount;
+ while (true) {
+ ReflectionData<T> rd = new ReflectionData<>(classRedefinedCount);
! // try to CAS it...
+ if (ReflectionData.compareAndSwap(this, oldReflectionData, new SoftReference<>(rd))) {
+ return rd;
}
+ // else retry
+ oldReflectionData = this.reflectionData;
+ classRedefinedCount = this.classRedefinedCount;
+ if (oldReflectionData != null &&
+ (rd = oldReflectionData.get()) != null &&
+ rd.redefinedCount == classRedefinedCount) {
+ return rd;
}
+ }
+ }
// Generic signature handling
private native String getGenericSignature();
// Generic info repository; lazily initialized
*** 2287,2317 ****
--- 2337,2359 ----
// Returns an array of "root" fields. These Field objects must NOT
// be propagated to the outside world, but must instead be copied
// via ReflectionFactory.copyField.
private Field[] privateGetDeclaredFields(boolean publicOnly) {
checkInitted();
- Field[] res = null;
if (useCaches) {
clearCachesOnClassRedefinition();
if (publicOnly) {
if (declaredPublicFields != null) {
res = declaredPublicFields.get();
}
} else {
if (declaredFields != null) {
res = declaredFields.get();
}
}
+ ReflectionData<T> rd = reflectionData();
+ if (rd != null) {
+ res = publicOnly ? rd.declaredPublicFields : rd.declaredFields;
if (res != null) return res;
}
// No cached value available; request value from VM
res = Reflection.filterFields(this, getDeclaredFields0(publicOnly));
! if (useCaches) {
! if (rd != null) {
if (publicOnly) {
! declaredPublicFields = new SoftReference<>(res);
! rd.declaredPublicFields = res;
} else {
! declaredFields = new SoftReference<>(res);
! rd.declaredFields = res;
}
}
return res;
}
*** 2318,2333 ****
--- 2360,2373 ----
// Returns an array of "root" fields. These Field objects must NOT
// be propagated to the outside world, but must instead be copied
// via ReflectionFactory.copyField.
private Field[] privateGetPublicFields(Set<Class<?>> traversedInterfaces) {
checkInitted();
- Field[] res = null;
if (useCaches) {
clearCachesOnClassRedefinition();
if (publicFields != null) {
res = publicFields.get();
}
+ ReflectionData<T> rd = reflectionData();
+ if (rd != null) {
+ res = rd.publicFields;
if (res != null) return res;
}
// No cached value available; compute value recursively.
// Traverse in correct order for getField().
*** 2356,2367 ****
--- 2396,2407 ----
}
}
res = new Field[fields.size()];
fields.toArray(res);
! if (useCaches) {
! publicFields = new SoftReference<>(res);
! if (rd != null) {
! rd.publicFields = res;
}
return res;
}
private static void addAll(Collection<Field> c, Field[] o) {
*** 2380,2401 ****
--- 2420,2433 ----
// Returns an array of "root" constructors. These Constructor
// objects must NOT be propagated to the outside world, but must
// instead be copied via ReflectionFactory.copyConstructor.
private Constructor<T>[] privateGetDeclaredConstructors(boolean publicOnly) {
checkInitted();
- Constructor<T>[] res = null;
if (useCaches) {
clearCachesOnClassRedefinition();
if (publicOnly) {
if (publicConstructors != null) {
res = publicConstructors.get();
}
} else {
if (declaredConstructors != null) {
res = declaredConstructors.get();
}
}
+ ReflectionData<T> rd = reflectionData();
+ if (rd != null) {
+ res = publicOnly ? rd.publicConstructors : rd.declaredConstructors;
if (res != null) return res;
}
// No cached value available; request value from VM
if (isInterface()) {
@SuppressWarnings("unchecked")
*** 2402,2416 ****
--- 2434,2448 ----
Constructor<T>[] temporaryRes = (Constructor<T>[]) new Constructor<?>[0];
res = temporaryRes;
} else {
res = getDeclaredConstructors0(publicOnly);
}
! if (useCaches) {
! if (rd != null) {
if (publicOnly) {
! publicConstructors = new SoftReference<>(res);
! rd.publicConstructors = res;
} else {
! declaredConstructors = new SoftReference<>(res);
! rd.declaredConstructors = res;
}
}
return res;
}
*** 2423,2453 ****
--- 2455,2477 ----
// Returns an array of "root" methods. These Method objects must NOT
// be propagated to the outside world, but must instead be copied
// via ReflectionFactory.copyMethod.
private Method[] privateGetDeclaredMethods(boolean publicOnly) {
checkInitted();
- Method[] res = null;
if (useCaches) {
clearCachesOnClassRedefinition();
if (publicOnly) {
if (declaredPublicMethods != null) {
res = declaredPublicMethods.get();
}
} else {
if (declaredMethods != null) {
res = declaredMethods.get();
}
}
+ ReflectionData<T> rd = reflectionData();
+ if (rd != null) {
+ res = publicOnly ? rd.declaredPublicMethods : rd.declaredMethods;
if (res != null) return res;
}
// No cached value available; request value from VM
res = Reflection.filterMethods(this, getDeclaredMethods0(publicOnly));
! if (useCaches) {
! if (rd != null) {
if (publicOnly) {
! declaredPublicMethods = new SoftReference<>(res);
! rd.declaredPublicMethods = res;
} else {
! declaredMethods = new SoftReference<>(res);
! rd.declaredMethods = res;
}
}
return res;
}
*** 2545,2560 ****
--- 2569,2582 ----
// Returns an array of "root" methods. These Method objects must NOT
// be propagated to the outside world, but must instead be copied
// via ReflectionFactory.copyMethod.
private Method[] privateGetPublicMethods() {
checkInitted();
- Method[] res = null;
if (useCaches) {
clearCachesOnClassRedefinition();
if (publicMethods != null) {
res = publicMethods.get();
}
+ ReflectionData<T> rd = reflectionData();
+ if (rd != null) {
+ res = rd.publicMethods;
if (res != null) return res;
}
// No cached value available; compute value recursively.
// Start by fetching public declared methods
*** 2598,2619 ****
--- 2620,2641 ----
inheritedMethods.removeByNameAndSignature(m);
}
methods.addAllIfNotPresent(inheritedMethods);
methods.compactAndTrim();
res = methods.getArray();
! if (useCaches) {
! publicMethods = new SoftReference<>(res);
! if (rd != null) {
! rd.publicMethods = res;
}
return res;
}
//
// Helpers for fetchers of one field, method, or constructor
//
! private static Field searchFields(Field[] fields, String name) {
String internedName = name.intern();
for (int i = 0; i < fields.length; i++) {
if (fields[i].getName() == internedName) {
return getReflectionFactory().copyField(fields[i]);
}
*** 2627,2637 ****
--- 2649,2659 ----
// privateGetPublicFields(). It fetches only the declared
// public fields for each class, however, to reduce the number
// of Field objects which have to be created for the common
// case where the field being requested is declared in the
// class which is being queried.
- Field res = null;
// Search declared public fields
if ((res = searchFields(privateGetDeclaredFields(true), name)) != null) {
return res;
}
// Direct superinterfaces, recursively
*** 2679,2689 ****
--- 2701,2711 ----
// privateGetPublicMethods(). It fetches only the declared
// public methods for each class, however, to reduce the
// number of Method objects which have to be created for the
// common case where the method being requested is declared in
// the class which is being queried.
- Method res = null;
// Search declared public methods
if ((res = searchMethods(privateGetDeclaredMethods(true),
name,
parameterTypes)) != null) {
return res;
*** 3123,3135 ****
--- 3145,3168 ----
}
// Annotations cache
private transient Map<Class<? extends Annotation>, Annotation> annotations;
private transient Map<Class<? extends Annotation>, Annotation> declaredAnnotations;
+ // Value of classRedefinedCount when we last cleared the cached annotations and declaredAnnotations fields
+ private transient int lastAnnotationsRedefinedCount = 0;
+ // Clears cached values that might possibly have been obsoleted by
+ // a class redefinition.
+ private void clearAnnotationCachesOnClassRedefinition() {
+ if (lastAnnotationsRedefinedCount != classRedefinedCount) {
+ annotations = declaredAnnotations = null;
+ lastAnnotationsRedefinedCount = classRedefinedCount;
+ }
+ }
+
private synchronized void initAnnotationsIfNecessary() {
! clearCachesOnClassRedefinition();
! clearAnnotationCachesOnClassRedefinition();
if (annotations != null)
return;
declaredAnnotations = AnnotationParser.parseAnnotations(
getRawAnnotations(), getConstantPool(), this);
Class<?> superClass = getSuperclass();
src/share/classes/java/lang/Class.java
Index
Unified diffs
Context diffs
Sdiffs
Wdiffs
Patch
New
Old
Previous File
Next File