changeset 3153:c380668f35d0

Merge
author Andrew John Hughes <gnu.andrew@redhat.com>
date Wed, 08 Oct 2014 17:18:58 +0100
parents f2308ef26cf8 (current diff) 251d55dd9268 (diff)
children a17dc173fdc5
files ChangeLog Makefile.am
diffstat 4 files changed, 1980 insertions(+), 4 deletions(-) [+]
line wrap: on
line diff
--- a/ChangeLog	Wed Jul 30 16:17:30 2014 +0100
+++ b/ChangeLog	Wed Oct 08 17:18:58 2014 +0100
@@ -1,3 +1,23 @@
+2014-10-02  Andrew John Hughes  <gnu.andrew@redhat.com>
+
+	* Makefile.am:
+	(ICEDTEA_PATCHES): Add new patch.
+	* NEWS: Updated.
+	* patches/openjdk/7122142-annotation_race_condition.patch:
+	Backport fix for annotation race condition.
+
+2014-07-30  Andrew John Hughes  <gnu.andrew@redhat.com>
+
+	PR1886: IcedTea does not checksum supplied tarballs
+	* Makefile.am:
+	(download-openjdk): Check all tarballs,
+	rather than just those downloaded by $(WGET).
+
+2014-07-14  Omair Majid  <omajid@redhat.com>
+
+	* Makefile.am:
+	(OPENJDK_SHA256SUM): Update checksum for new tarball.
+
 2014-07-30  Andrew John Hughes  <gnu.andrew@redhat.com>
 
 	* patches/openjdk/8010213-set_socketoptions_windows.patch:
--- a/Makefile.am	Wed Jul 30 16:17:30 2014 +0100
+++ b/Makefile.am	Wed Oct 08 17:18:58 2014 +0100
@@ -1,7 +1,7 @@
 # Dependencies
 
 OPENJDK_DATE = 15_jul_2014
-OPENJDK_SHA256SUM = 1a7404f38b3fa7cbb25d4273c0d94885912badd3343c5184c3b0947437501256
+OPENJDK_SHA256SUM = 9a5ad1b599953baac1b6b34189b9487ac5dcdb367aac5cc0aa5aa49700e73871
 OPENJDK_VERSION = b33
 OPENJDK_URL = https://java.net/downloads/openjdk6/
 
@@ -616,7 +616,8 @@
 	patches/openjdk/6611637-npe_in_glyphlayout.patch \
 	patches/openjdk/6727719-performance_of_textlayout_getbounds.patch \
 	patches/openjdk/6745225-memory_leak_in_attributed_string.patch \
-	patches/openjdk/oj639-handle_fonts_with_no_canon_flag_set.patch
+	patches/openjdk/oj639-handle_fonts_with_no_canon_flag_set.patch \
+	patches/openjdk/7122142-annotation_race_condition.patch
 
 if WITH_RHINO
 ICEDTEA_PATCHES += \
@@ -1120,7 +1121,7 @@
 else
 if USE_ALT_OPENJDK_SRC_ZIP
 	ln -sf $(ALT_OPENJDK_SRC_ZIP) $(OPENJDK_SRC_ZIP)
-else
+endif
 	if ! echo "$(OPENJDK_SHA256SUM)  $(OPENJDK_SRC_ZIP)" \
 	  | $(SHA256SUM) --check ; \
 	then \
@@ -1139,7 +1140,6 @@
 	fi
 endif
 endif
-endif
 	mkdir -p stamps
 	touch $@
 
--- a/NEWS	Wed Jul 30 16:17:30 2014 +0100
+++ b/NEWS	Wed Oct 08 17:18:58 2014 +0100
@@ -19,10 +19,13 @@
   - S6727719: Performance of TextLayout.getBounds()
   - S6745225: Memory leak while drawing Attributed String
   - S6904962: GlyphVector.getVisualBounds should not be affected by leading or trailing white space.
+  - S7122142: (ann) Race condition between isAnnotationPresent and getAnnotations
   - S7151089: PS NUMA: NUMA allocator should not attempt to free pages when using SHM large pages
   - S8013057: Detect mmap() commit failures in Linux and Solaris os::commit_memory() impls and call vm_exit_out_of_memory()
   - S8026887: Make issues due to failed large pages allocations easier to debug
   - OJ39: Handle fonts with the non-canonical processing flag set
