7154390: Add support for repeating annotations in j.l.r.AnnotatedElement
authorjfranck
Wed, 28 Nov 2012 09:21:37 -0800
changeset 14676 985410ec95e3
parent 14675 17224d0282f1
child 14678 8cf05595ebb7
7154390: Add support for repeating annotations in j.l.r.AnnotatedElement Reviewed-by: darcy
jdk/src/share/classes/java/lang/Class.java
jdk/src/share/classes/java/lang/Package.java
jdk/src/share/classes/java/lang/System.java
jdk/src/share/classes/java/lang/annotation/ContainedBy.java
jdk/src/share/classes/java/lang/annotation/ContainerFor.java
jdk/src/share/classes/java/lang/annotation/InvalidContainerAnnotationError.java
jdk/src/share/classes/java/lang/reflect/AccessibleObject.java
jdk/src/share/classes/java/lang/reflect/AnnotatedElement.java
jdk/src/share/classes/java/lang/reflect/Executable.java
jdk/src/share/classes/java/lang/reflect/Field.java
jdk/src/share/classes/sun/misc/JavaLangAccess.java
jdk/src/share/classes/sun/reflect/annotation/AnnotationParser.java
jdk/src/share/classes/sun/reflect/annotation/AnnotationSupport.java
jdk/src/share/classes/sun/reflect/generics/reflectiveObjects/TypeVariableImpl.java
jdk/test/java/lang/annotation/repeatingAnnotations/RepeatedUnitTest.java
jdk/test/java/lang/annotation/repeatingAnnotations/subpackage/Containee.java
jdk/test/java/lang/annotation/repeatingAnnotations/subpackage/Container.java
jdk/test/java/lang/annotation/repeatingAnnotations/subpackage/InheritedContainee.java
jdk/test/java/lang/annotation/repeatingAnnotations/subpackage/InheritedContainer.java
jdk/test/java/lang/annotation/repeatingAnnotations/subpackage/InheritedNonRepeated.java
jdk/test/java/lang/annotation/repeatingAnnotations/subpackage/NonRepeated.java
jdk/test/java/lang/annotation/repeatingAnnotations/subpackage/package-info.java
--- a/jdk/src/share/classes/java/lang/Class.java	Wed Nov 28 05:18:57 2012 -0800
+++ b/jdk/src/share/classes/java/lang/Class.java	Wed Nov 28 09:21:37 2012 -0800
@@ -48,6 +48,7 @@
 import java.util.Set;
 import java.util.Map;
 import java.util.HashMap;
+import java.util.Objects;
 import sun.misc.Unsafe;
 import sun.reflect.ConstantPool;
 import sun.reflect.Reflection;
@@ -3044,34 +3045,62 @@
      * @throws NullPointerException {@inheritDoc}
      * @since 1.5
      */
-    @SuppressWarnings("unchecked")
     public <A extends Annotation> A getAnnotation(Class<A> annotationClass) {
-        if (annotationClass == null)
-            throw new NullPointerException();
+        Objects.requireNonNull(annotationClass);
 
         initAnnotationsIfNecessary();
-        return (A) annotations.get(annotationClass);
+        return AnnotationSupport.getOneAnnotation(annotations, annotationClass);
     }
 
     /**
      * @throws NullPointerException {@inheritDoc}
      * @since 1.5
      */
