src/share/classes/java/lang/Class.java
Index Unified diffs Context diffs Sdiffs Wdiffs Patch New Old Previous File Next File jdk Cdiff src/share/classes/java/lang/Class.java

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

Print this page

        

*** 1,7 **** /* ! * Copyright (c) 1994, 2012, 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 --- 1,7 ---- /* ! * 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 **** * 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; // Intermediate results for getFields and getMethods ! private volatile transient SoftReference<Field[]> declaredPublicFields; ! private volatile transient SoftReference<Method[]> declaredPublicMethods; // 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; ! // 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; ! // 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; } } // Generic signature handling private native String getGenericSignature(); // Generic info repository; lazily initialized --- 2212,2306 ---- * Reflection support. */ // Caches for certain reflective results private static boolean useCaches = true; ! ! // 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 ! 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; ! // 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); ! } ! private ReflectionData<T> newReflectionData(SoftReference<ReflectionData<T>> oldReflectionData, ! int classRedefinedCount) { ! if (!useCaches) return null; ! 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 **** // 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(); ! } ! } if (res != null) return res; } // No cached value available; request value from VM res = Reflection.filterFields(this, getDeclaredFields0(publicOnly)); ! if (useCaches) { if (publicOnly) { ! declaredPublicFields = new SoftReference<>(res); } else { ! declaredFields = new SoftReference<>(res); } } return res; } --- 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; ! 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 (rd != null) { if (publicOnly) { ! rd.declaredPublicFields = res; } else { ! rd.declaredFields = res; } } return res; }
*** 2318,2333 **** // 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(); ! } if (res != null) return res; } // No cached value available; compute value recursively. // Traverse in correct order for getField(). --- 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; ! 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 **** } } res = new Field[fields.size()]; fields.toArray(res); ! if (useCaches) { ! publicFields = new SoftReference<>(res); } return res; } private static void addAll(Collection<Field> c, Field[] o) { --- 2396,2407 ---- } } res = new Field[fields.size()]; fields.toArray(res); ! if (rd != null) { ! rd.publicFields = res; } return res; } private static void addAll(Collection<Field> c, Field[] o) {
*** 2380,2401 **** // 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(); ! } ! } if (res != null) return res; } // No cached value available; request value from VM if (isInterface()) { @SuppressWarnings("unchecked") --- 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; ! 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 **** Constructor<T>[] temporaryRes = (Constructor<T>[]) new Constructor<?>[0]; res = temporaryRes; } else { res = getDeclaredConstructors0(publicOnly); } ! if (useCaches) { if (publicOnly) { ! publicConstructors = new SoftReference<>(res); } else { ! declaredConstructors = new SoftReference<>(res); } } return res; } --- 2434,2448 ---- Constructor<T>[] temporaryRes = (Constructor<T>[]) new Constructor<?>[0]; res = temporaryRes; } else { res = getDeclaredConstructors0(publicOnly); } ! if (rd != null) { if (publicOnly) { ! rd.publicConstructors = res; } else { ! rd.declaredConstructors = res; } } return res; }
*** 2423,2453 **** // 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(); ! } ! } if (res != null) return res; } // No cached value available; request value from VM res = Reflection.filterMethods(this, getDeclaredMethods0(publicOnly)); ! if (useCaches) { if (publicOnly) { ! declaredPublicMethods = new SoftReference<>(res); } else { ! declaredMethods = new SoftReference<>(res); } } return res; } --- 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; ! 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 (rd != null) { if (publicOnly) { ! rd.declaredPublicMethods = res; } else { ! rd.declaredMethods = res; } } return res; }
*** 2545,2560 **** // 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(); ! } if (res != null) return res; } // No cached value available; compute value recursively. // Start by fetching public declared methods --- 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; ! 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 **** inheritedMethods.removeByNameAndSignature(m); } methods.addAllIfNotPresent(inheritedMethods); methods.compactAndTrim(); res = methods.getArray(); ! if (useCaches) { ! publicMethods = new SoftReference<>(res); } return res; } // // Helpers for fetchers of one field, method, or constructor // ! private 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]); } --- 2620,2641 ---- inheritedMethods.removeByNameAndSignature(m); } methods.addAllIfNotPresent(inheritedMethods); methods.compactAndTrim(); res = methods.getArray(); ! 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 **** // 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 --- 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; // Search declared public fields if ((res = searchFields(privateGetDeclaredFields(true), name)) != null) { return res; } // Direct superinterfaces, recursively
*** 2679,2689 **** // 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; --- 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; // Search declared public methods if ((res = searchMethods(privateGetDeclaredMethods(true), name, parameterTypes)) != null) { return res;
*** 3123,3135 **** } // Annotations cache private transient Map<Class<? extends Annotation>, Annotation> annotations; private transient Map<Class<? extends Annotation>, Annotation> declaredAnnotations; private synchronized void initAnnotationsIfNecessary() { ! clearCachesOnClassRedefinition(); if (annotations != null) return; declaredAnnotations = AnnotationParser.parseAnnotations( getRawAnnotations(), getConstantPool(), this); Class<?> superClass = getSuperclass(); --- 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() { ! 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