+* Bug fixes
+  - PR1886: IcedTea does not checksum supplied tarballs
 
 New in release 1.13.4 (2014-07-15):
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/patches/openjdk/7122142-annotation_race_condition.patch	Wed Oct 08 17:18:58 2014 +0100
@@ -0,0 +1,1953 @@
+diff -r d1f592073a0e src/share/classes/java/lang/Class.java
+--- openjdk/jdk/src/share/classes/java/lang/Class.java	Fri Sep 12 22:39:32 2014 +0100
++++ openjdk/jdk/src/share/classes/java/lang/Class.java	Thu Oct 02 20:18:56 2014 +0100
+@@ -1,5 +1,5 @@
+ /*
+- * Copyright (c) 1994, 2012, Oracle and/or its affiliates. All rights reserved.
++ * Copyright (c) 1994, 2014, 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
+@@ -271,7 +271,7 @@
+     }
+ 
+     /** Called after security checks have been made. */
+-    private static native Class forName0(String name, boolean initialize,
++    private static native Class<?> forName0(String name, boolean initialize,
+                                             ClassLoader loader)
+         throws ClassNotFoundException;
+ 
+@@ -341,15 +341,15 @@
+                 );
+             }
+             try {
+-                Class[] empty = {};
++                Class<?>[] empty = {};
+                 final Constructor<T> c = getConstructor0(empty, Member.DECLARED);
+                 // Disable accessibility checks on the constructor
+                 // since we have to do the security check here anyway
+                 // (the stack depth is wrong for the Constructor's
+                 // security check to work)
+-                java.security.AccessController.doPrivileged
+-                    (new java.security.PrivilegedAction() {
+-                            public Object run() {
++                java.security.AccessController.doPrivileged(
++                    new java.security.PrivilegedAction<Void>() {
++                        public Void run() {
+                                 c.setAccessible(true);
+                                 return null;
+                             }
+@@ -379,7 +379,7 @@
+         }
+     }
+     private volatile transient Constructor<T> cachedConstructor;
+-    private volatile transient Class       newInstanceCallerCache;
++    private volatile transient Class<?>       newInstanceCallerCache;
+ 
+ 
+     /**
+@@ -637,7 +637,7 @@
+         if (getGenericSignature() != null)
+             return (TypeVariable<Class<T>>[])getGenericInfo().getTypeParameters();
+         else
+-            return (TypeVariable<Class<T>>[])new TypeVariable[0];
++            return (TypeVariable<Class<T>>[])new TypeVariable<?>[0];
+     }
+ 
+ 
+@@ -901,7 +901,7 @@
+ 
+             MethodRepository typeInfo = MethodRepository.make(enclosingInfo.getDescriptor(),
+                                                               getFactory());
+-            Class      returnType       = toClass(typeInfo.getReturnType());
++            Class<?>   returnType       = toClass(typeInfo.getReturnType());
+             Type []    parameterTypes   = typeInfo.getParameterTypes();
+             Class<?>[] parameterClasses = new Class<?>[parameterTypes.length];
+ 
+@@ -1005,12 +1005,12 @@
+ 
+     }
+ 
+-    private static Class toClass(Type o) {
++    private static Class<?> toClass(Type o) {
+         if (o instanceof GenericArrayType)
+             return Array.newInstance(toClass(((GenericArrayType)o).getGenericComponentType()),
+                                      0)
+                 .getClass();
+-        return (Class)o;
++        return (Class<?>)o;
+      }
+ 
+     /**
+@@ -1340,13 +1340,13 @@
+         // out anything other than public members and (2) public member access
+         // has already been ok'd by the SecurityManager.
+ 
+-        Class[] result = (Class[]) java.security.AccessController.doPrivileged
+-            (new java.security.PrivilegedAction() {
+-                public Object run() {
+-                    java.util.List<Class> list = new java.util.ArrayList();
+-                    Class currentClass = Class.this;
++        return java.security.AccessController.doPrivileged(
++            new java.security.PrivilegedAction<Class<?>[]>() {
++                public Class[] run() {
++                    List<Class<?>> list = new ArrayList<Class<?>>();
++                    Class<?> currentClass = Class.this;
+                     while (currentClass != null) {
+-                        Class[] members = currentClass.getDeclaredClasses();
++                        Class<?>[] members = currentClass.getDeclaredClasses();
+                         for (int i = 0; i < members.length; i++) {
+                             if (Modifier.isPublic(members[i].getModifiers())) {
+                                 list.add(members[i]);
+@@ -1354,12 +1354,9 @@
+                         }
+                         currentClass = currentClass.getSuperclass();
+                     }
+-                    Class[] empty = {};
+-                    return list.toArray(empty);
++                    return list.toArray(new Class[0]);
+                 }
+             });
+-
+-        return result;
+     }
+ 
+ 
+@@ -2283,7 +2280,7 @@
+             return name;
+         }
+         if (!name.startsWith("/")) {
+-            Class c = this;
++            Class<?> c = this;
+             while (c.isArray()) {
+                 c = c.getComponentType();
+             }
+@@ -2300,44 +2297,111 @@
+     }
+ 
+     /**
++     * 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;
+-    private volatile transient SoftReference declaredFields;
+-    private volatile transient SoftReference publicFields;
+-    private volatile transient SoftReference declaredMethods;
+-    private volatile transient SoftReference publicMethods;
+-    private volatile transient SoftReference declaredConstructors;
+-    private volatile transient SoftReference publicConstructors;
+-    // Intermediate results for getFields and getMethods
+-    private volatile transient SoftReference declaredPublicFields;
+-    private volatile transient SoftReference declaredPublicMethods;
++
++    // 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;
++        }
++    }
++
++    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<T>(classRedefinedCount);
++            // try to CAS it...
++            if (Atomic.casReflectionData(this, oldReflectionData,
++	      new SoftReference<ReflectionData<T>>(rd))) {
++                return rd;
++            }
++            // else retry
++            oldReflectionData = this.reflectionData;
++            classRedefinedCount = this.classRedefinedCount;
++            if (oldReflectionData != null &&
++                (rd = oldReflectionData.get()) != null &&
++                rd.redefinedCount == classRedefinedCount) {
++                return rd;
++            }
+         }
+     }
+ 
+@@ -2365,7 +2429,7 @@
+     }
+ 
+     // Annotations handling
+-    private native byte[] getRawAnnotations();
++    native byte[] getRawAnnotations();
+ 
+     native ConstantPool getConstantPool();
+ 
+@@ -2380,27 +2444,19 @@
+     // via ReflectionFactory.copyField.
+     private Field[] privateGetDeclaredFields(boolean publicOnly) {
+         checkInitted();
+-        Field[] res = null;
+-        if (useCaches) {
+-            clearCachesOnClassRedefinition();
+-            if (publicOnly) {
+-                if (declaredPublicFields != null) {
+-                    res = (Field[]) declaredPublicFields.get();
+-                }
+-            } else {
+-                if (declaredFields != null) {
+-                    res = (Field[]) declaredFields.get();
+-                }
+-            }
++        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 (useCaches) {
++        if (rd != null) {
+             if (publicOnly) {
+-                declaredPublicFields = new SoftReference(res);
++                rd.declaredPublicFields = res;
+             } else {
+-                declaredFields = new SoftReference(res);
++                rd.declaredFields = res;
+             }
+         }
+         return res;
+@@ -2409,22 +2465,20 @@
+     // 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 traversedInterfaces) {
++    private Field[] privateGetPublicFields(Set<Class<?>> traversedInterfaces) {
+         checkInitted();
+-        Field[] res = null;
+-        if (useCaches) {
+-            clearCachesOnClassRedefinition();
+-            if (publicFields != null) {
+-                res = (Field[]) publicFields.get();
+-            }
++        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().
+-        List fields = new ArrayList();
++        List<Field> fields = new ArrayList<Field>();
+         if (traversedInterfaces == null) {
+-            traversedInterfaces = new HashSet();
++            traversedInterfaces = new HashSet<Class<?>>();
+         }
+ 
+         // Local fields
+@@ -2432,9 +2486,7 @@
+         addAll(fields, tmp);
+ 
+         // Direct superinterfaces, recursively
+-        Class[] interfaces = getInterfaces();
+-        for (int i = 0; i < interfaces.length; i++) {
+-            Class c = interfaces[i];
++        for (Class<?> c : getInterfaces()) {
+             if (!traversedInterfaces.contains(c)) {
+                 traversedInterfaces.add(c);
+                 addAll(fields, c.privateGetPublicFields(traversedInterfaces));
+@@ -2443,7 +2495,7 @@
+ 
+         // Direct superclass, recursively
+         if (!isInterface()) {
+-            Class c = getSuperclass();
++            Class<?> c = getSuperclass();
+             if (c != null) {
+                 addAll(fields, c.privateGetPublicFields(traversedInterfaces));
+             }
+@@ -2451,13 +2503,13 @@
+ 
+         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 c, Field[] o) {
++    private static void addAll(Collection<Field> c, Field[] o) {
+         for (int i = 0; i < o.length; i++) {
+             c.add(o[i]);
+         }
+@@ -2473,20 +2525,12 @@
+     // 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[] privateGetDeclaredConstructors(boolean publicOnly) {
++    private Constructor<T>[] privateGetDeclaredConstructors(boolean publicOnly) {
+         checkInitted();
+-        Constructor[] res = null;
+-        if (useCaches) {
+-            clearCachesOnClassRedefinition();
+-            if (publicOnly) {
+-                if (publicConstructors != null) {
+-                    res = (Constructor[]) publicConstructors.get();
+-                }
+-            } else {
+-                if (declaredConstructors != null) {
+-                    res = (Constructor[]) declaredConstructors.get();
+-                }
+-            }
++        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
+@@ -2495,11 +2539,11 @@
+         } 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;
+@@ -2516,27 +2560,19 @@
+     // via ReflectionFactory.copyMethod.
+     private Method[] privateGetDeclaredMethods(boolean publicOnly) {
+         checkInitted();
+-        Method[] res = null;
+-        if (useCaches) {
+-            clearCachesOnClassRedefinition();
+-            if (publicOnly) {
+-                if (declaredPublicMethods != null) {
+-                    res = (Method[]) declaredPublicMethods.get();
+-                }
+-            } else {
+-                if (declaredMethods != null) {
+-                    res = (Method[]) declaredMethods.get();
+-                }
+-            }
++        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 (useCaches) {
++        if (rd != null) {
+             if (publicOnly) {
+-                declaredPublicMethods = new SoftReference(res);
++                rd.declaredPublicMethods = res;
+             } else {
+-                declaredMethods = new SoftReference(res);
++                rd.declaredMethods = res;
+             }
+         }
+         return res;
+@@ -2638,12 +2674,10 @@
+     // via ReflectionFactory.copyMethod.
+     private Method[] privateGetPublicMethods() {
+         checkInitted();
+-        Method[] res = null;
+-        if (useCaches) {
+-            clearCachesOnClassRedefinition();
+-            if (publicMethods != null) {
+-                res = (Method[]) publicMethods.get();
+-            }
++        Method[] res;
++        ReflectionData<T> rd = reflectionData();
++        if (rd != null) {
++            res = rd.publicMethods;
+             if (res != null) return res;
+         }
+ 
+@@ -2659,12 +2693,12 @@
+         // out concrete implementations inherited from superclasses at
+         // the end.
+         MethodArray inheritedMethods = new MethodArray();
+-        Class[] interfaces = getInterfaces();
++        Class<?>[] interfaces = getInterfaces();
+         for (int i = 0; i < interfaces.length; i++) {
+             inheritedMethods.addAll(interfaces[i].privateGetPublicMethods());
+         }
+         if (!isInterface()) {
+-            Class c = getSuperclass();
++            Class<?> c = getSuperclass();
+             if (c != null) {
+                 MethodArray supers = new MethodArray();
+                 supers.addAll(c.privateGetPublicMethods());
+@@ -2691,8 +2725,8 @@
+         methods.addAllIfNotPresent(inheritedMethods);
+         methods.compactAndTrim();
+         res = methods.getArray();
+-        if (useCaches) {
+-            publicMethods = new SoftReference(res);
++        if (rd != null) {
++            rd.publicMethods = res;
+         }
+         return res;
+     }
+@@ -2702,7 +2736,7 @@
+     // Helpers for fetchers of one field, method, or constructor
+     //
+ 
+-    private Field searchFields(Field[] fields, String name) {
++    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) {
+@@ -2720,22 +2754,22 @@
+         // 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;
++        Field res;
+         // Search declared public fields
+         if ((res = searchFields(privateGetDeclaredFields(true), name)) != null) {
+             return res;
+         }
+         // Direct superinterfaces, recursively
+-        Class[] interfaces = getInterfaces();
++        Class<?>[] interfaces = getInterfaces();
+         for (int i = 0; i < interfaces.length; i++) {
+-            Class c = interfaces[i];
++            Class<?> c = interfaces[i];
+             if ((res = c.getField0(name)) != null) {
+                 return res;
+             }
+         }
+         // Direct superclass, recursively
+         if (!isInterface()) {
+-            Class c = getSuperclass();
++            Class<?> c = getSuperclass();
+             if (c != null) {
+                 if ((res = c.getField0(name)) != null) {
+                     return res;
+@@ -2747,7 +2781,7 @@
+ 
+     private static Method searchMethods(Method[] methods,
+                                         String name,
+-                                        Class[] parameterTypes)
++                                        Class<?>[] parameterTypes)
+     {
+         Method res = null;
+         String internedName = name.intern();
+@@ -2764,7 +2798,7 @@
+     }
+ 
+ 
+-    private Method getMethod0(String name, Class[] parameterTypes) {
++    private Method getMethod0(String name, Class<?>[] parameterTypes) {
+         // Note: the intent is that the search algorithm this routine
+         // uses be equivalent to the ordering imposed by
+         // privateGetPublicMethods(). It fetches only the declared
+@@ -2772,7 +2806,7 @@
+         // 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;
++        Method res;
+         // Search declared public methods
+         if ((res = searchMethods(privateGetDeclaredMethods(true),
+                                  name,
+@@ -2781,7 +2815,7 @@
+         }
+         // Search superclass's methods
+         if (!isInterface()) {
+-            Class c = getSuperclass();
++            Class<? super T> c = getSuperclass();
+             if (c != null) {
+                 if ((res = c.getMethod0(name, parameterTypes)) != null) {
+                     return res;
+@@ -2789,9 +2823,9 @@
+             }
+         }
+         // Search superinterfaces' methods
+-        Class[] interfaces = getInterfaces();
++        Class<?>[] interfaces = getInterfaces();
+         for (int i = 0; i < interfaces.length; i++) {
+-            Class c = interfaces[i];
++            Class<?> c = interfaces[i];
+             if ((res = c.getMethod0(name, parameterTypes)) != null) {
+                 return res;
+             }
+@@ -2800,14 +2834,14 @@
+         return null;
+     }
+ 
+-    private Constructor<T> getConstructor0(Class[] parameterTypes,
++    private Constructor<T> getConstructor0(Class<?>[] parameterTypes,
+                                         int which) throws NoSuchMethodException
+     {
+-        Constructor[] constructors = privateGetDeclaredConstructors((which == Member.PUBLIC));
+-        for (int i = 0; i < constructors.length; i++) {
++        Constructor<T>[] constructors = privateGetDeclaredConstructors((which == Member.PUBLIC));
++        for (Constructor<T> constructor : constructors) {
+             if (arrayContentsEq(parameterTypes,
+-                                constructors[i].getParameterTypes())) {
+-                return getReflectionFactory().copyConstructor(constructors[i]);
++                                constructor.getParameterTypes())) {
++                return getReflectionFactory().copyConstructor(constructor);
+             }
+         }
+         throw new NoSuchMethodException(getName() + ".<init>" + argumentTypesToString(parameterTypes));
+@@ -2857,21 +2891,21 @@
+         return out;
+     }
+ 
+-    private static Constructor[] copyConstructors(Constructor[] arg) {
+-        Constructor[] out = new Constructor[arg.length];
++    private static <U> Constructor<U>[] copyConstructors(Constructor<U>[] arg) {
++        Constructor<U>[] out = arg.clone();
+         ReflectionFactory fact = getReflectionFactory();
+-        for (int i = 0; i < arg.length; i++) {
+-            out[i] = fact.copyConstructor(arg[i]);
++        for (int i = 0; i < out.length; i++) {
++            out[i] = fact.copyConstructor(out[i]);
+         }
+         return out;
+     }
+ 
+     private native Field[]       getDeclaredFields0(boolean publicOnly);
+     private native Method[]      getDeclaredMethods0(boolean publicOnly);
+-    private native Constructor[] getDeclaredConstructors0(boolean publicOnly);
+-    private native Class[]   getDeclaredClasses0();
++    private native Constructor<T>[] getDeclaredConstructors0(boolean publicOnly);
++    private native Class<?>[]   getDeclaredClasses0();
+ 
+-    private static String        argumentTypesToString(Class[] argTypes) {
++    private static String        argumentTypesToString(Class<?>[] argTypes) {
+         StringBuilder buf = new StringBuilder();
+         buf.append("(");
+         if (argTypes != null) {
+@@ -2879,7 +2913,7 @@
+                 if (i > 0) {
+                     buf.append(", ");
+                 }
+-                Class c = argTypes[i];
++                Class<?> c = argTypes[i];
+                 buf.append((c == null) ? "null" : c.getName());
+             }
+         }
+@@ -2952,7 +2986,7 @@
+     }
+ 
+     // Retrieves the desired assertion status of this class from the VM
+-    private static native boolean desiredAssertionStatus0(Class clazz);
++    private static native boolean desiredAssertionStatus0(Class<?> clazz);
+ 
+     /**
+      * Returns true if and only if this class was declared as an enum in the
+@@ -2973,7 +3007,7 @@
+     // Fetches the factory for reflective objects
+     private static ReflectionFactory getReflectionFactory() {
+         if (reflectionFactory == null) {
+-            reflectionFactory =  (ReflectionFactory)
++            reflectionFactory =
+                 java.security.AccessController.doPrivileged
+                     (new sun.reflect.ReflectionFactory.GetReflectionFactoryAction());
+         }
+@@ -3039,9 +3073,9 @@
+             if (!isEnum()) return null;
+             try {
+                 final Method values = getMethod("values");
+-                java.security.AccessController.doPrivileged
+-                    (new java.security.PrivilegedAction() {
+-                            public Object run() {
++                java.security.AccessController.doPrivileged(
++                    new java.security.PrivilegedAction<Void>() {
++                        public Void run() {
+                                 values.setAccessible(true);
+                                 return null;
+                             }
+@@ -3073,7 +3107,7 @@
+                     getName() + " is not an enum type");
+             Map<String, T> m = new HashMap<String, T>(2 * universe.length);
+             for (T constant : universe)
+-                m.put(((Enum)constant).name(), constant);
++                m.put(((Enum<?>)constant).name(), constant);
+             enumConstantDirectory = m;
+         }
+         return enumConstantDirectory;
+@@ -3173,11 +3207,22 @@
+     }
+ 
+     // Annotations cache
+-    private transient Map<Class, Annotation> annotations;
+-    private transient Map<Class, Annotation> declaredAnnotations;
++    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(
+@@ -3186,10 +3231,10 @@
+         if (superClass == null) {
+             annotations = declaredAnnotations;
+         } else {
+-            annotations = new HashMap<Class, Annotation>();
++            annotations = new HashMap<Class<? extends Annotation>, Annotation>();
+             superClass.initAnnotationsIfNecessary();
+-            for (Map.Entry<Class, Annotation> e : superClass.annotations.entrySet()) {
+-                Class annotationClass = e.getKey();
++            for (Map.Entry<Class<? extends Annotation>, Annotation> e : superClass.annotations.entrySet()) {
++                Class<? extends Annotation> annotationClass = e.getKey();
+                 if (AnnotationType.getInstance(annotationClass).isInherited())
+                     annotations.put(annotationClass, e.getValue());
+             }
+@@ -3199,10 +3244,11 @@
+ 
+     // 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() {
+diff -r d1f592073a0e src/share/classes/java/lang/System.java
+--- openjdk/jdk/src/share/classes/java/lang/System.java	Fri Sep 12 22:39:32 2014 +0100
++++ openjdk/jdk/src/share/classes/java/lang/System.java	Thu Oct 02 20:18:56 2014 +0100
+@@ -1,5 +1,5 @@
+ /*
+- * Copyright (c) 1994, 2007, Oracle and/or its affiliates. All rights reserved.
++ * Copyright (c) 1994, 2014, 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
+@@ -1146,12 +1146,15 @@
+             public sun.reflect.ConstantPool getConstantPool(Class klass) {
+                 return klass.getConstantPool();
+             }
+-            public void setAnnotationType(Class klass, AnnotationType type) {
+-                klass.setAnnotationType(type);
++            public boolean casAnnotationType(Class<?> klass, AnnotationType oldType, AnnotationType newType) {
++                return klass.casAnnotationType(oldType, newType);
+             }
+             public AnnotationType getAnnotationType(Class klass) {
+                 return klass.getAnnotationType();
+             }
++            public byte[] getRawClassAnnotations(Class<?> klass) {
++                return klass.getRawAnnotations();
++            }
+             public <E extends Enum<E>>
+                     E[] getEnumConstantsShared(Class<E> klass) {
+                 return klass.getEnumConstantsShared();
+diff -r d1f592073a0e src/share/classes/java/lang/reflect/Constructor.java
+--- openjdk/jdk/src/share/classes/java/lang/reflect/Constructor.java	Fri Sep 12 22:39:32 2014 +0100
++++ openjdk/jdk/src/share/classes/java/lang/reflect/Constructor.java	Thu Oct 02 20:18:56 2014 +0100
+@@ -65,8 +65,8 @@
+ 
+     private Class<T>            clazz;
+     private int                 slot;
+-    private Class[]             parameterTypes;
+-    private Class[]             exceptionTypes;
++    private Class<?>[]          parameterTypes;
++    private Class<?>[]          exceptionTypes;
+     private int                 modifiers;
+     // Generics and annotations support
+     private transient String    signature;
+@@ -118,8 +118,8 @@
+      * package via sun.reflect.LangReflectAccess.
+      */
+     Constructor(Class<T> declaringClass,
+-                Class[] parameterTypes,
+-                Class[] checkedExceptions,
++                Class<?>[] parameterTypes,
++                Class<?>[] checkedExceptions,
+                 int modifiers,
+                 int slot,
+                 String signature,
+@@ -366,14 +366,14 @@
+             }
+             sb.append(Field.getTypeName(getDeclaringClass()));
+             sb.append("(");
+-            Class[] params = parameterTypes; // avoid clone
++            Class<?>[] params = parameterTypes; // avoid clone
+             for (int j = 0; j < params.length; j++) {
+                 sb.append(Field.getTypeName(params[j]));
+                 if (j < (params.length - 1))
+                     sb.append(",");
+             }
+             sb.append(")");
+-            Class[] exceptions = exceptionTypes; // avoid clone
++            Class<?>[] exceptions = exceptionTypes; // avoid clone
+             if (exceptions.length > 0) {
+                 sb.append(" throws ");
+                 for (int k = 0; k < exceptions.length; k++) {
+@@ -454,7 +454,7 @@
+                 sb.append(" throws ");
+                 for (int k = 0; k < exceptions.length; k++) {
+                     sb.append((exceptions[k] instanceof Class)?
+-                              ((Class)exceptions[k]).getName():
++                              ((Class<?>)exceptions[k]).getName():
+                               exceptions[k].toString());
+                     if (k < (exceptions.length - 1))
+                         sb.append(",");
+@@ -630,9 +630,9 @@
+         return declaredAnnotations().values().toArray(EMPTY_ANNOTATION_ARRAY);
+     }
+ 
+-    private transient Map<Class, Annotation> declaredAnnotations;
++    private transient Map<Class<? extends Annotation>, Annotation> declaredAnnotations;
+ 
+-    private synchronized  Map<Class, Annotation> declaredAnnotations() {
++    private synchronized  Map<Class<? extends Annotation>, Annotation> declaredAnnotations() {
+         if (declaredAnnotations == null) {
+             declaredAnnotations = AnnotationParser.parseAnnotations(
+                 annotations, sun.misc.SharedSecrets.getJavaLangAccess().
+diff -r d1f592073a0e src/share/classes/java/lang/reflect/Field.java
+--- openjdk/jdk/src/share/classes/java/lang/reflect/Field.java	Fri Sep 12 22:39:32 2014 +0100
++++ openjdk/jdk/src/share/classes/java/lang/reflect/Field.java	Thu Oct 02 20:18:56 2014 +0100
+@@ -59,12 +59,12 @@
+ public final
+ class Field extends AccessibleObject implements Member {
+ 
+-    private Class               clazz;
++    private Class<?>            clazz;
+     private int                 slot;
+     // This is guaranteed to be interned by the VM in the 1.4
+     // reflection implementation
+     private String              name;
+-    private Class               type;
++    private Class<?>            type;
+     private int                 modifiers;
+     // Generics and annotations support
+     private transient String    signature;
+@@ -113,9 +113,9 @@
+      * instantiation of these objects in Java code from the java.lang
+      * package via sun.reflect.LangReflectAccess.
+      */
+-    Field(Class declaringClass,
++    Field(Class<?> declaringClass,
+           String name,
+-          Class type,
++          Class<?> type,
+           int modifiers,
+           int slot,
+           String signature,
+@@ -1090,10 +1090,10 @@
+     /*
+      * Utility routine to paper over array type names
+      */
+-    static String getTypeName(Class type) {
++    static String getTypeName(Class<?> type) {
+         if (type.isArray()) {
+             try {
+-                Class cl = type;
++                Class<?> cl = type;
+                 int dimensions = 0;
+                 while (cl.isArray()) {
+                     dimensions++;
+@@ -1130,9 +1130,9 @@
+         return declaredAnnotations().values().toArray(EMPTY_ANNOTATION_ARRAY);
+     }
+ 
+-    private transient Map<Class, Annotation> declaredAnnotations;
++    private transient Map<Class<? extends Annotation>, Annotation> declaredAnnotations;
+ 
+-    private synchronized  Map<Class, Annotation> declaredAnnotations() {
++    private synchronized  Map<Class<? extends Annotation>, Annotation> declaredAnnotations() {
+         if (declaredAnnotations == null) {
+             declaredAnnotations = AnnotationParser.parseAnnotations(
+                 annotations, sun.misc.SharedSecrets.getJavaLangAccess().
+diff -r d1f592073a0e src/share/classes/java/lang/reflect/Method.java
+--- openjdk/jdk/src/share/classes/java/lang/reflect/Method.java	Fri Sep 12 22:39:32 2014 +0100
++++ openjdk/jdk/src/share/classes/java/lang/reflect/Method.java	Thu Oct 02 20:18:56 2014 +0100
+@@ -62,14 +62,14 @@
+ public final
+     class Method extends AccessibleObject implements GenericDeclaration,
+                                                      Member {
+-    private Class               clazz;
++    private Class<?>            clazz;
+     private int                 slot;
+     // This is guaranteed to be interned by the VM in the 1.4
+     // reflection implementation
+     private String              name;
+-    private Class               returnType;
+-    private Class[]             parameterTypes;
+-    private Class[]             exceptionTypes;
++    private Class<?>            returnType;
++    private Class<?>[]          parameterTypes;
++    private Class<?>[]          exceptionTypes;
+     private int                 modifiers;
+     // Generics and annotations support
+     private transient String              signature;
+@@ -121,11 +121,11 @@
+      * instantiation of these objects in Java code from the java.lang
+      * package via sun.reflect.LangReflectAccess.
+      */
+-    Method(Class declaringClass,
++    Method(Class<?> declaringClass,
+            String name,
+-           Class[] parameterTypes,
+-           Class returnType,
+-           Class[] checkedExceptions,
++           Class<?>[] parameterTypes,
++           Class<?> returnType,
++           Class<?>[] checkedExceptions,
+            int modifiers,
+            int slot,
+            String signature,
+@@ -366,8 +366,8 @@
+                 if (!returnType.equals(other.getReturnType()))
+                     return false;
+                 /* Avoid unnecessary cloning */
+-                Class[] params1 = parameterTypes;
+-                Class[] params2 = other.parameterTypes;
++                Class<?>[] params1 = parameterTypes;
++                Class<?>[] params2 = other.parameterTypes;
+                 if (params1.length == params2.length) {
+                     for (int i = 0; i < params1.length; i++) {
+                         if (params1[i] != params2[i])
+@@ -428,7 +428,7 @@
+                     sb.append(",");
+             }
+             sb.append(")");
+-            Class[] exceptions = exceptionTypes; // avoid clone
++            Class<?>[] exceptions = exceptionTypes; // avoid clone
+             if (exceptions.length > 0) {
+                 sb.append(" throws ");
+                 for (int k = 0; k < exceptions.length; k++) {
+@@ -723,9 +723,9 @@
+         return declaredAnnotations().values().toArray(EMPTY_ANNOTATION_ARRAY);
+     }
+ 
+-    private transient Map<Class, Annotation> declaredAnnotations;
++    private transient Map<Class<? extends Annotation>, Annotation> declaredAnnotations;
+ 
+-    private synchronized  Map<Class, Annotation> declaredAnnotations() {
++    private synchronized  Map<Class<? extends Annotation>, Annotation> declaredAnnotations() {
+         if (declaredAnnotations == null) {
+             declaredAnnotations = AnnotationParser.parseAnnotations(
+                 annotations, sun.misc.SharedSecrets.getJavaLangAccess().
+@@ -752,7 +752,7 @@
+     public Object getDefaultValue() {
+         if  (annotationDefault == null)
+             return null;
+-        Class memberType = AnnotationType.invocationHandlerReturnType(
++        Class<?> memberType = AnnotationType.invocationHandlerReturnType(
+             getReturnType());
+         Object result = AnnotationParser.parseMemberValue(
+             memberType, ByteBuffer.wrap(annotationDefault),
+diff -r d1f592073a0e src/share/classes/sun/misc/JavaLangAccess.java
+--- openjdk/jdk/src/share/classes/sun/misc/JavaLangAccess.java	Fri Sep 12 22:39:32 2014 +0100
++++ openjdk/jdk/src/share/classes/sun/misc/JavaLangAccess.java	Thu Oct 02 20:18:56 2014 +0100
+@@ -1,5 +1,5 @@
+ /*
+- * Copyright (c) 2003, 2006, Oracle and/or its affiliates. All rights reserved.
++ * Copyright (c) 2003, 2014, 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
+@@ -35,10 +35,10 @@
+     ConstantPool getConstantPool(Class klass);
+ 
+     /**
+-     * Set the AnnotationType instance corresponding to this class.
++     * Compare-And-Swap the AnnotationType instance corresponding to this class.
+      * (This method only applies to annotation types.)
+      */
+-    void setAnnotationType(Class klass, AnnotationType annotationType);
++    boolean casAnnotationType(Class<?> klass, AnnotationType oldType, AnnotationType newType);
+ 
+     /**
+      * Get the AnnotationType instance corresponding to this class.
+@@ -47,6 +47,12 @@
+     AnnotationType getAnnotationType(Class klass);
+ 
+     /**
++     * Get the array of bytes that is the class-file representation
++     * of this Class' annotations.
++     */
++    byte[] getRawClassAnnotations(Class<?> klass);
++
++    /**
+      * Returns the elements of an enum class or null if the
+      * Class object does not represent an enum type;
+      * the result is uncloned, cached, and shared by all callers.
+diff -r d1f592073a0e src/share/classes/sun/reflect/ReflectionFactory.java
+--- openjdk/jdk/src/share/classes/sun/reflect/ReflectionFactory.java	Fri Sep 12 22:39:32 2014 +0100
++++ openjdk/jdk/src/share/classes/sun/reflect/ReflectionFactory.java	Thu Oct 02 20:18:56 2014 +0100
+@@ -84,8 +84,8 @@
+      * <code>AccessController.doPrivileged</code>.
+      */
+     public static final class GetReflectionFactoryAction
+-        implements PrivilegedAction {
+-        public Object run() {
++        implements PrivilegedAction<ReflectionFactory> {
++        public ReflectionFactory run() {
+             return getReflectionFactory();
+         }
+     }
+@@ -164,7 +164,7 @@
+     public ConstructorAccessor newConstructorAccessor(Constructor c) {
+         checkInitted();
+ 
+-        Class declaringClass = c.getDeclaringClass();
++        Class<?> declaringClass = c.getDeclaringClass();
+         if (Modifier.isAbstract(declaringClass.getModifiers())) {
+             return new InstantiationExceptionConstructorAccessorImpl(null);
+         }
+@@ -203,10 +203,10 @@
+     //
+ 
+     /** Creates a new java.lang.reflect.Field. Access checks as per
+-        java.lang.reflect.AccessibleObject are not overridden. */
+-    public Field newField(Class declaringClass,
++        java.lang.reflect.AccessibleObject are not overridden. */ 
++    public Field newField(Class<?> declaringClass,
+                           String name,
+-                          Class type,
++                          Class<?> type,
+                           int modifiers,
+                           int slot,
+                           String signature,
+@@ -223,11 +223,11 @@
+ 
+     /** Creates a new java.lang.reflect.Method. Access checks as per
+         java.lang.reflect.AccessibleObject are not overridden. */
+-    public Method newMethod(Class declaringClass,
++    public Method newMethod(Class<?> declaringClass,
+                             String name,
+-                            Class[] parameterTypes,
+-                            Class returnType,
+-                            Class[] checkedExceptions,
++                            Class<?>[] parameterTypes,
++                            Class<?> returnType,
++                            Class<?>[] checkedExceptions,
+                             int modifiers,
+                             int slot,
+                             String signature,
+@@ -250,9 +250,9 @@
+ 
+     /** Creates a new java.lang.reflect.Constructor. Access checks as
+         per java.lang.reflect.AccessibleObject are not overridden. */
+-    public Constructor newConstructor(Class declaringClass,
+-                                      Class[] parameterTypes,
+-                                      Class[] checkedExceptions,
++    public Constructor newConstructor(Class<?> declaringClass,
++                                      Class<?>[] parameterTypes,
++                                      Class<?>[] checkedExceptions,
+                                       int modifiers,
+                                       int slot,
+                                       String signature,
+@@ -310,7 +310,7 @@
+     /** Makes a copy of the passed constructor. The returned
+         constructor is a "child" of the passed one; see the comments
+         in Constructor.java for details. */
+-    public Constructor copyConstructor(Constructor arg) {
++    public <T> Constructor<T> copyConstructor(Constructor<T> arg) {
+         return langReflectAccess().copyConstructor(arg);
+     }
+ 
+@@ -321,7 +321,7 @@
+     //
+ 
+     public Constructor newConstructorForSerialization
+-        (Class classToInstantiate, Constructor constructorToCall)
++        (Class<?> classToInstantiate, Constructor constructorToCall)
+     {
+         // Fast path
+         if (constructorToCall.getDeclaringClass() == classToInstantiate) {
+@@ -366,8 +366,9 @@
+         run, before the system properties are set up. */
+     private static void checkInitted() {
+         if (initted) return;
+-        AccessController.doPrivileged(new PrivilegedAction() {
+-                public Object run() {
++        AccessController.doPrivileged(
++            new PrivilegedAction<Void>() {
++                public Void run() {
+                     // Tests to ensure the system properties table is fully
+                     // initialized. This is needed because reflection code is
+                     // called very early in the initialization process (before
+diff -r d1f592073a0e src/share/classes/sun/reflect/annotation/AnnotationInvocationHandler.java
+--- openjdk/jdk/src/share/classes/sun/reflect/annotation/AnnotationInvocationHandler.java	Fri Sep 12 22:39:32 2014 +0100
++++ openjdk/jdk/src/share/classes/sun/reflect/annotation/AnnotationInvocationHandler.java	Thu Oct 02 20:18:56 2014 +0100
+@@ -41,17 +41,17 @@
+  */
+ class AnnotationInvocationHandler implements InvocationHandler, Serializable {
+     private static final long serialVersionUID = 6182022883658399397L;
+-    private final Class type;
++    private final Class<? extends Annotation> type;
+     private final Map<String, Object> memberValues;
+ 
+-    AnnotationInvocationHandler(Class type, Map<String, Object> memberValues) {
++    AnnotationInvocationHandler(Class<? extends Annotation> type, Map<String, Object> memberValues) {
+         this.type = type;
+         this.memberValues = memberValues;
+     }
+ 
+     public Object invoke(Object proxy, Method method, Object[] args) {
+         String member = method.getName();
+-        Class[] paramTypes = method.getParameterTypes();
++        Class<?>[] paramTypes = method.getParameterTypes();
+ 
+         // Handle Object and Annotation methods
+         if (member.equals("equals") && paramTypes.length == 1 &&
+@@ -85,7 +85,7 @@
+      * if Cloneable had a public clone method.
+      */
+     private Object cloneArray(Object array) {
+-        Class type = array.getClass();
++        Class<?> type = array.getClass();
+ 
+         if (type == byte[].class) {
+             byte[] byteArray = (byte[])array;
+@@ -152,7 +152,7 @@
+      * Translates a member value (in "dynamic proxy return form") into a string
+      */
+     private static String memberValueToString(Object value) {
+-        Class type = value.getClass();
++        Class<?> type = value.getClass();
+         if (!type.isArray())    // primitive, string, class, enum const,
+                                 // or annotation
+             return value.toString();
+@@ -230,7 +230,7 @@
+      * two members are identical object references.
+      */
+     private static boolean memberValueEquals(Object v1, Object v2) {
+-        Class type = v1.getClass();
++        Class<?> type = v1.getClass();
+ 
+         // Check for primitive, string, class, enum const, annotation,
+         // or ExceptionProxy
+@@ -302,7 +302,7 @@
+      * Computes hashCode of a member value (in "dynamic proxy return form")
+      */
+     private static int memberValueHashCode(Object value) {
+-        Class type = value.getClass();
++        Class<?> type = value.getClass();
+         if (!type.isArray())    // primitive, string, class, enum const,
+                                 // or annotation
+             return value.hashCode();
+@@ -341,14 +341,14 @@
+             throw new java.io.InvalidObjectException("Non-annotation type in annotation serial stream");
+         }
+ 
+-        Map<String, Class> memberTypes = annotationType.memberTypes();
++        Map<String, Class<?>> memberTypes = annotationType.memberTypes();
+ 
+ 
+         // If there are annotation members without values, that
+         // situation is handled by the invoke method.
+         for (Map.Entry<String, Object> memberValue : memberValues.entrySet()) {
+             String name = memberValue.getKey();
+-            Class memberType = memberTypes.get(name);
++            Class<?> memberType = memberTypes.get(name);
+             if (memberType != null) {  // i.e. member still exists
+                 Object value = memberValue.getValue();
+                 if (!(memberType.isInstance(value) ||
+diff -r d1f592073a0e src/share/classes/sun/reflect/annotation/AnnotationParser.java
+--- openjdk/jdk/src/share/classes/sun/reflect/annotation/AnnotationParser.java	Fri Sep 12 22:39:32 2014 +0100
++++ openjdk/jdk/src/share/classes/sun/reflect/annotation/AnnotationParser.java	Thu Oct 02 20:18:56 2014 +0100
+@@ -1,5 +1,5 @@
+ /*
+- * Copyright (c) 2003, 2005, Oracle and/or its affiliates. All rights reserved.
++ * Copyright (c) 2003, 2014, 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
+@@ -59,15 +59,15 @@
+      * @throws AnnotationFormatError if an annotation is found to be
+      *         malformed.
+      */
+-    public static Map<Class, Annotation> parseAnnotations(
++    public static Map<Class<? extends Annotation>, Annotation> parseAnnotations(
+                 byte[] rawAnnotations,
+                 ConstantPool constPool,
+-                Class container) {
++                Class<?> container) {
+         if (rawAnnotations == null)
+             return Collections.emptyMap();
+ 
+         try {
+-            return parseAnnotations2(rawAnnotations, constPool, container);
++            return parseAnnotations2(rawAnnotations, constPool, container, null);
+         } catch(BufferUnderflowException e) {
+             throw new AnnotationFormatError("Unexpected end of annotations.");
+         } catch(IllegalArgumentException e) {
+@@ -76,24 +76,53 @@
+         }
+     }
+ 
+-    private static Map<Class, Annotation> parseAnnotations2(
++    /**
++     * Like {@link #parseAnnotations(byte[], sun.reflect.ConstantPool, Class)}
++     * with an additional parameter {@code selectAnnotationClasses} which selects the
++     * annotation types to parse (other than selected are quickly skipped).<p>
++     * This method is only used to parse select meta annotations in the construction
++     * phase of {@link AnnotationType} instances to prevent infinite recursion.
++     *
++     * @param selectAnnotationClasses an array of annotation types to select when parsing
++     */
++    static Map<Class<? extends Annotation>, Annotation> parseSelectAnnotations(
+                 byte[] rawAnnotations,
+                 ConstantPool constPool,
+-                Class container) {
+-        Map<Class, Annotation> result = new LinkedHashMap<Class, Annotation>();
++                Class<?> container,
++                Class<? extends Annotation> ... selectAnnotationClasses) {
++        if (rawAnnotations == null)
++            return Collections.emptyMap();
++
++        try {
++            return parseAnnotations2(rawAnnotations, constPool, container, selectAnnotationClasses);
++        } catch(BufferUnderflowException e) {
++            throw new AnnotationFormatError("Unexpected end of annotations.");
++        } catch(IllegalArgumentException e) {
++            // Type mismatch in constant pool
++            throw new AnnotationFormatError(e);
++        }
++    }
++
++    private static Map<Class<? extends Annotation>, Annotation> parseAnnotations2(
++                byte[] rawAnnotations,
++                ConstantPool constPool,
++                Class<?> container,
++                Class<? extends Annotation>[] selectAnnotationClasses) {
++        Map<Class<? extends Annotation>, Annotation> result =
++            new LinkedHashMap<Class<? extends Annotation>, Annotation>();
+         ByteBuffer buf = ByteBuffer.wrap(rawAnnotations);
+         int numAnnotations = buf.getShort() & 0xFFFF;
+         for (int i = 0; i < numAnnotations; i++) {
+-            Annotation a = parseAnnotation(buf, constPool, container, false);
++            Annotation a = parseAnnotation2(buf, constPool, container, false, selectAnnotationClasses);
+             if (a != null) {
+-                Class klass = a.annotationType();
+-                AnnotationType type = AnnotationType.getInstance(klass);
+-                if (type.retention() == RetentionPolicy.RUNTIME)
+-                    if (result.put(klass, a) != null)
++                Class<? extends Annotation> klass = a.annotationType();
++                if (AnnotationType.getInstance(klass).retention() == RetentionPolicy.RUNTIME &&
++                    result.put(klass, a) != null) {
+                         throw new AnnotationFormatError(
+                             "Duplicate annotation for class: "+klass+": " + a);
+             }
+         }
++        }
+         return result;
+     }
+ 
+@@ -123,7 +152,7 @@
+     public static Annotation[][] parseParameterAnnotations(
+                     byte[] rawAnnotations,
+                     ConstantPool constPool,
+-                    Class container) {
++                    Class<?> container) {
+         try {
+             return parseParameterAnnotations2(rawAnnotations, constPool, container);
+         } catch(BufferUnderflowException e) {
+@@ -138,7 +167,7 @@
+     private static Annotation[][] parseParameterAnnotations2(
+                     byte[] rawAnnotations,
+                     ConstantPool constPool,
+-                    Class container) {
++                    Class<?> container) {
+         ByteBuffer buf = ByteBuffer.wrap(rawAnnotations);
+         int numParameters = buf.get() & 0xFF;
+         Annotation[][] result = new Annotation[numParameters][];
+@@ -188,15 +217,24 @@
+      */
+     private static Annotation parseAnnotation(ByteBuffer buf,
+                                               ConstantPool constPool,
+-                                              Class container,
++                                              Class<?> container,
+                                               boolean exceptionOnMissingAnnotationClass) {
++       return parseAnnotation2(buf, constPool, container, exceptionOnMissingAnnotationClass, null);
++    }
++
++    @SuppressWarnings("unchecked")
++    private static Annotation parseAnnotation2(ByteBuffer buf,
++                                              ConstantPool constPool,
++                                              Class<?> container,
++                                              boolean exceptionOnMissingAnnotationClass,
++                                              Class<? extends Annotation>[] selectAnnotationClasses) {
+         int typeIndex = buf.getShort() & 0xFFFF;
+-        Class annotationClass = null;
++        Class<? extends Annotation> annotationClass = null;
+         String sig = "[unknown]";
+         try {
+             try {
+                 sig = constPool.getUTF8At(typeIndex);
+-                annotationClass = parseSig(sig, container);
++                annotationClass = (Class<? extends Annotation>)parseSig(sig, container);
+             } catch (IllegalArgumentException ex) {
+                 // support obsolete early jsr175 format class files
+                 annotationClass = constPool.getClassAt(typeIndex);
+@@ -215,6 +253,10 @@
+             skipAnnotation(buf, false);
+             return null;
+         }
++        if (selectAnnotationClasses != null && !contains(selectAnnotationClasses, annotationClass)) {
++            skipAnnotation(buf, false);
++            return null;
++        }
+         AnnotationType type = null;
+         try {
+             type = AnnotationType.getInstance(annotationClass);
+@@ -223,7 +265,7 @@
+             return null;
+         }
+ 
+-        Map<String, Class> memberTypes = type.memberTypes();
++        Map<String, Class<?>> memberTypes = type.memberTypes();
+         Map<String, Object> memberValues =
+             new LinkedHashMap<String, Object>(type.memberDefaults());
+ 
+@@ -231,7 +273,7 @@
+         for (int i = 0; i < numMembers; i++) {
+             int memberNameIndex = buf.getShort() & 0xFFFF;
+             String memberName = constPool.getUTF8At(memberNameIndex);
+-            Class memberType = memberTypes.get(memberName);
++            Class<?> memberType = memberTypes.get(memberName);
+ 
+             if (memberType == null) {
+                 // Member is no longer present in annotation type; ignore it
+@@ -252,7 +294,7 @@
+      * member -> value map.
+      */
+     public static Annotation annotationForMap(
+-        Class type, Map<String, Object> memberValues)
++        Class<? extends Annotation> type, Map<String, Object> memberValues)
+     {
+         return (Annotation) Proxy.newProxyInstance(
+             type.getClassLoader(), new Class[] { type },
+@@ -286,14 +328,15 @@
+      * The member must be of the indicated type. If it is not, this
+      * method returns an AnnotationTypeMismatchExceptionProxy.
+      */
+-    public static Object parseMemberValue(Class memberType, ByteBuffer buf,
++    public static Object parseMemberValue(Class<?> memberType,
++                                          ByteBuffer buf,
+                                           ConstantPool constPool,
+-                                          Class container) {
++                                          Class<?> container) {
+         Object result = null;
+         int tag = buf.get();
+         switch(tag) {
+           case 'e':
+-              return parseEnumValue(memberType, buf, constPool, container);
++              return parseEnumValue((Class<? extends Enum<?>>)memberType, buf, constPool, container);
+           case 'c':
+               result = parseClassValue(buf, constPool, container);
+               break;
+@@ -361,7 +404,7 @@
+      */
+     private static Object parseClassValue(ByteBuffer buf,
+                                           ConstantPool constPool,
+-                                          Class container) {
++                                          Class<?> container) {
+         int classIndex = buf.getShort() & 0xFFFF;
+         try {
+             try {
+@@ -379,7 +422,7 @@
+         }
+     }
+ 
+-    private static Class<?> parseSig(String sig, Class container) {
++    private static Class<?> parseSig(String sig, Class<?> container) {
+         if (sig.equals("V")) return void.class;
+         SignatureParser parser = SignatureParser.make();
+         TypeSignature typeSig = parser.parseTypeSig(sig);
+@@ -389,7 +432,7 @@
+         Type result = reify.getResult();
+         return toClass(result);
+     }
+-    static Class toClass(Type o) {
++    static Class<?> toClass(Type o) {
+         if (o instanceof GenericArrayType)
+             return Array.newInstance(toClass(((GenericArrayType)o).getGenericComponentType()),
+                                      0)
+@@ -409,9 +452,9 @@
+      *           u2   const_name_index;
+      *       } enum_const_value;
+      */
+-    private static Object parseEnumValue(Class enumType, ByteBuffer buf,
++    private static Object parseEnumValue(Class<? extends Enum> enumType, ByteBuffer buf,
+                                          ConstantPool constPool,
+-                                         Class container) {
++                                         Class<?> container) {
+         int typeNameIndex = buf.getShort() & 0xFFFF;
+         String typeName  = constPool.getUTF8At(typeNameIndex);
+         int constNameIndex = buf.getShort() & 0xFFFF;
+@@ -449,12 +492,12 @@
+      * If the array values do not match arrayType, an
+      * AnnotationTypeMismatchExceptionProxy will be returned.
+      */
+-    private static Object parseArray(Class arrayType,
++    private static Object parseArray(Class<?> arrayType,
+                                      ByteBuffer buf,
+                                      ConstantPool constPool,
+-                                     Class container) {
++                                     Class<?> container) {
+         int length = buf.getShort() & 0xFFFF;  // Number of array components
+-        Class componentType = arrayType.getComponentType();
++        Class<?> componentType = arrayType.getComponentType();
+ 
+         if (componentType == byte.class) {
+             return parseByteArray(length, buf, constPool);
+@@ -477,11 +520,11 @@
+         } else if (componentType == Class.class) {
+             return parseClassArray(length, buf, constPool, container);
+         } else if (componentType.isEnum()) {
+-            return parseEnumArray(length, componentType, buf,
++            return parseEnumArray(length, (Class<? extends Enum>)componentType, buf,
+                                   constPool, container);
+         } else {
+             assert componentType.isAnnotation();
+-            return parseAnnotationArray(length, componentType, buf,
++            return parseAnnotationArray(length, (Class <? extends Annotation>)componentType, buf,
+                                         constPool, container);
+         }
+     }
+@@ -660,8 +703,8 @@
+     private static Object parseClassArray(int length,
+                                           ByteBuffer buf,
+                                           ConstantPool constPool,
+-                                          Class container) {
+-        Object[] result = new Class[length];
++                                          Class<?> container) {
++        Object[] result = new Class<?>[length];
+         boolean typeMismatch = false;
+         int tag = 0;
+ 
+@@ -677,10 +720,10 @@
+         return typeMismatch ? exceptionProxy(tag) : result;
+     }
+ 
+-    private static Object parseEnumArray(int length, Class enumType,
++    private static Object parseEnumArray(int length, Class<? extends Enum> enumType,
+                                          ByteBuffer buf,
+                                          ConstantPool constPool,
+-                                         Class container) {
++                                         Class<?> container) {
+         Object[] result = (Object[]) Array.newInstance(enumType, length);
+         boolean typeMismatch = false;
+         int tag = 0;
+@@ -698,10 +741,10 @@
+     }
+ 
+     private static Object parseAnnotationArray(int length,
+-                                               Class annotationType,
++                                               Class<? extends Annotation> annotationType,
+                                                ByteBuffer buf,
+                                                ConstantPool constPool,
+-                                               Class container) {
++                                               Class<?> container) {
+         Object[] result = (Object[]) Array.newInstance(annotationType, length);
+         boolean typeMismatch = false;
+         int tag = 0;
+@@ -788,4 +831,16 @@
+         for (int i = 0; i < length; i++)
+             skipMemberValue(buf);
+     }
++
++    /**
++     * Searches for given {@code element} in given {@code array} by identity.
++     * Returns {@code true} if found {@code false} if not.
++     */
++    private static boolean contains(Object[] array, Object element) {
++        for (Object e : array)
++            if (e == element)
++                return true;
++        return false;
++    }
++
+ }
+diff -r d1f592073a0e src/share/classes/sun/reflect/annotation/AnnotationType.java
+--- openjdk/jdk/src/share/classes/sun/reflect/annotation/AnnotationType.java	Fri Sep 12 22:39:32 2014 +0100
++++ openjdk/jdk/src/share/classes/sun/reflect/annotation/AnnotationType.java	Thu Oct 02 20:18:56 2014 +0100
+@@ -1,5 +1,5 @@
+ /*
+- * Copyright (c) 2003, 2006, Oracle and/or its affiliates. All rights reserved.
++ * Copyright (c) 2003, 2014, 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
+@@ -25,6 +25,8 @@
+ 
+ package sun.reflect.annotation;
+ 
++import sun.misc.JavaLangAccess;
++
+ import java.lang.annotation.*;
+ import java.lang.reflect.*;
+ import java.util.*;
+@@ -45,29 +47,28 @@
+      * types.  This matches the return value that must be used for a
+      * dynamic proxy, allowing for a simple isInstance test.
+      */
+-    private final Map<String, Class> memberTypes = new HashMap<String,Class>();
++    private final Map<String, Class<?>> memberTypes;
+ 
+     /**
+      * Member name -> default value mapping.
+      */
+-    private final Map<String, Object> memberDefaults =
+-        new HashMap<String, Object>();
++    private final Map<String, Object> memberDefaults;
+ 
+     /**
+-     * Member name -> Method object mapping. This (and its assoicated
++     * Member name -> Method object mapping. This (and its associated
+      * accessor) are used only to generate AnnotationTypeMismatchExceptions.
+      */
+-    private final Map<String, Method> members = new HashMap<String, Method>();
++    private final Map<String, Method> members;
+ 
+     /**
+      * The retention policy for this annotation type.
+      */
+-    private RetentionPolicy retention = RetentionPolicy.RUNTIME;;
++    private final RetentionPolicy retention;
+ 
+     /**
+      * Whether this annotation type is inherited.
+      */
+-    private boolean inherited = false;
++    private final boolean inherited;
+ 
+     /**
+      * Returns an AnnotationType instance for the specified annotation type.
+@@ -75,13 +76,20 @@
+      * @throw IllegalArgumentException if the specified class object for
+      *     does not represent a valid annotation type
+      */
+-    public static synchronized AnnotationType getInstance(
+-        Class annotationClass)
++    public static AnnotationType getInstance(
++        Class<? extends Annotation> annotationClass)
+     {
+-        AnnotationType result = sun.misc.SharedSecrets.getJavaLangAccess().
+-            getAnnotationType(annotationClass);
+-        if (result == null)
+-            result = new AnnotationType((Class<?>) annotationClass);
++        JavaLangAccess jla = sun.misc.SharedSecrets.getJavaLangAccess();
++        AnnotationType result = jla.getAnnotationType(annotationClass); // volatile read
++        if (result == null) {
++            result = new AnnotationType(annotationClass);
++            // try to CAS the AnnotationType: null -> result
++            if (!jla.casAnnotationType(annotationClass, null, result)) {
++                // somebody was quicker -> read its result
++                result = jla.getAnnotationType(annotationClass);
++                assert result != null;
++            }
++        }
+ 
+         return result;
+     }
+@@ -93,7 +101,7 @@
+      * @throw IllegalArgumentException if the specified class object for
+      *     does not represent a valid annotation type
+      */
+-    private AnnotationType(final Class<?> annotationClass) {
++    private AnnotationType(final Class<? extends Annotation> annotationClass) {
+         if (!annotationClass.isAnnotation())
+             throw new IllegalArgumentException("Not an annotation type");
+ 
+@@ -105,32 +113,42 @@
+                 }
+             });
+ 
++        memberTypes = new HashMap<String,Class<?>>(methods.length+1, 1.0f);
++        memberDefaults = new HashMap<String, Object>(0);
++        members = new HashMap<String, Method>(methods.length+1, 1.0f);
+ 
+         for (Method method :  methods) {
+             if (method.getParameterTypes().length != 0)
+                 throw new IllegalArgumentException(method + " has params");
+             String name = method.getName();
+-            Class type = method.getReturnType();
++            Class<?> type = method.getReturnType();
+             memberTypes.put(name, invocationHandlerReturnType(type));
+             members.put(name, method);
+ 
+             Object defaultValue = method.getDefaultValue();
+             if (defaultValue != null)
+                 memberDefaults.put(name, defaultValue);
+-
+-            members.put(name, method);
+         }
+ 
+-        sun.misc.SharedSecrets.getJavaLangAccess().
+-            setAnnotationType(annotationClass, this);
+-
+         // Initialize retention, & inherited fields.  Special treatment
+         // of the corresponding annotation types breaks infinite recursion.
+         if (annotationClass != Retention.class &&
+             annotationClass != Inherited.class) {
+-            Retention ret = annotationClass.getAnnotation(Retention.class);
++            JavaLangAccess jla = sun.misc.SharedSecrets.getJavaLangAccess();
++            Map<Class<? extends Annotation>, Annotation> metaAnnotations =
++                AnnotationParser.parseSelectAnnotations(
++                    jla.getRawClassAnnotations(annotationClass),
++                    jla.getConstantPool(annotationClass),
++                    annotationClass,
++                    Retention.class, Inherited.class
++                );
++            Retention ret = (Retention) metaAnnotations.get(Retention.class);
+             retention = (ret == null ? RetentionPolicy.CLASS : ret.value());
+-            inherited = annotationClass.isAnnotationPresent(Inherited.class);
++            inherited = metaAnnotations.containsKey(Inherited.class);
++        }
++        else {
++            retention = RetentionPolicy.RUNTIME;
++            inherited = false;
+         }
+     }
+ 
+@@ -140,7 +158,7 @@
+      * the specified type (which is assumed to be a legal member type
+      * for an annotation).
+      */
+-    public static Class invocationHandlerReturnType(Class type) {
++    public static Class<?> invocationHandlerReturnType(Class<?> type) {
+         // Translate primitives to wrappers
+         if (type == byte.class)
+             return Byte.class;
+@@ -167,7 +185,7 @@
+      * Returns member types for this annotation type
+      * (member name -> type mapping).
+      */
+-    public Map<String, Class> memberTypes() {
++    public Map<String, Class<?>> memberTypes() {
+         return memberTypes;
+     }
+ 
+@@ -205,11 +223,10 @@
+      * For debugging.
+      */
+     public String toString() {
+-        StringBuffer s = new StringBuffer("Annotation Type:" + "\n");
+-        s.append("   Member types: " + memberTypes + "\n");
+-        s.append("   Member defaults: " + memberDefaults + "\n");
+-        s.append("   Retention policy: " + retention + "\n");
+-        s.append("   Inherited: " + inherited);
+-        return s.toString();
++        return "Annotation Type:\n" +
++               "   Member types: " + memberTypes + "\n" +
++               "   Member defaults: " + memberDefaults + "\n" +
++               "   Retention policy: " + retention + "\n" +
++               "   Inherited: " + inherited;
+     }
+ }
+diff -r d1f592073a0e test/java/lang/annotation/AnnotationType/AnnotationTypeDeadlockTest.java
+--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
++++ openjdk/jdk/test/java/lang/annotation/AnnotationType/AnnotationTypeDeadlockTest.java	Thu Oct 02 20:18:56 2014 +0100
+@@ -0,0 +1,101 @@
++/*
++ * Copyright (c) 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.
++ *
++ * This code is distributed in the hope that it will be useful, but WITHOUT
++ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
++ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
++ * version 2 for more details (a copy is included in the LICENSE file that
++ * accompanied this code).
++ *
++ * You should have received a copy of the GNU General Public License version
++ * 2 along with this work; if not, write to the Free Software Foundation,
++ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
++ *
++ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
++ * or visit www.oracle.com if you need additional information or have any
++ * questions.
++ */
++
++/*
++ * @test
++ * @bug 7122142
++ * @summary Test deadlock situation when recursive annotations are parsed
++ */
++
++import java.lang.annotation.Retention;
++import java.lang.management.ManagementFactory;
++import java.lang.management.ThreadInfo;
++import java.lang.management.ThreadMXBean;
++import java.util.concurrent.CountDownLatch;
++import java.util.concurrent.atomic.AtomicInteger;
++
++import static java.lang.annotation.RetentionPolicy.RUNTIME;
++
++public class AnnotationTypeDeadlockTest {
++
++    @Retention(RUNTIME)
++    @AnnB
++    public @interface AnnA {
++    }
++
++    @Retention(RUNTIME)
++    @AnnA
++    public @interface AnnB {
++    }
++
++    static class Task extends Thread {
++        final CountDownLatch prepareLatch;
++        final AtomicInteger goLatch;
++        final Class<?> clazz;
++
++        Task(CountDownLatch prepareLatch, AtomicInteger goLatch, Class<?> clazz) {
++            super(clazz.getSimpleName());
++            setDaemon(true); // in case it deadlocks
++            this.prepareLatch = prepareLatch;
++            this.goLatch = goLatch;
++            this.clazz = clazz;
++        }
++
++        @Override
++        public void run() {
++            prepareLatch.countDown();  // notify we are prepared
++            while (goLatch.get() > 0); // spin-wait before go
++            clazz.getDeclaredAnnotations();
++        }
++    }
++
++    public static void main(String[] args) throws Exception {
++        CountDownLatch prepareLatch = new CountDownLatch(2);
++        AtomicInteger goLatch = new AtomicInteger(1);
++        Task taskA = new Task(prepareLatch, goLatch, AnnA.class);
++        Task taskB = new Task(prepareLatch, goLatch, AnnB.class);
++        taskA.start();
++        taskB.start();
++        // wait until both threads start-up
++        prepareLatch.await();
++        // let them go
++        goLatch.set(0);
++        // obtain ThreadMXBean
++        ThreadMXBean threadBean = ManagementFactory.getThreadMXBean();
++        // wait for threads to finish or dead-lock
++        while (taskA.isAlive() || taskB.isAlive()) {
++            // attempt to join threads
++            taskA.join(500L);
++            taskB.join(500L);
++            // detect dead-lock
++            long[] deadlockedIds = threadBean.findMonitorDeadlockedThreads();
++            if (deadlockedIds != null && deadlockedIds.length > 0) {
++                StringBuilder sb = new StringBuilder("deadlock detected:\n\n");
++                for (ThreadInfo ti : threadBean.getThreadInfo(deadlockedIds, Integer.MAX_VALUE)) {
++                    sb.append(ti);
++                }
++                throw new IllegalStateException(sb.toString());
++            }
++        }
++    }
++}
+diff -r d1f592073a0e test/java/lang/annotation/AnnotationType/AnnotationTypeRuntimeAssumptionTest.java
+--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
++++ openjdk/jdk/test/java/lang/annotation/AnnotationType/AnnotationTypeRuntimeAssumptionTest.java	Thu Oct 02 20:18:56 2014 +0100
+@@ -0,0 +1,187 @@
++/*
++ * Copyright (c) 2013, 2014, 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.
++ *
++ * This code is distributed in the hope that it will be useful, but WITHOUT
++ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
++ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
++ * version 2 for more details (a copy is included in the LICENSE file that
++ * accompanied this code).
++ *
++ * You should have received a copy of the GNU General Public License version
++ * 2 along with this work; if not, write to the Free Software Foundation,
++ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
++ *
++ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
++ * or visit www.oracle.com if you need additional information or have any
++ * questions.
++ */
++
++/*
++ * @test
++ * @bug 7122142
++ * @summary Test consistent parsing of ex-RUNTIME annotations that
++ *          were changed and separately compiled to have CLASS retention
++ */
++
++import sun.misc.IOUtils;
++
++import java.io.IOException;
++import java.io.InputStream;
++import java.lang.annotation.Annotation;
++import java.lang.annotation.Retention;
++import java.lang.annotation.RetentionPolicy;
++
++import static java.lang.annotation.RetentionPolicy.CLASS;
++import static java.lang.annotation.RetentionPolicy.RUNTIME;
++
++/**
++ * This test simulates a situation where there are two mutually recursive
++ * {@link RetentionPolicy#RUNTIME RUNTIME} annotations {@link AnnA_v1 AnnA_v1}
++ * and {@link AnnB AnnB} and then the first is changed to have
++ * {@link RetentionPolicy#CLASS CLASS} retention and separately compiled.
++ * When {@link AnnA_v1 AnnA_v1} annotation is looked-up on {@link AnnB AnnB}
++ * it still appears to have {@link RetentionPolicy#RUNTIME RUNTIME} retention.
++ */
++public class AnnotationTypeRuntimeAssumptionTest {
++
++    @Retention(RUNTIME)
++    @AnnB
++    public @interface AnnA_v1 {
++    }
++
++    // An alternative version of AnnA_v1 with CLASS retention instead.
++    // Used to simulate separate compilation (see AltClassLoader below).
++    @Retention(CLASS)
++    @AnnB
++    public @interface AnnA_v2 {
++    }
++
++    @Retention(RUNTIME)
++    @AnnA_v1
++    public @interface AnnB {
++    }
++
++    @AnnA_v1
++    public static class TestTask implements Runnable {
++        @Override
++        public void run() {
++            AnnA_v1 ann1 = getDeclaredAnnotation(TestTask.class, AnnA_v1.class);
++            if (ann1 != null) {
++                throw new IllegalStateException(
++                    "@" + ann1.annotationType().getSimpleName() +
++                    " found on: " + TestTask.class.getName() +
++                    " should not be visible at runtime");
++            }
++            AnnA_v1 ann2 = getDeclaredAnnotation(AnnB.class, AnnA_v1.class);
++            if (ann2 != null) {
++                throw new IllegalStateException(
++                    "@" + ann2.annotationType().getSimpleName() +
++                    " found on: " + AnnB.class.getName() +
++                    " should not be visible at runtime");
++            }
++        }
++
++        private static <A extends Annotation> A getDeclaredAnnotation(Class<?> clazz, Class<A> annotationClass) {
++            for (Annotation ann : clazz.getDeclaredAnnotations()) {
++                if (ann.annotationType() == annotationClass) {
++                    return annotationClass.cast(ann);
++                }
++            }
++            return null;
++        }
++    }
++
++    public static void main(String[] args) throws Exception {
++        ClassLoader altLoader = new AltClassLoader(
++            AnnotationTypeRuntimeAssumptionTest.class.getClassLoader());
++
++        Runnable altTask = (Runnable) Class.forName(
++            TestTask.class.getName(),
++            true,
++            altLoader).newInstance();
++
++        altTask.run();
++    }
++
++    /**
++     * A ClassLoader implementation that loads alternative implementations of
++     * classes. If class name ends with "_v1" it locates instead a class with
++     * name ending with "_v2" and loads that class instead.
++     */
++    static class AltClassLoader extends ClassLoader {
++        AltClassLoader(ClassLoader parent) {
++            super(parent);
++        }
++
++        @Override
++        protected Class<?> loadClass(String name, boolean resolve)
++                throws ClassNotFoundException {
++            if (name.indexOf('.') < 0) { // root package is our class
++                synchronized (getClassLoadingLock(name)) {
++                    // First, check if the class has already been loaded
++                    Class<?> c = findLoadedClass(name);
++                    if (c == null) {
++                        c = findClass(name);
++                    }
++                    if (resolve) {
++                        resolveClass(c);
++                    }
++                    return c;
++                }
++            }
++            else { // not our class
++                return super.loadClass(name, resolve);
++            }
++        }
++
++        @Override
++        protected Class<?> findClass(String name)
++                throws ClassNotFoundException {
++            // special class name -> replace it with alternative name
++            if (name.endsWith("_v1")) {
++                String altName = name.substring(0, name.length() - 3) + "_v2";
++                String altPath = altName.replace('.', '/').concat(".class");
++                try (InputStream is = getResourceAsStream(altPath)) {
++                    if (is != null) {
++                        byte[] bytes = IOUtils.readFully(is, -1, true);
++                        // patch class bytes to contain original name
++                        for (int i = 0; i < bytes.length - 2; i++) {
++                            if (bytes[i] == '_' &&
++                                bytes[i + 1] == 'v' &&
++                                bytes[i + 2] == '2') {
++                                bytes[i + 2] = '1';
++                            }
++                        }
++                        return defineClass(name, bytes, 0, bytes.length);
++                    }
++                    else {
++                        throw new ClassNotFoundException(name);
++                    }
++                }
++                catch (IOException e) {
++                    throw new ClassNotFoundException(name, e);
++                }
++            }
++            else { // not special class name -> just load the class
++                String path = name.replace('.', '/').concat(".class");
++                try (InputStream is = getResourceAsStream(path)) {
++                    if (is != null) {
++                        byte[] bytes = IOUtils.readFully(is, -1, true);
++                        return defineClass(name, bytes, 0, bytes.length);
++                    }
++                    else {
++                        throw new ClassNotFoundException(name);
++                    }
++                }
++                catch (IOException e) {
++                    throw new ClassNotFoundException(name, e);
++                }
++            }
++        }
++    }
++}