-    public boolean isAnnotationPresent(
-        Class<? extends Annotation> annotationClass) {
-        if (annotationClass == null)
-            throw new NullPointerException();
+    public boolean isAnnotationPresent(Class<? extends Annotation> annotationClass) {
+        Objects.requireNonNull(annotationClass);
 
         return getAnnotation(annotationClass) != null;
     }
 
+    /**
+     * @throws NullPointerException {@inheritDoc}
+     * @since 1.8
+     */
+    public <A extends Annotation> A[] getAnnotations(Class<A> annotationClass) {
+        Objects.requireNonNull(annotationClass);
+
+        initAnnotationsIfNecessary();
+        return AnnotationSupport.getMultipleAnnotations(annotations, annotationClass);
+    }
 
     /**
      * @since 1.5
      */
     public Annotation[] getAnnotations() {
         initAnnotationsIfNecessary();
-        return AnnotationParser.toArray(annotations);
+        return AnnotationSupport.unpackToArray(annotations);
+    }
+
+    /**
+     * @throws NullPointerException {@inheritDoc}
+     * @since 1.8
+     */
+    public <A extends Annotation> A getDeclaredAnnotation(Class<A> annotationClass) {
+        Objects.requireNonNull(annotationClass);
+
+        initAnnotationsIfNecessary();
+        return AnnotationSupport.getOneAnnotation(declaredAnnotations, annotationClass);
+    }
+
+    /**
+     * @throws NullPointerException {@inheritDoc}
+     * @since 1.8
+     */
+    public <A extends Annotation> A[] getDeclaredAnnotations(Class<A> annotationClass) {
+        Objects.requireNonNull(annotationClass);
+
+        initAnnotationsIfNecessary();
+        return AnnotationSupport.getMultipleAnnotations(declaredAnnotations, annotationClass);
     }
 
     /**
@@ -3079,7 +3108,17 @@
      */
     public Annotation[] getDeclaredAnnotations()  {
         initAnnotationsIfNecessary();
-        return AnnotationParser.toArray(declaredAnnotations);
+        return AnnotationSupport.unpackToArray(declaredAnnotations);
+    }
+
+    /** Returns one "directly" present annotation or null */
+    <A extends Annotation> A getDirectDeclaredAnnotation(Class<A> annotationClass) {
+        Objects.requireNonNull(annotationClass);
+
+        initAnnotationsIfNecessary();
+        @SuppressWarnings("unchecked") // TODO check safe
+        A ret = (A)declaredAnnotations.get(annotationClass);
+        return ret;
     }
 
     // Annotations cache
--- a/jdk/src/share/classes/java/lang/Package.java	Wed Nov 28 05:18:57 2012 -0800
+++ b/jdk/src/share/classes/java/lang/Package.java	Wed Nov 28 09:21:37 2012 -0800
@@ -395,6 +395,14 @@
     }
 
     /**
+     * @throws NullPointerException {@inheritDoc}
+     * @since 1.8
+     */
+    public  <A extends Annotation> A[] getAnnotations(Class<A> annotationClass) {
+        return getPackageInfo().getAnnotations(annotationClass);
+    }
+
+    /**
      * @since 1.5
      */
     public Annotation[] getAnnotations() {
@@ -402,6 +410,22 @@
     }
 
     /**
+     * @throws NullPointerException {@inheritDoc}
+     * @since 1.8
+     */
+    public <A extends Annotation> A getDeclaredAnnotation(Class<A> annotationClass) {
+        return getPackageInfo().getDeclaredAnnotation(annotationClass);
+    }
+
+    /**
+     * @throws NullPointerException {@inheritDoc}
+     * @since 1.8
+     */
+    public <A extends Annotation> A[] getDeclaredAnnotations(Class<A> annotationClass) {
+        return getPackageInfo().getDeclaredAnnotations(annotationClass);
+    }
+
+    /**
      * @since 1.5
      */
     public Annotation[] getDeclaredAnnotations()  {
--- a/jdk/src/share/classes/java/lang/System.java	Wed Nov 28 05:18:57 2012 -0800
+++ b/jdk/src/share/classes/java/lang/System.java	Wed Nov 28 09:21:37 2012 -0800
@@ -25,6 +25,7 @@
 package java.lang;
 
 import java.io.*;
+import java.lang.annotation.Annotation;
 import java.util.Properties;
 import java.util.PropertyPermission;
 import java.util.StringTokenizer;
@@ -1195,6 +1196,9 @@
             public AnnotationType getAnnotationType(Class<?> klass) {
                 return klass.getAnnotationType();
             }
+            public <A extends Annotation> A getDirectDeclaredAnnotation(Class<?> klass, Class<A> anno) {
+                return klass.getDirectDeclaredAnnotation(anno);
+            }
             public <E extends Enum<E>>
                     E[] getEnumConstantsShared(Class<E> klass) {
                 return klass.getEnumConstantsShared();
--- a/jdk/src/share/classes/java/lang/annotation/ContainedBy.java	Wed Nov 28 05:18:57 2012 -0800
+++ b/jdk/src/share/classes/java/lang/annotation/ContainedBy.java	Wed Nov 28 09:21:37 2012 -0800
@@ -26,10 +26,35 @@
 package java.lang.annotation;
 
 /**
- * A meta-annotation to indicate which annotation type should be used
- * as a container for repeated values of the annotation type modified
- * by the {@code ContainedBy} annotation.
+ * The annotation type {@code java.lang.annotation.ContainedBy} is
+ * used to indicate that the annotation type whose declaration it
+ * (meta-)annotates is <em>repeatable</em>. The value of
+ * {@code @ContainedBy} indicates the <em>containing annotation
+ * type</em> for the repeatable annotation type.
+ *
+ * <p>The pair of annotation types {@code @ContainedBy} and
+ * {@link java.lang.annotation.ContainerFor @ContainerFor} are used to
+ * indicate that annotation types are repeatable. Specifically:
+ *
+ * <ul>
+ * <li>The annotation type {@code @ContainedBy} is used on the
+ * declaration of a repeatable annotation type (JLS 9.6) to indicate
+ * its containing annotation type.
  *
+ * <li>The annotation type {@code @ContainerFor} is used on the
+ * declaration of a containing annotation type (JLS 9.6) to indicate
+ * the repeatable annotation type for which it serves as the
+ * containing annotation type.
+ * </ul>
+ *
+ * <p>
+ * An inconsistent pair of {@code @ContainedBy} and
+ * {@code @ContainerFor} annotations on a repeatable annotation type
+ * and its containing annotation type (JLS 9.6) will lead to
+ * compile-time errors and runtime exceptions when using reflection to
+ * read annotations of a repeatable type.
+ *
+ * @see java.lang.annotation.ContainerFor
  * @since 1.8
  * @jls 9.6 Annotation Types
  * @jls 9.7 Annotations
@@ -39,8 +64,8 @@
 @Target(ElementType.ANNOTATION_TYPE)
 public @interface ContainedBy {
     /**
-     * The annotation type to use to store repeated values of another
-     * annotation.
+     * Indicates the <em>containing annotation type</em> for the
+     * repeatable annotation type.
      */
     Class<? extends Annotation> value();
 }
--- a/jdk/src/share/classes/java/lang/annotation/ContainerFor.java	Wed Nov 28 05:18:57 2012 -0800
+++ b/jdk/src/share/classes/java/lang/annotation/ContainerFor.java	Wed Nov 28 09:21:37 2012 -0800
@@ -26,10 +26,36 @@
 package java.lang.annotation;
 
 /**
- * Indicates that an annotation type is a container for repeated
- * instances of annotations of the type of the value of the
- * {@code ContainerFor}'s value element.
+ * The annotation type {@code java.lang.annotation.ContainerFor} is
+ * used to indicate that the annotation type whose declaration it
+ * (meta-)annotates is a <em>containing annotation type</em>. The
+ * value of {@code @ContainerFor} indicates the <em>repeatable
+ * annotation type</em> for the containing annotation type.
+ *
+ * <p>The pair of annotation types {@link
+ * java.lang.annotation.ContainedBy @ContainedBy} and
+ * {@code @ContainerFor} are used to indicate that annotation types
+ * are repeatable. Specifically:
  *
+ * <ul>
+ * <li>The annotation type {@code @ContainedBy} is used on the
+ * declaration of a repeatable annotation type (JLS 9.6) to indicate
+ * its containing annotation type.
+ *
+ * <li>The annotation type {@code @ContainerFor} is used on the
+ * declaration of a containing annotation type (JLS 9.6) to indicate
+ * the repeatable annotation type for which it serves as the
+ * containing annotation type.
+ * </ul>
+ *
+ * <p>
+ * An inconsistent pair of {@code @ContainedBy} and
+ * {@code @ContainerFor} annotations on a repeatable annotation type
+ * and its containing annotation type (JLS 9.6) will lead to
+ * compile-time errors and runtime exceptions when using reflection to
+ * read annotations of a repeatable type.
+ *
+ * @see java.lang.annotation.ContainedBy
  * @since 1.8
  * @jls 9.6 Annotation Types
  * @jls 9.7 Annotations
@@ -38,9 +64,10 @@
 @Retention(RetentionPolicy.RUNTIME)
 @Target(ElementType.ANNOTATION_TYPE)
 public @interface ContainerFor {
+
     /**
-     * The repeating annotation type that the annotation type
-     * annotated with this annotation is a container for.
+     * Indicates the repeatable annotation type for the containing
+     * annotation type.
      */
     Class<? extends Annotation> value();
 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/share/classes/java/lang/annotation/InvalidContainerAnnotationError.java	Wed Nov 28 09:21:37 2012 -0800
@@ -0,0 +1,129 @@
+/*
+ * Copyright (c) 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
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * 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.
+ */
+package java.lang.annotation;
+
+import java.util.Objects;
+
+/**
+ * Thrown to indicate that an annotation type whose declaration is
+ * (meta-)annotated with a {@link ContainerFor} annotation is not, in
+ * fact, the <em>containing annotation type of the type named by {@link
+ * ContainerFor}</em>.
+ *
+ * @see   java.lang.reflect.AnnotatedElement
+ * @since 1.8
+ * @jls   9.6 Annotation Types
+ * @jls   9.7 Annotations
+ */
+public class InvalidContainerAnnotationError extends AnnotationFormatError {
+    private static final long serialVersionUID = 5023L;
+
+    /**
+     * The instance of the erroneous container.
+     */
+    private transient Annotation container;
+
+    /**
+     * The type of the annotation that should be contained in the
+     * container.
+     */
+    private transient Class<? extends Annotation> annotationType;
+
+    /**
+     * Constructs a new InvalidContainerAnnotationError with the
+     * specified detail message.
+     *
+     * @param  message the detail message.
+     */
+    public InvalidContainerAnnotationError(String message) {
+        super(message);
+    }
+
+    /**
+     * Constructs a new InvalidContainerAnnotationError with the specified
+     * detail message and cause.  Note that the detail message associated
+     * with {@code cause} is <i>not</i> automatically incorporated in
+     * this error's detail message.
+     *
+     * @param message the detail message
+     * @param cause the cause, may be {@code null}
+     */
+    public InvalidContainerAnnotationError(String message, Throwable cause) {
+        super(message, cause);
+    }
+
+    /**
+     * Constructs a new InvalidContainerAnnotationError with the
+     * specified cause and a detail message of {@code (cause == null ?
+     * null : cause.toString())} (which typically contains the class
+     * and detail message of {@code cause}).
+     *
+     * @param cause the cause, may be {@code null}
+     */
+    public InvalidContainerAnnotationError(Throwable cause) {
+        super(cause);
+    }
+
+    /**
+     * Constructs InvalidContainerAnnotationError for the specified
+     * container instance and contained annotation type.
+     *
+     * @param  message the detail message
+     * @param  cause the cause, may be {@code null}
+     * @param container the erroneous container instance, may be
+     *        {@code null}
+     * @param annotationType the annotation type intended to be
+     *        contained, may be {@code null}
+     */
+    public InvalidContainerAnnotationError(String message,
+                                           Throwable cause,
+                                           Annotation container,
+                                           Class<? extends Annotation> annotationType) {
+        super(message, cause);
+        this.container = container;
+        this.annotationType = annotationType;
+    }
+
+    /**
+     * Returns the erroneous container.
+     *
+     * @return the erroneous container, may return {@code null}
+     */
+    public Annotation getContainer() {
+        return container;
+    }
+
+    /**
+     * Returns the annotation type intended to be contained. Returns
+     * {@code null} if the annotation type intended to be contained
+     * could not be determined.
+     *
+     * @return the annotation type intended to be contained, or {@code
+     * null} if unknown
+     */
+    public Class<? extends Annotation> getAnnotationType() {
+        return annotationType;
+    }
+}
--- a/jdk/src/share/classes/java/lang/reflect/AccessibleObject.java	Wed Nov 28 05:18:57 2012 -0800
+++ b/jdk/src/share/classes/java/lang/reflect/AccessibleObject.java	Wed Nov 28 09:21:37 2012 -0800
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 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
@@ -184,12 +184,19 @@
      * @throws NullPointerException {@inheritDoc}
      * @since 1.5
      */
-    public boolean isAnnotationPresent(
-        Class<? extends Annotation> annotationClass) {
+    public boolean isAnnotationPresent(Class<? extends Annotation> annotationClass) {
         return getAnnotation(annotationClass) != null;
     }
 
     /**
+     * @throws NullPointerException {@inheritDoc}
+     * @since 1.8
+     */
+    public <T extends Annotation> T[] getAnnotations(Class<T> annotationClass) {
+        throw new AssertionError("All subclasses should override this method");
+    }
+
+    /**
      * @since 1.5
      */
     public Annotation[] getAnnotations() {
@@ -197,6 +204,28 @@
     }
 
     /**
+     * @throws NullPointerException {@inheritDoc}
+     * @since 1.8
+     */
+    public <T extends Annotation> T getDeclaredAnnotation(Class<T> annotationClass) {
+        // Only annotations on classes are inherited, for all other
+        // objects getDeclaredAnnotation is the same as
+        // getAnnotation.
+        return getAnnotation(annotationClass);
+    }
+
+    /**
+     * @throws NullPointerException {@inheritDoc}
+     * @since 1.8
+     */
+    public <T extends Annotation> T[] getDeclaredAnnotations(Class<T> annotationClass) {
+        // Only annotations on classes are inherited, for all other
+        // objects getDeclaredAnnotations is the same as
+        // getAnnotations.
+        return getAnnotations(annotationClass);
+    }
+
+    /**
      * @since 1.5
      */
     public Annotation[] getDeclaredAnnotations()  {
--- a/jdk/src/share/classes/java/lang/reflect/AnnotatedElement.java	Wed Nov 28 05:18:57 2012 -0800
+++ b/jdk/src/share/classes/java/lang/reflect/AnnotatedElement.java	Wed Nov 28 09:21:37 2012 -0800
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2003, 2005, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 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
@@ -45,6 +45,11 @@
  * a {@link EnumConstantNotPresentException} if the enum constant in the
  * annotation is no longer present in the enum type.
  *
+ * <p>Attempting to read annotations of a repeatable annotation type T
+ * that are contained in an annotation whose type is not, in fact, the
+ * containing annotation type of T will result in an
+ * InvalidContainerAnnotationError.
+ *
  * <p>Finally, Attempting to read a member whose definition has evolved
  * incompatibly will result in a {@link
  * java.lang.annotation.AnnotationTypeMismatchException} or an
@@ -55,6 +60,7 @@
  * @see java.lang.annotation.AnnotationFormatError
  * @see java.lang.annotation.AnnotationTypeMismatchException
  * @see java.lang.annotation.IncompleteAnnotationException
+ * @see java.lang.annotation.InvalidContainerAnnotationError
  * @since 1.5
  * @author Josh Bloch
  */
@@ -87,6 +93,23 @@
     <T extends Annotation> T getAnnotation(Class<T> annotationClass);
 
     /**
+     * Returns an array of all this element's annotations for the
+     * specified type if one or more of such annotation is present,
+     * else an array of length zero.
+     *
+     * The caller of this method is free to modify the returned array;
+     * it will have no effect on the arrays returned to other callers.
+     *
+     * @param annotationClass the Class object corresponding to the
+     *        annotation type
+     * @return all this element's annotations for the specified annotation type if
+     *     present on this element, else an array of length zero
+     * @throws NullPointerException if the given annotation class is null
+     * @since 1.8
+     */
+    <T extends Annotation> T[] getAnnotations(Class<T> annotationClass);
+
+    /**
      * Returns all annotations present on this element.  (Returns an array
      * of length zero if this element has no annotations.)  The caller of
      * this method is free to modify the returned array; it will have no
@@ -98,12 +121,48 @@
     Annotation[] getAnnotations();
 
     /**
+     * Returns this element's annotation for the specified type if
+     * such an annotation is present, else null.
+     *
+     * This method ignores inherited annotations. (Returns null if no
+     * annotations are directly present on this element.)
+     *
+     * @param annotationClass the Class object corresponding to the
+     *        annotation type
+     * @return this element's annotation for the specified annotation type if
+     *     present on this element, else null
+     * @throws NullPointerException if the given annotation class is null
+     * @since 1.8
+     */
+    <T extends Annotation> T getDeclaredAnnotation(Class<T> annotationClass);
+
+   /**
+     * Returns an array of all this element's annotations for the
+     * specified type if one or more of such annotation is directly
+     * present, else an array of length zero.
+     *
+     * This method ignores inherited annotations. (Returns
+     * an array of length zero if no annotations are directly present
+     * on this element.)  The caller of this method is free to modify
+     * the returned array; it will have no effect on the arrays
+     * returned to other callers.
+     *
+     * @param annotationClass the Class object corresponding to the
+     *        annotation type
+     * @return all this element's annotations for the specified annotation type if
+     *     present on this element, else an array of length zero
+     * @throws NullPointerException if the given annotation class is null
+     * @since 1.8
+     */
+    <T extends Annotation> T[] getDeclaredAnnotations(Class<T> annotationClass);
+
+    /**
      * Returns all annotations that are directly present on this
-     * element.  Unlike the other methods in this interface, this method
-     * ignores inherited annotations.  (Returns an array of length zero if
-     * no annotations are directly present on this element.)  The caller of
-     * this method is free to modify the returned array; it will have no
-     * effect on the arrays returned to other callers.
+     * element. This method ignores inherited annotations. (Returns
+     * an array of length zero if no annotations are directly present
+     * on this element.)  The caller of this method is free to modify
+     * the returned array; it will have no effect on the arrays
+     * returned to other callers.
      *
      * @return All annotations directly present on this element
      * @since 1.5
--- a/jdk/src/share/classes/java/lang/reflect/Executable.java	Wed Nov 28 05:18:57 2012 -0800
+++ b/jdk/src/share/classes/java/lang/reflect/Executable.java	Wed Nov 28 09:21:37 2012 -0800
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2011, 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 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
@@ -26,8 +26,11 @@
 package java.lang.reflect;
 
 import java.lang.annotation.*;
+import java.util.Collections;
 import java.util.Map;
+import java.util.Objects;
 import sun.reflect.annotation.AnnotationParser;
+import sun.reflect.annotation.AnnotationSupport;
 import sun.reflect.generics.repository.ConstructorRepository;
 
 /**
@@ -363,19 +366,28 @@
      * {@inheritDoc}
      * @throws NullPointerException  {@inheritDoc}
      */
-    @SuppressWarnings("unchecked")
     public <T extends Annotation> T getAnnotation(Class<T> annotationClass) {
-        if (annotationClass == null)
-            throw new NullPointerException();
+        Objects.requireNonNull(annotationClass);
+
+        return AnnotationSupport.getOneAnnotation(declaredAnnotations(), annotationClass);
+    }
 
-        return (T) declaredAnnotations().get(annotationClass);
+    /**
+     * {@inheritDoc}
+     * @throws NullPointerException {@inheritDoc}
+     * @since 1.8
+     */
+    public <T extends Annotation> T[] getAnnotations(Class<T> annotationClass) {
+        Objects.requireNonNull(annotationClass);
+
+        return AnnotationSupport.getMultipleAnnotations(declaredAnnotations(), annotationClass);
     }
 
     /**
      * {@inheritDoc}
      */
     public Annotation[] getDeclaredAnnotations()  {
-        return AnnotationParser.toArray(declaredAnnotations());
+        return AnnotationSupport.unpackToArray(declaredAnnotations());
     }
 
     private transient Map<Class<? extends Annotation>, Annotation> declaredAnnotations;
--- a/jdk/src/share/classes/java/lang/reflect/Field.java	Wed Nov 28 05:18:57 2012 -0800
+++ b/jdk/src/share/classes/java/lang/reflect/Field.java	Wed Nov 28 09:21:37 2012 -0800
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1996, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1996, 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
@@ -33,7 +33,9 @@
 import sun.reflect.generics.scope.ClassScope;
 import java.lang.annotation.Annotation;
 import java.util.Map;
+import java.util.Objects;
 import sun.reflect.annotation.AnnotationParser;
+import sun.reflect.annotation.AnnotationSupport;
 
 
 /**
@@ -1012,19 +1014,28 @@
      * @throws NullPointerException {@inheritDoc}
      * @since 1.5
      */
-    @SuppressWarnings("unchecked")
     public <T extends Annotation> T getAnnotation(Class<T> annotationClass) {
-        if (annotationClass == null)
-            throw new NullPointerException();
+        Objects.requireNonNull(annotationClass);
 
-        return (T) declaredAnnotations().get(annotationClass);
+        return AnnotationSupport.getOneAnnotation(declaredAnnotations(), annotationClass);
     }
 
     /**
-     * @since 1.5
+     * {@inheritDoc}
+     * @throws NullPointerException {@inheritDoc}
+     * @since 1.8
+     */
+    public <T extends Annotation> T[] getAnnotations(Class<T> annotationClass) {
+        Objects.requireNonNull(annotationClass);
+
+        return AnnotationSupport.getMultipleAnnotations(declaredAnnotations(), annotationClass);
+    }
+
+    /**
+     * {@inheritDoc}
      */
     public Annotation[] getDeclaredAnnotations()  {
-        return AnnotationParser.toArray(declaredAnnotations());
+        return AnnotationSupport.unpackToArray(declaredAnnotations());
     }
 
     private transient Map<Class<? extends Annotation>, Annotation> declaredAnnotations;
--- a/jdk/src/share/classes/sun/misc/JavaLangAccess.java	Wed Nov 28 05:18:57 2012 -0800
+++ b/jdk/src/share/classes/sun/misc/JavaLangAccess.java	Wed Nov 28 09:21:37 2012 -0800
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2003, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 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
@@ -25,6 +25,7 @@
 
 package sun.misc;
 
+import java.lang.annotation.Annotation;
 import sun.reflect.ConstantPool;
 import sun.reflect.annotation.AnnotationType;
 import sun.nio.ch.Interruptible;
@@ -83,4 +84,9 @@
      * Returns the ith StackTraceElement for the given throwable.
      */
     StackTraceElement getStackTraceElement(Throwable t, int i);
+
+    /**
+     * Returns a directly present annotation.
+     */
+    public <A extends Annotation> A getDirectDeclaredAnnotation(Class<?> klass, Class<A> anno);
 }
--- a/jdk/src/share/classes/sun/reflect/annotation/AnnotationParser.java	Wed Nov 28 05:18:57 2012 -0800
+++ b/jdk/src/share/classes/sun/reflect/annotation/AnnotationParser.java	Wed Nov 28 09:21:37 2012 -0800
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2003, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 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
@@ -806,4 +806,6 @@
     public static Annotation[] toArray(Map<Class<? extends Annotation>, Annotation> annotations) {
         return annotations.values().toArray(EMPTY_ANNOTATION_ARRAY);
     }
+
+    static Annotation[] getEmptyAnnotationArray() { return EMPTY_ANNOTATION_ARRAY; }
 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/share/classes/sun/reflect/annotation/AnnotationSupport.java	Wed Nov 28 09:21:37 2012 -0800
@@ -0,0 +1,232 @@
+/*
+ * Copyright (c) 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
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * 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.
+ */
+
+package sun.reflect.annotation;
+
+import java.lang.annotation.*;
+import java.lang.reflect.*;
+import java.util.Arrays;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import java.util.Map;
+import java.util.Objects;
+import sun.reflect.Reflection;
+import sun.misc.JavaLangAccess;
+
+public final class AnnotationSupport {
+    private static JavaLangAccess javaLangAccess = sun.misc.SharedSecrets.getJavaLangAccess();
+
+    /**
+     * Finds and returns _one_ annotation of the type indicated by
+     * {@code annotationClass} from the {@code Map} {@code
+     * annotationMap}. Looks into containers of the {@code
+     * annotationClass} (as specified by an the {@code
+     * annotationClass} type being meta-annotated with an {@code
+     * ContainedBy} annotation).
+     *
+     * @param annotationMap the {@code Map} used to store annotations and indexed by their type
+     * @param annotationClass the type of annotation to search for
+     *
+     * @return in instance of {@code annotationClass} or {@code null} if none were found
+     */
+    public static <A extends Annotation> A getOneAnnotation(final Map<Class<? extends Annotation>, Annotation> annotationMap,
+                                                            final Class<A> annotationClass) {
+        @SuppressWarnings("unchecked")
+        final A candidate = (A)annotationMap.get(annotationClass);
+        if (candidate != null) {
+            return candidate;
+        }
+
+        final Class<? extends Annotation> containerClass = getContainer(annotationClass);
+        if (containerClass != null) {
+            return unpackOne(annotationMap.get(containerClass), annotationClass);
+        }
+
+        return null; // found none
+    }
+
+    /**
+     * Finds and returns all annotation of the type indicated by
+     * {@code annotationClass} from the {@code Map} {@code
+     * annotationMap}. Looks into containers of the {@code
+     * annotationClass} (as specified by an the {@code
+     * annotationClass} type being meta-annotated with an {@code
+     * ContainedBy} annotation).
+     *
+     * @param annotationMap the {@code Map} used to store annotations indexed by their type
+     * @param annotationClass the type of annotation to search for
+     *
+     * @return an array of instances of {@code annotationClass} or an empty array if none were found
+     */
+    public static  <A extends Annotation> A[] getMultipleAnnotations(final Map<Class<? extends Annotation>, Annotation> annotationMap,
+                                                                     final Class<A> annotationClass) {
+        final ArrayList<A> res = new ArrayList<A>();
+
+        @SuppressWarnings("unchecked")
+        final A candidate = (A)annotationMap.get(annotationClass);
+        if (candidate != null) {
+            res.add(candidate);
+        }
+
+        final Class<? extends Annotation> containerClass = getContainer(annotationClass);
+        if (containerClass != null) {
+            res.addAll(unpackAll(annotationMap.get(containerClass), annotationClass));
+        }
+
+        @SuppressWarnings("unchecked") // should be safe annotationClass is a token for A
+        final A[] emptyTemplateArray = (A[])Array.newInstance(annotationClass, 0);
+        return res.isEmpty() ? emptyTemplateArray : res.toArray(emptyTemplateArray);
+    }
+
+    /**
+     * Unpacks the {@code annotationMap} parameter into an array of
+     * {@code Annotation}s. This method will unpack all repeating
+     * annotaions containers (once). An annotation type is marked as a
+     * container by meta-annotating it the with the {@code
+     * ContainerFor} annotation.
+     *
+     * @param annotationMap the {@code Map} from where the annotations are unpacked
+     *
+     * @return an array of Annotation
+     */
+    public static Annotation[] unpackToArray(Map<Class<? extends Annotation>, Annotation> annotationMap) {
+        List<Annotation> res = new ArrayList<>();
+        for (Map.Entry<Class<? extends Annotation>, Annotation> e : annotationMap.entrySet()) {
+            Class<? extends Annotation> annotationClass = e.getKey();
+            Annotation annotationInstance = e.getValue();
+            Class<? extends Annotation> containee = getContainee(e.getKey());
+            boolean isContainer = javaLangAccess.getDirectDeclaredAnnotation(annotationClass, ContainerFor.class) != null;
+
+            if (isContainer) {
+                res.addAll(unpackAll(annotationInstance, containee));
+            } else {
+                res.add(annotationInstance);
+            }
+        }
+
+        return res.isEmpty()
+               ? AnnotationParser.getEmptyAnnotationArray()
+               : res.toArray(AnnotationParser.getEmptyAnnotationArray());
+    }
+
+    /** Helper to get the container, or null if none, of an annotation. */
+    private static <A extends Annotation> Class<? extends Annotation> getContainer(Class<A> annotationClass) {
+        ContainedBy containerAnnotation =
+            javaLangAccess.getDirectDeclaredAnnotation(annotationClass, ContainedBy.class);
+        return (containerAnnotation == null) ? null : containerAnnotation.value();
+    }
+
+    /** Helper to get the containee, or null if this isn't a container, of a possible container annotation. */
+    private static <A extends Annotation> Class<? extends Annotation> getContainee(Class<A> annotationClass) {
+        ContainerFor containerAnnotation =
+            javaLangAccess.getDirectDeclaredAnnotation(annotationClass, ContainerFor.class);
+        return (containerAnnotation == null) ? null : containerAnnotation.value();
+    }
+
+    /** Reflectively look up and get the returned array from the the
+     * invocation of the value() element on an instance of an
+     * Annotation.
+     */
+    private static  <A extends Annotation> A[] getValueArray(Annotation containerInstance) {
+        try {
+            // the spec tells us the container must have an array-valued
+            // value element. Get the AnnotationType, get the "value" element
+            // and invoke it to get the contents.
+
+            Class<?> containerClass = containerInstance.annotationType();
+            AnnotationType annoType = javaLangAccess.getAnnotationType(containerClass);
+            if (annoType == null)
+                throw new InvalidContainerAnnotationError(containerInstance + " is an invalid container for repeating annotations");
+
+            Method m = annoType.members().get("value");
+            if (m == null)
+                throw new InvalidContainerAnnotationError(containerInstance + " is an invalid container for repeating annotations");
+            m.setAccessible(true);
+
+            @SuppressWarnings("unchecked") // not provably safe, but we catch the ClassCastException
+            A[] a = (A[])m.invoke(containerInstance); // this will erase to (Annotation[]) but we
+                                                      // do a runtime cast on the return-value
+                                                      // in the methods that call this method
+            return a;
+        } catch (IllegalAccessException | // couldnt loosen security
+                 IllegalArgumentException | // parameters doesn't match
+                 InvocationTargetException | // the value method threw an exception
+                 ClassCastException e) { // well, a cast failed ...
+            e.getCause().printStackTrace();
+            throw new InvalidContainerAnnotationError(containerInstance + " is an invalid container for repeating annotations",
+                                                      e,
+                                                      containerInstance,
+                                                      null);
+        }
+    }
+
+    /* Sanity check type of and return the first annotation instance
+     * of type {@code annotationClass} from {@code
+     * containerInstance}.
+     */
+    private static <A extends Annotation> A unpackOne(Annotation containerInstance, Class<A> annotationClass) {
+        if (containerInstance == null) {
+            return null;
+        }
+
+        try {
+            return annotationClass.cast(getValueArray(containerInstance)[0]);
+        } catch (ArrayIndexOutOfBoundsException | // empty array
+                 ClassCastException | // well, a cast failed ...
+                 NullPointerException e) { // can this NP? for good meassure
+            throw new InvalidContainerAnnotationError(String.format("%s is an invalid container for repeating annotations of type: %s",
+                                                                    containerInstance, annotationClass),
+                                                      e,
+                                                      containerInstance,
+                                                      annotationClass);
+        }
+    }
+
+    /* Sanity check type of and return a list of all the annotation
+     * instances of type {@code annotationClass} from {@code
+     * containerInstance}.
+     */
+    private static <A extends Annotation> List<A> unpackAll(Annotation containerInstance, Class<A> annotationClass) {
+        if (containerInstance == null) {
+            return Collections.emptyList(); // container not present
+        }
+
+        try {
+            A[] a = getValueArray(containerInstance);
+            ArrayList<A> l = new ArrayList<>(a.length);
+            for (int i  = 0; i < a.length; i++)
+                l.add(annotationClass.cast(a[i]));
+            return l;
+        } catch (ClassCastException |
+                 NullPointerException e) {
+            throw new InvalidContainerAnnotationError(String.format("%s is an invalid container for repeating annotations of type: %s",
+                                                                    containerInstance, annotationClass),
+                                                      e,
+                                                      containerInstance,
+                                                      annotationClass);
+        }
+    }
+}
--- a/jdk/src/share/classes/sun/reflect/generics/reflectiveObjects/TypeVariableImpl.java	Wed Nov 28 05:18:57 2012 -0800
+++ b/jdk/src/share/classes/sun/reflect/generics/reflectiveObjects/TypeVariableImpl.java	Wed Nov 28 09:21:37 2012 -0800
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2003, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 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
@@ -26,6 +26,7 @@
 package sun.reflect.generics.reflectiveObjects;
 
 import java.lang.annotation.Annotation;
+import java.lang.reflect.Array;
 import java.lang.reflect.GenericDeclaration;
 import java.lang.reflect.Type;
 import java.lang.reflect.TypeVariable;
@@ -192,6 +193,25 @@
         return null;
     }
 
+    public <T extends Annotation> T getDeclaredAnnotation(Class<T> annotationClass) {
+        Objects.requireNonNull(annotationClass);
+        return null;
+    }
+
+    @SuppressWarnings("unchecked")
+    public <T extends Annotation> T[] getAnnotations(Class<T> annotationClass) {
+        Objects.requireNonNull(annotationClass);
+        // safe because annotationClass is the class for T
+        return (T[])Array.newInstance(annotationClass, 0);
+    }
+
+    @SuppressWarnings("unchecked")
+    public <T extends Annotation> T[] getDeclaredAnnotations(Class<T> annotationClass) {
+        Objects.requireNonNull(annotationClass);
+        // safe because annotationClass is the class for T
+        return (T[])Array.newInstance(annotationClass, 0);
+    }
+
     public Annotation[] getAnnotations() {
         // Since zero-length, don't need defensive clone
         return EMPTY_ANNOTATION_ARRAY;
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/lang/annotation/repeatingAnnotations/RepeatedUnitTest.java	Wed Nov 28 09:21:37 2012 -0800
@@ -0,0 +1,243 @@
+/*
+ * Copyright (c) 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.
+ *
+ * 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     7154390
+ * @summary Unit test for repeated annotation reflection
+ *
+ * @compile RepeatedUnitTest.java subpackage/package-info.java subpackage/Container.java subpackage/Containee.java subpackage/NonRepeated.java subpackage/InheritedContainee.java subpackage/InheritedContainer.java subpackage/InheritedNonRepeated.java
+ * @run main RepeatedUnitTest
+ */
+
+import subpackage.*;
+
+import java.lang.annotation.*;
+import java.lang.reflect.*;
+import java.util.*;
+
+public class RepeatedUnitTest {
+    public static void main(String[] args) throws Exception {
+        // PACKAGE ANNOTATIONS
+        Class c = Class.forName("subpackage.NonRepeated"); // force package "subpackage" load
+        Package p = Package.getPackage("subpackage");
+        packageNonRepeated(p);
+        packageRepeated(p);
+        packageContainer(p);
+
+        // INHERITED/NON-INHERITED ON CLASS
+        inheritedMe1();
+        inheritedMe2();
+        inheritedMe3();
+        inheritedMe4();
+
+        // CONSTRUCTOR
+        checkMultiplier(Me1.class.getConstructor(new Class[0]), 10);
+
+        // FIELD
+        checkMultiplier(Me1.class.getField("foo"), 1);
+
+        // METHOD
+        checkMultiplier(Me1.class.getDeclaredMethod("mee", null), 100);
+
+        // INNER CLASS
+        checkMultiplier(Me1.MiniMee.class, 1000);
+
+        // ENUM ELEMENT
+        checkMultiplier(Me1.E.class.getField("EE"), 10000);
+
+        // ENUM
+        checkMultiplier(Me1.E.class, 100000);
+    }
+
+    static void packageNonRepeated(AnnotatedElement e) {
+        NonRepeated nr = e.getAnnotation(NonRepeated.class);
+        check(nr.value() == 10);
+
+        check(1 == countAnnotation(e, NonRepeated.class));
+
+        nr = e.getAnnotations(NonRepeated.class)[0];
+        check(nr.value() == 10);
+
+        check(1 == containsAnnotationOfType(e.getAnnotations(), NonRepeated.class));
+    }
+
+    static void packageRepeated(AnnotatedElement e) {
+        Containee c = e.getAnnotation(Containee.class);
+        check(c.value() == 1);
+
+        check(2 == countAnnotation(e, Containee.class));
+
+        c = e.getAnnotations(Containee.class)[0];
+        check(c.value() == 1);
+        c = e.getAnnotations(Containee.class)[1];
+        check(c.value() == 2);
+
+        check(2 == containsAnnotationOfType(e.getAnnotations(), Containee.class));
+    }
+
+    static void packageContainer(AnnotatedElement e) {
+        Container cr = e.getAnnotation(Container.class);
+        check(null != cr);
+        check(1 == containsAnnotationOfType(e.getAnnotations(Container.class), Container.class));
+        check(1 == countAnnotation(e, Container.class));
+    }
+
+    static void inheritedMe1() {
+        AnnotatedElement e = Me1.class;
+        check(null == e.getAnnotation(NonRepeated.class));
+        check(e.getAnnotation(InheritedNonRepeated.class).value() == 20);
+        check(0 == countAnnotation(e, Containee.class));
+        check(4 == countAnnotation(e, InheritedContainee.class));
+        check(0 == countAnnotation(e, Container.class));
+        check(1 == countAnnotation(e, InheritedContainer.class));
+    }
+
+    static void inheritedMe2() {
+        AnnotatedElement e = Me2.class;
+        check(e.getAnnotation(NonRepeated.class).value() == 100);
+        check(e.getAnnotation(InheritedNonRepeated.class).value() == 200);
+        check(4 == countAnnotation(e, Containee.class));
+        check(4 == countAnnotation(e, InheritedContainee.class));
+        check(1 == countAnnotation(e, Container.class));
+        check(1 == countAnnotation(e, InheritedContainer.class));
+        check(1 == countAnnotation(e, NonRepeated.class));
+        check(1 == countAnnotation(e, InheritedNonRepeated.class));
+
+        check(e.getAnnotations(Containee.class)[2].value() == 300);
+        check(e.getAnnotations(InheritedContainee.class)[2].value() == 300);
+        check(e.getAnnotations(InheritedNonRepeated.class)[0].value() == 200);
+        check(e.getAnnotations(NonRepeated.class)[0].value() == 100);
+    }
+
+    static void inheritedMe3() {
+        AnnotatedElement e = Me3.class;
+        check(null == e.getAnnotation(NonRepeated.class));
+
+        check(0 == countAnnotation(e, Containee.class));
+        check(4 == countAnnotation(e, InheritedContainee.class));
+        check(0 == countAnnotation(e, Container.class));
+        check(1 == countAnnotation(e, InheritedContainer.class));
+
+        check(e.getAnnotations(InheritedContainee.class)[2].value() == 350);
+        check(e.getAnnotations(InheritedNonRepeated.class)[0].value() == 15);
+    }
+
+    static void inheritedMe4() {
+        AnnotatedElement e = Me4.class;
+        check(e.getAnnotation(NonRepeated.class).value() == 1000);
+        check(e.getAnnotation(InheritedNonRepeated.class).value() == 2000);
+        check(4 == countAnnotation(e, Containee.class));
+        check(4 == countAnnotation(e, InheritedContainee.class));
+        check(1 == countAnnotation(e, Container.class));
+        check(1 == countAnnotation(e, InheritedContainer.class));
+        check(1 == countAnnotation(e, NonRepeated.class));
+        check(1 == countAnnotation(e, InheritedNonRepeated.class));
+
+        check(e.getAnnotations(Containee.class)[2].value() == 3000);
+        check(e.getAnnotations(InheritedContainee.class)[2].value() == 3000);
+        check(e.getAnnotations(InheritedNonRepeated.class)[0].value() == 2000);
+        check(e.getAnnotations(NonRepeated.class)[0].value() == 1000);
+    }
+
+    static void checkMultiplier(AnnotatedElement e, int m) {
+        check(e.getAnnotation(NonRepeated.class).value() == 5 * m);
+
+        check(4 == countAnnotation(e, Containee.class));
+        check(1 == countAnnotation(e, Container.class));
+        check(1 == countAnnotation(e, NonRepeated.class));
+
+        check(e.getAnnotations(Containee.class)[2].value() == 3 * m);
+        check(e.getAnnotations(NonRepeated.class)[0].value() == 5 * m);
+    }
+
+    static void check(Boolean b) {
+        if (!b) throw new RuntimeException();
+    }
+
+    static int countAnnotation(AnnotatedElement e, Class<? extends Annotation> c) {
+        return containsAnnotationOfType(e.getAnnotations(c), c);
+    }
+
+    static <A extends Annotation> int containsAnnotationOfType(A[] l, Class<? extends Annotation> a) {
+        int count = 0;
+        for (Annotation an : l) {
+            if (an.annotationType().equals(a))
+                count++;
+        }
+        return count;
+    }
+}
+
+@NonRepeated @InheritedNonRepeated
+@InheritedContainee(1) @InheritedContainee(2) @InheritedContainee(3) @InheritedContainee(4)
+@Containee(1) @Containee(2) @Containee(3) @Containee(4)
+class Grandma {}
+
+class Mother extends Grandma {}
+
+@NonRepeated(5) @InheritedNonRepeated(15)
+@InheritedContainee(150) @InheritedContainee(250) @InheritedContainee(350) @InheritedContainee(450)
+@Containee(150) @Containee(250) @Containee(350) @Containee(450)
+class Father extends Grandma {}
+
+class Me1 extends Mother {
+
+    @NonRepeated(5)
+    @Containee(1) @Containee(2) @Containee(3) @Containee(4)
+    public String foo = "";
+
+    @NonRepeated(50)
+    @Containee(10) @Containee(20) @Containee(30) @Containee(40)
+    public Me1() {
+    }
+
+    @NonRepeated(500)
+    @Containee(100) @Containee(200) @Containee(300) @Containee(400)
+    public void mee() {
+    }
+
+    @NonRepeated(5000)
+    @Containee(1000) @Containee(2000) @Containee(3000) @Containee(4000)
+    public class MiniMee {}
+
+    @NonRepeated(500000)
+    @Containee(100000) @Containee(200000) @Containee(300000) @Containee(400000)
+    public enum E {
+        @NonRepeated(50000)
+        @Containee(10000) @Containee(20000) @Containee(30000) @Containee(40000)
+        EE(),
+    }
+}
+
+@NonRepeated(100) @InheritedNonRepeated(200)
+@InheritedContainee(100) @InheritedContainee(200) @InheritedContainee(300) @InheritedContainee(400)
+@Containee(100) @Containee(200) @Containee(300) @Containee(400)
+class Me2 extends Mother {}
+
+class Me3 extends Father {}
+
+@NonRepeated(1000) @InheritedNonRepeated(2000)
+@InheritedContainee(1000) @InheritedContainee(2000) @InheritedContainee(3000) @InheritedContainee(4000)
+@Containee(1000) @Containee(2000) @Containee(3000) @Containee(4000)
+class Me4 extends Father {}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/lang/annotation/repeatingAnnotations/subpackage/Containee.java	Wed Nov 28 09:21:37 2012 -0800
@@ -0,0 +1,32 @@
+/*
+ * Copyright (c) 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.
+ *
+ * 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.
+ */
+
+package subpackage;
+
+import java.lang.annotation.*;
+
+@Retention(RetentionPolicy.RUNTIME)
+@ContainedBy(Container.class)
+public @interface Containee {
+    int value();
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/lang/annotation/repeatingAnnotations/subpackage/Container.java	Wed Nov 28 09:21:37 2012 -0800
@@ -0,0 +1,32 @@
+/*
+ * Copyright (c) 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.
+ *
+ * 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.
+ */
+
+package subpackage;
+
+import java.lang.annotation.*;
+
+@Retention(RetentionPolicy.RUNTIME)
+@ContainerFor(Containee.class)
+public @interface Container {
+    Containee[] value();
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/lang/annotation/repeatingAnnotations/subpackage/InheritedContainee.java	Wed Nov 28 09:21:37 2012 -0800
@@ -0,0 +1,33 @@
+/*
+ * Copyright (c) 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.
+ *
+ * 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.
+ */
+
+package subpackage;
+
+import java.lang.annotation.*;
+
+@Inherited
+@Retention(RetentionPolicy.RUNTIME)
+@ContainedBy(InheritedContainer.class)
+public @interface InheritedContainee {
+    int value();
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/lang/annotation/repeatingAnnotations/subpackage/InheritedContainer.java	Wed Nov 28 09:21:37 2012 -0800
@@ -0,0 +1,33 @@
+/*
+ * Copyright (c) 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.
+ *
+ * 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.
+ */
+
+package subpackage;
+
+import java.lang.annotation.*;
+
+@Inherited
+@Retention(RetentionPolicy.RUNTIME)
+@ContainerFor(InheritedContainee.class)
+public @interface InheritedContainer {
+    InheritedContainee[] value();
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/lang/annotation/repeatingAnnotations/subpackage/InheritedNonRepeated.java	Wed Nov 28 09:21:37 2012 -0800
@@ -0,0 +1,31 @@
+/*
+ * Copyright (c) 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.
+ *
+ * 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.
+ */
+package subpackage;
+
+import java.lang.annotation.*;
+
+@Inherited
+@Retention(RetentionPolicy.RUNTIME)
+public @interface InheritedNonRepeated {
+    int value() default 20;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/lang/annotation/repeatingAnnotations/subpackage/NonRepeated.java	Wed Nov 28 09:21:37 2012 -0800
@@ -0,0 +1,30 @@
+/*
+ * Copyright (c) 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.
+ *
+ * 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.
+ */
+package subpackage;
+
+import java.lang.annotation.*;
+
+@Retention(RetentionPolicy.RUNTIME)
+public @interface NonRepeated {
+    int value() default 10;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/lang/annotation/repeatingAnnotations/subpackage/package-info.java	Wed Nov 28 09:21:37 2012 -0800
@@ -0,0 +1,25 @@
+/*
+ * Copyright (c) 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.
+ *
+ * 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.
+ */
+
+@NonRepeated @Containee(1) @Containee(2)
+package subpackage;