8004698: Implement Core Reflection for Type Annotations
authorjfranck
Tue, 29 Jan 2013 10:32:49 +0100
changeset 15510 898d924a7efd
parent 15313 35fafa425a70
child 15511 8f45487ac694
8004698: Implement Core Reflection for Type Annotations Reviewed-by: darcy
jdk/src/share/classes/java/lang/Class.java
jdk/src/share/classes/java/lang/System.java
jdk/src/share/classes/java/lang/reflect/AnnotatedArrayType.java
jdk/src/share/classes/java/lang/reflect/AnnotatedParameterizedType.java
jdk/src/share/classes/java/lang/reflect/AnnotatedType.java
jdk/src/share/classes/java/lang/reflect/AnnotatedTypeVariable.java
jdk/src/share/classes/java/lang/reflect/AnnotatedWildcardType.java
jdk/src/share/classes/java/lang/reflect/Constructor.java
jdk/src/share/classes/java/lang/reflect/Executable.java
jdk/src/share/classes/java/lang/reflect/Field.java
jdk/src/share/classes/java/lang/reflect/Method.java
jdk/src/share/classes/java/lang/reflect/ReflectAccess.java
jdk/src/share/classes/java/lang/reflect/TypeVariable.java
jdk/src/share/classes/sun/misc/JavaLangAccess.java
jdk/src/share/classes/sun/reflect/LangReflectAccess.java
jdk/src/share/classes/sun/reflect/ReflectionFactory.java
jdk/src/share/classes/sun/reflect/annotation/AnnotatedTypeFactory.java
jdk/src/share/classes/sun/reflect/annotation/AnnotationParser.java
jdk/src/share/classes/sun/reflect/annotation/TypeAnnotation.java
jdk/src/share/classes/sun/reflect/annotation/TypeAnnotationParser.java
jdk/src/share/classes/sun/reflect/generics/reflectiveObjects/TypeVariableImpl.java
jdk/src/share/javavm/export/jvm.h
jdk/src/share/native/java/lang/Class.c
jdk/test/java/lang/annotation/TypeAnnotationReflection.java
jdk/test/java/lang/annotation/TypeParamAnnotation.java
--- a/jdk/src/share/classes/java/lang/Class.java	Sat Jan 26 16:57:02 2013 +0000
+++ b/jdk/src/share/classes/java/lang/Class.java	Tue Jan 29 10:32:49 2013 +0100
@@ -29,12 +29,14 @@
 import java.lang.reflect.GenericArrayType;
 import java.lang.reflect.Member;
 import java.lang.reflect.Field;
+import java.lang.reflect.Executable;
 import java.lang.reflect.Method;
 import java.lang.reflect.Constructor;
 import java.lang.reflect.Modifier;
 import java.lang.reflect.Type;
 import java.lang.reflect.TypeVariable;
 import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.AnnotatedType;
 import java.lang.ref.SoftReference;
 import java.io.InputStream;
 import java.io.ObjectStreamField;
@@ -2325,6 +2327,11 @@
 
     // Annotations handling
     private native byte[] getRawAnnotations();
+    // Since 1.8
+    native byte[] getRawTypeAnnotations();
+    static byte[] getExecutableTypeAnnotationBytes(Executable ex) {
+        return getReflectionFactory().getExecutableTypeAnnotationBytes(ex);
+    }
 
     native ConstantPool getConstantPool();
 
@@ -3196,4 +3203,53 @@
      * Maintained by the ClassValue class.
      */
     transient ClassValue.ClassValueMap classValueMap;
+
+    /**
+     * Returns an AnnotatedType object that represents the use of a type to specify
+     * the superclass of the entity represented by this Class. (The <em>use</em> of type
+     * Foo to specify the superclass in '... extends Foo' is distinct from the
+     * <em>declaration</em> of type Foo.)
+     *
+     * If this Class represents a class type whose declaration does not explicitly
+     * indicate an annotated superclass, the return value is null.
+     *
+     * If this Class represents either the Object class, an interface type, an
+     * array type, a primitive type, or void, the return value is null.
+     *
+     * @since 1.8
+     */
+    public AnnotatedType getAnnotatedSuperclass() {
+         return TypeAnnotationParser.buildAnnotatedSuperclass(getRawTypeAnnotations(), getConstantPool(), this);
 }
+
+    /**
+     * Returns an array of AnnotatedType objects that represent the use of types to
+     * specify superinterfaces of the entity represented by this Class. (The <em>use</em>
+     * of type Foo to specify a superinterface in '... implements Foo' is
+     * distinct from the <em>declaration</em> of type Foo.)
+     *
+     * If this Class represents a class, the return value is an array
+     * containing objects representing the uses of interface types to specify
+     * interfaces implemented by the class. The order of the objects in the
+     * array corresponds to the order of the interface types used in the
+     * 'implements' clause of the declaration of this Class.
+     *
+     * If this Class represents an interface, the return value is an array
+     * containing objects representing the uses of interface types to specify
+     * interfaces directly extended by the interface. The order of the objects in
+     * the array corresponds to the order of the interface types used in the
+     * 'extends' clause of the declaration of this Class.
+     *
+     * If this Class represents a class or interface whose declaration does not
+     * explicitly indicate any annotated superinterfaces, the return value is an
+     * array of length 0.
+     *
+     * If this Class represents either the Object class, an array type, a
+     * primitive type, or void, the return value is an array of length 0.
+     *
+     * @since 1.8
+     */
+    public AnnotatedType[] getAnnotatedInterfaces() {
+         return TypeAnnotationParser.buildAnnotatedInterfaces(getRawTypeAnnotations(), getConstantPool(), this);
+    }
+}
--- a/jdk/src/share/classes/java/lang/System.java	Sat Jan 26 16:57:02 2013 +0000
+++ b/jdk/src/share/classes/java/lang/System.java	Tue Jan 29 10:32:49 2013 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1994, 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1994, 2013, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -26,6 +26,7 @@
 
 import java.io.*;
 import java.lang.annotation.Annotation;
+import java.lang.reflect.Executable;
 import java.util.Properties;
 import java.util.PropertyPermission;
 import java.util.StringTokenizer;
@@ -1199,6 +1200,12 @@
             public <A extends Annotation> A getDirectDeclaredAnnotation(Class<?> klass, Class<A> anno) {
                 return klass.getDirectDeclaredAnnotation(anno);
             }
+            public byte[] getRawClassTypeAnnotations(Class<?> klass) {
+                return klass.getRawTypeAnnotations();
+            }
+            public byte[] getRawExecutableTypeAnnotations(Executable executable) {
+                return Class.getExecutableTypeAnnotationBytes(executable);
+            }
             public <E extends Enum<E>>
                     E[] getEnumConstantsShared(Class<E> klass) {
                 return klass.getEnumConstantsShared();
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/share/classes/java/lang/reflect/AnnotatedArrayType.java	Tue Jan 29 10:32:49 2013 +0100
@@ -0,0 +1,43 @@
+/*
+ * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * 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.reflect;
+
+
+/**
+ * AnnotatedArrayType represents the use of an array type, whose component
+ * type may itself represent the annotated use of a type.
+ *
+ * @since 1.8
+ */
+public interface AnnotatedArrayType extends AnnotatedType {
+
+    /**
+     * Returns the annotated generic component type of this array type.
+     *
+     * @return the annotated generic component type of this array type
+     */
+    AnnotatedType  getAnnotatedGenericComponentType();
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/share/classes/java/lang/reflect/AnnotatedParameterizedType.java	Tue Jan 29 10:32:49 2013 +0100
@@ -0,0 +1,42 @@
+/*
+ * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * 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.reflect;
+
+/**
+ * AnnotatedParameterizedType represents the use of a parameterized type,
+ * whose type arguments may themselves represent annotated uses of types.
+ *
+ * @since 1.8
+ */
+public interface AnnotatedParameterizedType extends AnnotatedType {
+
+    /**
+     * Returns the annotated actual type arguments of this parameterized type.
+     *
+     * @return the annotated actual type arguments of this parameterized type
+     */
+    AnnotatedType[] getAnnotatedActualTypeArguments();
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/share/classes/java/lang/reflect/AnnotatedType.java	Tue Jan 29 10:32:49 2013 +0100
@@ -0,0 +1,44 @@
+/*
+ * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * 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.reflect;
+
+/**
+ * AnnotatedType represents the annotated use of a type in the program
+ * currently running in this VM. The use may be of any type in the Java
+ * programming language, including an array type, a parameterized type, a type
+ * variable, or a wildcard type.
+ *
+ * @since 1.8
+ */
+public interface AnnotatedType extends AnnotatedElement {
+
+    /**
+     * Returns the underlying type that this annotated type represents.
+     *
+     * @return the type this annotated type represents
+     */
+    public Type getType();
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/share/classes/java/lang/reflect/AnnotatedTypeVariable.java	Tue Jan 29 10:32:49 2013 +0100
@@ -0,0 +1,43 @@
+/*
+ * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * 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.reflect;
+
+/**
+ * AnnotatedTypeVariable represents the use of a type variable, whose
+ * declaration may have bounds which themselves represent annotated uses of
+ * types.
+ *
+ * @since 1.8
+ */
+public interface AnnotatedTypeVariable extends AnnotatedType {
+
+    /**
+     * Returns the annotated bounds of this type variable.
+     *
+     * @return the annotated bounds of this type variable
+     */
+    AnnotatedType[] getAnnotatedBounds();
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/share/classes/java/lang/reflect/AnnotatedWildcardType.java	Tue Jan 29 10:32:49 2013 +0100
@@ -0,0 +1,49 @@
+/*
+ * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * 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.reflect;
+
+/**
+ * AnnotatedWildcardType represents the use of a wildcard type argument, whose
+ * upper or lower bounds may themselves represent annotated uses of types.
+ *
+ * @since 1.8
+ */
+public interface AnnotatedWildcardType extends AnnotatedType {
+
+    /**
+     * Returns the annotated lower bounds of this wildcard type.
+     *
+     * @return the annotated lower bounds of this wildcard type
+     */
+    AnnotatedType[] getAnnotatedLowerBounds();
+
+    /**
+     * Returns the annotated upper bounds of this wildcard type.
+     *
+     * @return the annotated upper bounds of this wildcard type
+     */
+    AnnotatedType[] getAnnotatedUpperBounds();
+}
--- a/jdk/src/share/classes/java/lang/reflect/Constructor.java	Sat Jan 26 16:57:02 2013 +0000
+++ b/jdk/src/share/classes/java/lang/reflect/Constructor.java	Tue Jan 29 10:32:49 2013 +0100
@@ -154,6 +154,10 @@
     byte[] getAnnotationBytes() {
         return annotations;
     }
+    @Override
+    byte[] getTypeAnnotationBytes() {
+        return typeAnnotations;
+    }
 
     /**
      * {@inheritDoc}
@@ -523,4 +527,12 @@
             }
         }
     }
+
+    /**
+     * {@inheritDoc}
+     * @since 1.8
+     */
+    public AnnotatedType getAnnotatedReturnType() {
+        return getAnnotatedReturnType0(getDeclaringClass());
+    }
 }
--- a/jdk/src/share/classes/java/lang/reflect/Executable.java	Sat Jan 26 16:57:02 2013 +0000
+++ b/jdk/src/share/classes/java/lang/reflect/Executable.java	Tue Jan 29 10:32:49 2013 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 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
@@ -31,6 +31,8 @@
 import java.util.Objects;
 import sun.reflect.annotation.AnnotationParser;
 import sun.reflect.annotation.AnnotationSupport;
+import sun.reflect.annotation.TypeAnnotationParser;
+import sun.reflect.annotation.TypeAnnotation;
 import sun.reflect.generics.repository.ConstructorRepository;
 
 /**
@@ -50,6 +52,7 @@
      * Accessor method to allow code sharing
      */
     abstract byte[] getAnnotationBytes();
+    abstract byte[] getTypeAnnotationBytes();
 
     /**
      * Does the Executable have generic information.
@@ -470,4 +473,86 @@
         return declaredAnnotations;
     }
 
+
+    /* Helper for subclasses of Executable.
+     *
+     * Returns an AnnotatedType object that represents the use of a type to
+     * specify the return type of the method/constructor represented by this
+     * Executable.
+     *
+     * @since 1.8
+     */
+    AnnotatedType getAnnotatedReturnType0(Type returnType) {
+        return TypeAnnotationParser.buildAnnotatedType(getTypeAnnotationBytes(),
+                                                       sun.misc.SharedSecrets.getJavaLangAccess().
+                                                           getConstantPool(getDeclaringClass()),
+                                                       this,
+                                                       getDeclaringClass(),
+                                                       returnType,
+                                                       TypeAnnotation.TypeAnnotationTarget.METHOD_RETURN_TYPE);
+    }
+
+    /**
+     * Returns an AnnotatedType object that represents the use of a type to
+     * specify the receiver type of the method/constructor represented by this
+     * Executable. The receiver type of a method/constructor is available only
+     * if the method/constructor declares a formal parameter called 'this'.
+     *
+     * Returns null if this Executable represents a constructor or instance
+     * method that either declares no formal parameter called 'this', or
+     * declares a formal parameter called 'this' with no annotations on its
+     * type.
+     *
+     * Returns null if this Executable represents a static method.
+     *
+     * @since 1.8
+     */
+    public AnnotatedType getAnnotatedReceiverType() {
+        return TypeAnnotationParser.buildAnnotatedType(getTypeAnnotationBytes(),
+                                                       sun.misc.SharedSecrets.getJavaLangAccess().
+                                                           getConstantPool(getDeclaringClass()),
+                                                       this,
+                                                       getDeclaringClass(),
+                                                       getDeclaringClass(),
+                                                       TypeAnnotation.TypeAnnotationTarget.METHOD_RECEIVER_TYPE);
+    }
+
+    /**
+     * Returns an array of AnnotatedType objects that represent the use of
+     * types to specify formal parameter types of the method/constructor
+     * represented by this Executable. The order of the objects in the array
+     * corresponds to the order of the formal parameter types in the
+     * declaration of the method/constructor.
+     *
+     * Returns an array of length 0 if the method/constructor declares no
+     * parameters.
+     *
+     * @since 1.8
+     */
+    public AnnotatedType[] getAnnotatedParameterTypes() {
+        throw new UnsupportedOperationException("Not yet");
+    }
+
+    /**
+     * Returns an array of AnnotatedType objects that represent the use of
+     * types to specify the declared exceptions of the method/constructor
+     * represented by this Executable. The order of the objects in the array
+     * corresponds to the order of the exception types in the declaration of
+     * the method/constructor.
+     *
+     * Returns an array of length 0 if the method/constructor declares no
+     * exceptions.
+     *
+     * @since 1.8
+     */
+    public AnnotatedType[] getAnnotatedExceptionTypes() {
+        return TypeAnnotationParser.buildAnnotatedTypes(getTypeAnnotationBytes(),
+                                                        sun.misc.SharedSecrets.getJavaLangAccess().
+                                                            getConstantPool(getDeclaringClass()),
+                                                        this,
+                                                        getDeclaringClass(),
+                                                        getGenericExceptionTypes(),
+                                                        TypeAnnotation.TypeAnnotationTarget.THROWS);
+    }
+
 }
--- a/jdk/src/share/classes/java/lang/reflect/Field.java	Sat Jan 26 16:57:02 2013 +0000
+++ b/jdk/src/share/classes/java/lang/reflect/Field.java	Tue Jan 29 10:32:49 2013 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1996, 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1996, 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
@@ -36,7 +36,8 @@
 import java.util.Objects;
 import sun.reflect.annotation.AnnotationParser;
 import sun.reflect.annotation.AnnotationSupport;
-
+import sun.reflect.annotation.TypeAnnotation;
+import sun.reflect.annotation.TypeAnnotationParser;
 
 /**
  * A {@code Field} provides information about, and dynamic access to, a
@@ -1053,4 +1054,20 @@
         }
         return declaredAnnotations;
     }
+
+    /**
+     * Returns an AnnotatedType object that represents the use of a type to specify
+     * the declared type of the field represented by this Field.
+     *
+     * @since 1.8
+     */
+    public AnnotatedType getAnnotatedType() {
+        return TypeAnnotationParser.buildAnnotatedType(typeAnnotations,
+                                                       sun.misc.SharedSecrets.getJavaLangAccess().
+                                                           getConstantPool(getDeclaringClass()),
+                                                       this,
+                                                       getDeclaringClass(),
+                                                       getGenericType(),
+                                                       TypeAnnotation.TypeAnnotationTarget.FIELD_TYPE);
 }
+}
--- a/jdk/src/share/classes/java/lang/reflect/Method.java	Sat Jan 26 16:57:02 2013 +0000
+++ b/jdk/src/share/classes/java/lang/reflect/Method.java	Tue Jan 29 10:32:49 2013 +0100
@@ -165,6 +165,10 @@
     byte[] getAnnotationBytes() {
         return annotations;
     }
+    @Override
+    byte[] getTypeAnnotationBytes() {
+        return typeAnnotations;
+    }
 
     /**
      * {@inheritDoc}
@@ -621,6 +625,14 @@
         return sharedGetParameterAnnotations(parameterTypes, parameterAnnotations);
     }
 
+    /**
+     * {@inheritDoc}
+     * @since 1.8
+     */
+    public AnnotatedType getAnnotatedReturnType() {
+        return getAnnotatedReturnType0(getGenericReturnType());
+    }
+
     @Override
     void handleParameterNumberMismatch(int resultLength, int numParameters) {
         throw new AnnotationFormatError("Parameter annotations don't match number of parameters");
--- a/jdk/src/share/classes/java/lang/reflect/ReflectAccess.java	Sat Jan 26 16:57:02 2013 +0000
+++ b/jdk/src/share/classes/java/lang/reflect/ReflectAccess.java	Tue Jan 29 10:32:49 2013 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2001, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2001, 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
@@ -128,6 +128,10 @@
         return c.getRawParameterAnnotations();
     }
 
+    public byte[] getExecutableTypeAnnotationBytes(Executable ex) {
+        return ex.getTypeAnnotationBytes();
+    }
+
     //
     // Copying routines, needed to quickly fabricate new Field,
     // Method, and Constructor objects from templates
--- a/jdk/src/share/classes/java/lang/reflect/TypeVariable.java	Sat Jan 26 16:57:02 2013 +0000
+++ b/jdk/src/share/classes/java/lang/reflect/TypeVariable.java	Tue Jan 29 10:32:49 2013 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2003, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 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
@@ -86,4 +86,16 @@
      * @return the name of this type variable, as it appears in the source code
      */
     String getName();
+
+    /**
+     * Returns an array of AnnotatedType objects that represent the use of
+     * types to denote the upper bounds of the type parameter represented by
+     * this TypeVariable. The order of the objects in the array corresponds to
+     * the order of the bounds in the declaration of the type parameter.
+     *
+     * Returns an array of length 0 if the type parameter declares no bounds.
+     *
+     * @since 1.8
+     */
+     AnnotatedType[] getAnnotatedBounds();
 }
--- a/jdk/src/share/classes/sun/misc/JavaLangAccess.java	Sat Jan 26 16:57:02 2013 +0000
+++ b/jdk/src/share/classes/sun/misc/JavaLangAccess.java	Tue Jan 29 10:32:49 2013 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2003, 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 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
@@ -26,6 +26,7 @@
 package sun.misc;
 
 import java.lang.annotation.Annotation;
+import java.lang.reflect.Executable;
 import sun.reflect.ConstantPool;
 import sun.reflect.annotation.AnnotationType;
 import sun.nio.ch.Interruptible;
@@ -47,6 +48,18 @@
     AnnotationType getAnnotationType(Class<?> klass);
 
     /**
+     * Get the array of bytes that is the class-file representation
+     * of this Class' type annotations.
+     */
+    byte[] getRawClassTypeAnnotations(Class<?> klass);
+
+    /**
+     * Get the array of bytes that is the class-file representation
+     * of this Executable's type annotations.
+     */
+    byte[] getRawExecutableTypeAnnotations(Executable executable);
+
+    /**
      * 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.
--- a/jdk/src/share/classes/sun/reflect/LangReflectAccess.java	Sat Jan 26 16:57:02 2013 +0000
+++ b/jdk/src/share/classes/sun/reflect/LangReflectAccess.java	Tue Jan 29 10:32:49 2013 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2001, 2004, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2001, 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
@@ -81,6 +81,9 @@
     public void setConstructorAccessor(Constructor<?> c,
                                        ConstructorAccessor accessor);
 
+    /** Gets the byte[] that encodes TypeAnnotations on an Executable. */
+    public byte[] getExecutableTypeAnnotationBytes(Executable ex);
+
     /** Gets the "slot" field from a Constructor (used for serialization) */
     public int getConstructorSlot(Constructor<?> c);
 
--- a/jdk/src/share/classes/sun/reflect/ReflectionFactory.java	Sat Jan 26 16:57:02 2013 +0000
+++ b/jdk/src/share/classes/sun/reflect/ReflectionFactory.java	Tue Jan 29 10:32:49 2013 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2001, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2001, 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
@@ -26,6 +26,7 @@
 package sun.reflect;
 
 import java.lang.reflect.Field;
+import java.lang.reflect.Executable;
 import java.lang.reflect.Method;
 import java.lang.reflect.Constructor;
 import java.lang.reflect.Modifier;
@@ -314,6 +315,12 @@
         return langReflectAccess().copyConstructor(arg);
     }
 
+    /** Gets the byte[] that encodes TypeAnnotations on an executable.
+     */
+    public byte[] getExecutableTypeAnnotationBytes(Executable ex) {
+        return langReflectAccess().getExecutableTypeAnnotationBytes(ex);
+    }
+
     //--------------------------------------------------------------------------
     //
     // Routines used by serialization
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/share/classes/sun/reflect/annotation/AnnotatedTypeFactory.java	Tue Jan 29 10:32:49 2013 +0100
@@ -0,0 +1,320 @@
+/*
+ * 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.  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.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+import java.util.Map;
+
+import static sun.reflect.annotation.TypeAnnotation.*;
+
+public class AnnotatedTypeFactory {
+    /**
+     * Create an AnnotatedType.
+     *
+     * @param type the type this AnnotatedType corresponds to
+     * @param currentLoc the location this AnnotatedType corresponds to
+     * @param actualTypeAnnos the type annotations this AnnotatedType has
+     * @param allOnSameTarget all type annotation on the same TypeAnnotationTarget
+     *                          as the AnnotatedType being built
+     * @param decl the declaration having the type use this AnnotatedType
+     *                          corresponds to
+     */
+    public static AnnotatedType buildAnnotatedType(Type type,
+                                                   LocationInfo currentLoc,
+                                                   TypeAnnotation[] actualTypeAnnos,
+                                                   TypeAnnotation[] allOnSameTarget,
+                                                   AnnotatedElement decl) {
+        if (type == null) {
+            return EMPTY_ANNOTATED_TYPE;
+        }
+        if (isArray(type))
+            return new AnnotatedArrayTypeImpl(type,
+                    currentLoc,
+                    actualTypeAnnos,
+                    allOnSameTarget,
+                    decl);
+        if (type instanceof Class) {
+            return new AnnotatedTypeBaseImpl(type,
+                    addNesting(type, currentLoc),
+                    actualTypeAnnos,
+                    allOnSameTarget,
+                    decl);
+        } else if (type instanceof TypeVariable) {
+            return new AnnotatedTypeVariableImpl((TypeVariable)type,
+                    currentLoc,
+                    actualTypeAnnos,
+                    allOnSameTarget,
+                    decl);
+        } else if (type instanceof ParameterizedType) {
+            return new AnnotatedParameterizedTypeImpl((ParameterizedType)type,
+                    addNesting(type, currentLoc),
+                    actualTypeAnnos,
+                    allOnSameTarget,
+                    decl);
+        } else if (type instanceof WildcardType) {
+            return new AnnotatedWildcardTypeImpl((WildcardType) type,
+                    currentLoc,
+                    actualTypeAnnos,
+                    allOnSameTarget,
+                    decl);
+        }
+        throw new AssertionError("Unknown instance of Type: " + type + "\nThis should not happen.");
+    }
+
+    private static LocationInfo addNesting(Type type, LocationInfo addTo) {
+        if (isArray(type))
+            return addTo;
+        if (type instanceof Class) {
+            Class<?> clz = (Class)type;
+            if (clz.getEnclosingClass() == null)
+                return addTo;
+            return addNesting(clz.getEnclosingClass(), addTo.pushInner());
+        } else if (type instanceof ParameterizedType) {
+            ParameterizedType t = (ParameterizedType)type;
+            if (t.getOwnerType() == null)
+                return addTo;
+            return addNesting(t.getOwnerType(), addTo.pushInner());
+        }
+        return addTo;
+    }
+
+    private static boolean isArray(Type t) {
+        if (t instanceof Class) {
+            Class<?> c = (Class)t;
+            if (c.isArray())
+                return true;
+        } else if (t instanceof GenericArrayType) {
+            return true;
+        }
+        return false;
+    }
+
+    static final AnnotatedType EMPTY_ANNOTATED_TYPE = new AnnotatedTypeBaseImpl(null, LocationInfo.BASE_LOCATION,
+                                                            new TypeAnnotation[0], new TypeAnnotation[0], null);
+
+    private static class AnnotatedTypeBaseImpl implements AnnotatedType {
+        private final Type type;
+        private final AnnotatedElement decl;
+        private final LocationInfo location;
+        private final TypeAnnotation[] allOnSameTargetTypeAnnotations;
+        private final Map<Class <? extends Annotation>, Annotation> annotations;
+
+        AnnotatedTypeBaseImpl(Type type, LocationInfo location,
+                TypeAnnotation[] actualTypeAnnotations, TypeAnnotation[] allOnSameTargetTypeAnnotations,
+                AnnotatedElement decl) {
+            this.type = type;
+            this.decl = decl;
+            this.location = location;
+            this.allOnSameTargetTypeAnnotations = allOnSameTargetTypeAnnotations;
+            this.annotations = TypeAnnotationParser.mapTypeAnnotations(location.filter(actualTypeAnnotations));
+        }
+
+        // AnnotatedElement
+        @Override
+        public final boolean isAnnotationPresent(Class<? extends Annotation> annotation) {
+            return annotations.get(annotation) != null;
+        }
+
+        @Override
+        public final Annotation[] getAnnotations() {
+            return getDeclaredAnnotations();
+        }
+
+        @Override
+        public final <T extends Annotation> T getAnnotation(Class<T> annotation) {
+            return getDeclaredAnnotation(annotation);
+        }
+
+        @Override
+        public final <T extends Annotation> T[] getAnnotations(Class<T> annotation) {
+            return getDeclaredAnnotations(annotation);
+        }
+
+        @Override
+        public Annotation[] getDeclaredAnnotations() {
+            return annotations.values().toArray(new Annotation[0]);
+        }
+
+        @Override
+        @SuppressWarnings("unchecked")
+        public <T extends Annotation> T getDeclaredAnnotation(Class<T> annotation) {
+            return (T)annotations.get(annotation);
+        }
+
+        @Override
+        public <T extends Annotation> T[] getDeclaredAnnotations(Class<T> annotation) {
+            return AnnotationSupport.getMultipleAnnotations(annotations, annotation);
+        }
+
+        // AnnotatedType
+        @Override
+        public Type getType() {
+            return type;
+        }
+
+        // Implementation details
+        LocationInfo getLocation() {
+            return location;
+        }
+        TypeAnnotation[] getTypeAnnotations() {
+            return allOnSameTargetTypeAnnotations;
+        }
+        AnnotatedElement getDecl() {
+            return decl;
+        }
+    }
+
+    private static class AnnotatedArrayTypeImpl extends AnnotatedTypeBaseImpl implements AnnotatedArrayType {
+        AnnotatedArrayTypeImpl(Type type, LocationInfo location,
+                TypeAnnotation[] actualTypeAnnotations, TypeAnnotation[] allOnSameTargetTypeAnnotations,
+                AnnotatedElement decl) {
+            super(type, location, actualTypeAnnotations, allOnSameTargetTypeAnnotations, decl);
+        }
+
+        @Override
+        public AnnotatedType getAnnotatedGenericComponentType() {
+            return AnnotatedTypeFactory.buildAnnotatedType(getComponentType(),
+                                                           getLocation().pushArray(),
+                                                           getTypeAnnotations(),
+                                                           getTypeAnnotations(),
+                                                           getDecl());
+        }
+
+        private Type getComponentType() {
+            Type t = getType();
+            if (t instanceof Class) {
+                Class<?> c = (Class)t;
+                return c.getComponentType();
+            }
+            return ((GenericArrayType)t).getGenericComponentType();
+        }
+    }
+
+    private static class AnnotatedTypeVariableImpl extends AnnotatedTypeBaseImpl implements AnnotatedTypeVariable {
+        AnnotatedTypeVariableImpl(TypeVariable<?> type, LocationInfo location,
+                TypeAnnotation[] actualTypeAnnotations, TypeAnnotation[] allOnSameTargetTypeAnnotations,
+                AnnotatedElement decl) {
+            super(type, location, actualTypeAnnotations, allOnSameTargetTypeAnnotations, decl);
+        }
+
+        @Override
+        public AnnotatedType[] getAnnotatedBounds() {
+            return getTypeVariable().getAnnotatedBounds();
+        }
+
+        private TypeVariable<?> getTypeVariable() {
+            return (TypeVariable)getType();
+        }
+    }
+
+    private static class AnnotatedParameterizedTypeImpl extends AnnotatedTypeBaseImpl implements AnnotatedParameterizedType {
+        AnnotatedParameterizedTypeImpl(ParameterizedType type, LocationInfo location,
+                TypeAnnotation[] actualTypeAnnotations, TypeAnnotation[] allOnSameTargetTypeAnnotations,
+                AnnotatedElement decl) {
+            super(type, location, actualTypeAnnotations, allOnSameTargetTypeAnnotations, decl);
+        }
+
+        @Override
+        public AnnotatedType[] getAnnotatedActualTypeArguments() {
+            Type[] arguments = getParameterizedType().getActualTypeArguments();
+            AnnotatedType[] res = new AnnotatedType[arguments.length];
+            Arrays.fill(res, EMPTY_ANNOTATED_TYPE);
+            int initialCapacity = getTypeAnnotations().length;
+            for (int i = 0; i < res.length; i++) {
+                List<TypeAnnotation> l = new ArrayList<>(initialCapacity);
+                LocationInfo newLoc = getLocation().pushTypeArg((byte)i);
+                for (TypeAnnotation t : getTypeAnnotations())
+                    if (t.getLocationInfo().isSameLocationInfo(newLoc))
+                        l.add(t);
+                res[i] = buildAnnotatedType(arguments[i],
+                                            newLoc,
+                                            l.toArray(new TypeAnnotation[0]),
+                                            getTypeAnnotations(),
+                                            getDecl());
+            }
+            return res;
+        }
+
+        private ParameterizedType getParameterizedType() {
+            return (ParameterizedType)getType();
+        }
+    }
+
+    private static class AnnotatedWildcardTypeImpl extends AnnotatedTypeBaseImpl implements AnnotatedWildcardType {
+        private final boolean hasUpperBounds;
+        AnnotatedWildcardTypeImpl(WildcardType type, LocationInfo location,
+                TypeAnnotation[] actualTypeAnnotations, TypeAnnotation[] allOnSameTargetTypeAnnotations,
+                AnnotatedElement decl) {
+            super(type, location, actualTypeAnnotations, allOnSameTargetTypeAnnotations, decl);
+            hasUpperBounds = (type.getLowerBounds().length == 0);
+        }
+
+        @Override
+        public AnnotatedType[] getAnnotatedUpperBounds() {
+            if (!hasUpperBounds())
+                return new AnnotatedType[0];
+            return getAnnotatedBounds(getWildcardType().getUpperBounds());
+        }
+
+        @Override
+        public AnnotatedType[] getAnnotatedLowerBounds() {
+            if (hasUpperBounds)
+                return new AnnotatedType[0];
+            return getAnnotatedBounds(getWildcardType().getLowerBounds());
+        }
+
+        private AnnotatedType[] getAnnotatedBounds(Type[] bounds) {
+            AnnotatedType[] res = new AnnotatedType[bounds.length];
+            Arrays.fill(res, EMPTY_ANNOTATED_TYPE);
+            LocationInfo newLoc = getLocation().pushWildcard();
+            int initialCapacity = getTypeAnnotations().length;
+            for (int i = 0; i < res.length; i++) {
+                List<TypeAnnotation> l = new ArrayList<>(initialCapacity);
+                for (TypeAnnotation t : getTypeAnnotations())
+                    if (t.getLocationInfo().isSameLocationInfo(newLoc))
+                        l.add(t);
+                res[i] = buildAnnotatedType(bounds[i],
+                                            newLoc,
+                                            l.toArray(new TypeAnnotation[0]),
+                                            getTypeAnnotations(),
+                                            getDecl());
+            }
+            return res;
+        }
+
+        private WildcardType getWildcardType() {
+            return (WildcardType)getType();
+        }
+
+        private boolean hasUpperBounds() {
+            return hasUpperBounds;
+        }
+    }
+}
--- a/jdk/src/share/classes/sun/reflect/annotation/AnnotationParser.java	Sat Jan 26 16:57:02 2013 +0000
+++ b/jdk/src/share/classes/sun/reflect/annotation/AnnotationParser.java	Tue Jan 29 10:32:49 2013 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2003, 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 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
@@ -188,7 +188,7 @@
      * available at runtime
      */
     @SuppressWarnings("unchecked")
-    private static Annotation parseAnnotation(ByteBuffer buf,
+    static Annotation parseAnnotation(ByteBuffer buf,
                                               ConstantPool constPool,
                                               Class<?> container,
                                               boolean exceptionOnMissingAnnotationClass) {
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/share/classes/sun/reflect/annotation/TypeAnnotation.java	Tue Jan 29 10:32:49 2013 +0100
@@ -0,0 +1,227 @@
+/*
+ * 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.  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.Annotation;
+import java.lang.annotation.AnnotationFormatError;
+import java.lang.reflect.AnnotatedElement;
+import java.nio.ByteBuffer;
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * A TypeAnnotation contains all the information needed to transform type
+ * annotations on declarations in the class file to actual Annotations in
+ * AnnotatedType instances.
+ *
+ * TypeAnnotaions contain a base Annotation, location info (which lets you
+ * distinguish between '@A Inner.@B Outer' in for example nested types),
+ * target info and the declaration the TypeAnnotaiton was parsed from.
+ */
+public class TypeAnnotation {
+    private final TypeAnnotationTargetInfo targetInfo;
+    private final LocationInfo loc;
+    private final Annotation annotation;
+    private final AnnotatedElement baseDeclaration;
+
+    public TypeAnnotation(TypeAnnotationTargetInfo targetInfo,
+                          LocationInfo loc,
+                          Annotation annotation,
+                          AnnotatedElement baseDeclaration) {
+        this.targetInfo = targetInfo;
+        this.loc = loc;
+        this.annotation = annotation;
+        this.baseDeclaration = baseDeclaration;
+    }
+
+    public TypeAnnotationTargetInfo getTargetInfo() {
+        return targetInfo;
+    }
+    public Annotation getAnnotation() {
+        return annotation;
+    }
+    public AnnotatedElement getBaseDeclaration() {
+        return baseDeclaration;
+    }
+    public LocationInfo getLocationInfo() {
+        return loc;
+    }
+
+    public static List<TypeAnnotation> filter(TypeAnnotation[] typeAnnotations,
+                                              TypeAnnotationTarget predicate) {
+        ArrayList<TypeAnnotation> typeAnnos = new ArrayList<>(typeAnnotations.length);
+        for (TypeAnnotation t : typeAnnotations)
+            if (t.getTargetInfo().getTarget() == predicate)
+                typeAnnos.add(t);
+        typeAnnos.trimToSize();
+        return typeAnnos;
+    }
+
+    public static enum TypeAnnotationTarget {
+        CLASS_TYPE_PARAMETER,
+        METHOD_TYPE_PARAMETER,
+        CLASS_EXTENDS,
+        CLASS_IMPLEMENTS,
+        CLASS_PARAMETER_BOUND,
+        METHOD_PARAMETER_BOUND,
+        METHOD_RETURN_TYPE,
+        METHOD_RECEIVER_TYPE,
+        FIELD_TYPE,
+        THROWS;
+    }
+    public static class TypeAnnotationTargetInfo {
+        private final TypeAnnotationTarget target;
+        private final int count;
+        private final int secondaryIndex;
+        private static final int UNUSED_INDEX = -2; // this is not a valid index in the 308 spec
+
+        public TypeAnnotationTargetInfo(TypeAnnotationTarget target) {
+            this(target, UNUSED_INDEX, UNUSED_INDEX);
+        }
+
+        public TypeAnnotationTargetInfo(TypeAnnotationTarget target,
+                                        int count) {
+            this(target, count, UNUSED_INDEX);
+        }
+
+        public TypeAnnotationTargetInfo(TypeAnnotationTarget target,
+                                        int count,
+                                        int secondaryIndex) {
+            this.target = target;
+            this.count = count;
+            this.secondaryIndex = secondaryIndex;
+        }
+
+        public TypeAnnotationTarget getTarget() {
+            return target;
+        }
+        public int getCount() {
+            return count;
+        }
+        public int getSecondaryIndex() {
+            return secondaryIndex;
+        }
+
+        @Override
+        public String toString() {
+            return "" + target + ": " + count + ", " + secondaryIndex;
+        }
+    }
+
+    public static class LocationInfo {
+        private final int depth;
+        private final Location[] locations;
+
+        private LocationInfo() {
+            this(0, new Location[0]);
+        }
+        private LocationInfo(int depth, Location[] locations) {
+            this.depth = depth;
+            this.locations = locations;
+        }
+
+        public static final LocationInfo BASE_LOCATION = new LocationInfo();
+
+        public static LocationInfo parseLocationInfo(ByteBuffer buf) {
+            int depth = buf.get();
+            if (depth == 0)
+                return BASE_LOCATION;
+            Location[] locations = new Location[depth];
+            for (int i = 0; i < depth; i++) {
+                byte tag = buf.get();
+                byte index = buf.get();
+                if (!(tag == 0 || tag == 1 | tag == 2 || tag == 3))
+                    throw new AnnotationFormatError("Bad Location encoding in Type Annotation");
+                if (tag != 3 && index != 0)
+                    throw new AnnotationFormatError("Bad Location encoding in Type Annotation");
+                locations[i] = new Location(tag, index);
+            }
+            return new LocationInfo(depth, locations);
+        }
+
+        public LocationInfo pushArray() {
+            return pushLocation((byte)0, (byte)0);
+        }
+
+        public LocationInfo pushInner() {
+            return pushLocation((byte)1, (byte)0);
+        }
+
+        public LocationInfo pushWildcard() {
+            return pushLocation((byte) 2, (byte) 0);
+        }
+
+        public LocationInfo pushTypeArg(byte index) {
+            return pushLocation((byte) 3, index);
+        }
+
+        public LocationInfo pushLocation(byte tag, byte index) {
+            int newDepth = this.depth + 1;
+            Location[] res = new Location[newDepth];
+            System.arraycopy(this.locations, 0, res, 0, depth);
+            res[newDepth - 1] = new Location(tag, index);
+            return new LocationInfo(newDepth, res);
+        }
+
+        public TypeAnnotation[] filter(TypeAnnotation[] ta) {
+            ArrayList<TypeAnnotation> l = new ArrayList<>(ta.length);
+            for (TypeAnnotation t : ta) {
+                if (isSameLocationInfo(t.getLocationInfo()))
+                    l.add(t);
+            }
+            return l.toArray(new TypeAnnotation[0]);
+        }
+
+        boolean isSameLocationInfo(LocationInfo other) {
+            if (depth != other.depth)
+                return false;
+            for (int i = 0; i < depth; i++)
+                if (!locations[i].isSameLocation(other.locations[i]))
+                    return false;
+            return true;
+        }
+
+        public static class Location {
+            public final byte tag;
+            public final byte index;
+
+            boolean isSameLocation(Location other) {
+                return tag == other.tag && index == other.index;
+            }
+
+            public Location(byte tag, byte index) {
+                this.tag = tag;
+                this.index = index;
+            }
+        }
+    }
+
+    @Override
+    public String toString() {
+        return annotation.toString() + " with Targetnfo: " +
+            targetInfo.toString() + " on base declaration: " +
+            baseDeclaration.toString();
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/share/classes/sun/reflect/annotation/TypeAnnotationParser.java	Tue Jan 29 10:32:49 2013 +0100
@@ -0,0 +1,491 @@
+/*
+ * 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.  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.nio.ByteBuffer;
+import java.nio.BufferUnderflowException;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+import java.util.HashMap;
+import java.util.LinkedHashMap;
+import java.util.Map;
+import sun.misc.JavaLangAccess;
+import sun.reflect.ConstantPool;
+import static sun.reflect.annotation.TypeAnnotation.*;
+
+/**
+ * TypeAnnotationParser implements the logic needed to parse
+ * TypeAnnotations from an array of bytes.
+ */
+public class TypeAnnotationParser {
+    private static final TypeAnnotation[] EMPTY_TYPE_ANNOTATION_ARRAY = new TypeAnnotation[0];
+
+    /**
+     * Build an AnnotatedType from the parameters supplied.
+     *
+     * This method and {@code buildAnnotatedTypes} are probably
+     * the entry points you are looking for.
+     *
+     * @param rawAnnotations the byte[] encoding of all type annotations on this declaration
+     * @param cp the ConstantPool needed to parse the embedded Annotation
+     * @param decl the dclaration this type annotation is on
+     * @param container the Class this type annotation is on (may be the same as decl)
+     * @param type the type the AnnotatedType corresponds to
+     * @param filter the type annotation targets included in this AnnotatedType
+     */
+    public static AnnotatedType buildAnnotatedType(byte[] rawAnnotations,
+            ConstantPool cp,
+            AnnotatedElement decl,
+            Class<?> container,
+            Type type,
+            TypeAnnotationTarget filter) {
+        TypeAnnotation[] tas = parseTypeAnnotations(rawAnnotations,
+                                                    cp,
+                                                    decl,
+                                                    container);
+        List<TypeAnnotation> l = new ArrayList<>(tas.length);
+        for (TypeAnnotation t : tas) {
+            TypeAnnotationTargetInfo ti = t.getTargetInfo();
+            if (ti.getTarget() == filter)
+                l.add(t);
+        }
+        TypeAnnotation[] typeAnnotations = l.toArray(new TypeAnnotation[0]);
+        return AnnotatedTypeFactory.buildAnnotatedType(type,
+                                                       LocationInfo.BASE_LOCATION,
+                                                       typeAnnotations,
+                                                       typeAnnotations,
+                                                       decl);
+    }
+
+    /**
+     * Build an array of AnnotatedTypes from the parameters supplied.
+     *
+     * This method and {@code buildAnnotatedType} are probably
+     * the entry points you are looking for.
+     *
+     * @param rawAnnotations the byte[] encoding of all type annotations on this declaration
+     * @param cp the ConstantPool needed to parse the embedded Annotation
+     * @param decl the declaration this type annotation is on
+     * @param container the Class this type annotation is on (may be the same as decl)
+     * @param types the Types the AnnotatedTypes corresponds to
+     * @param filter the type annotation targets that included in this AnnotatedType
+     */
+    public static AnnotatedType[] buildAnnotatedTypes(byte[] rawAnnotations,
+            ConstantPool cp,
+            AnnotatedElement decl,
+            Class<?> container,
+            Type[] types,
+            TypeAnnotationTarget filter) {
+        int size = types.length;
+        AnnotatedType[] result = new AnnotatedType[size];
+        Arrays.fill(result, AnnotatedTypeFactory.EMPTY_ANNOTATED_TYPE);
+        @SuppressWarnings("rawtypes")
+        ArrayList[] l = new ArrayList[size]; // array of ArrayList<TypeAnnotation>
+
+        TypeAnnotation[] tas = parseTypeAnnotations(rawAnnotations,
+                                                    cp,
+                                                    decl,
+                                                    container);
+        for (TypeAnnotation t : tas) {
+            TypeAnnotationTargetInfo ti = t.getTargetInfo();
+            if (ti.getTarget() == filter) {
+                int pos = ti.getCount();
+                if (l[pos] == null) {
+                    ArrayList<TypeAnnotation> tmp = new ArrayList<>(tas.length);
+                    l[pos] = tmp;
+                }
+                @SuppressWarnings("unchecked")
+                ArrayList<TypeAnnotation> tmp = l[pos];
+                tmp.add(t);
+            }
+        }
+        for (int i = 0; i < size; i++) {
+            @SuppressWarnings("unchecked")
+            ArrayList<TypeAnnotation> list = l[i];
+            if (list != null) {
+                TypeAnnotation[] typeAnnotations = list.toArray(new TypeAnnotation[0]);
+                result[i] = AnnotatedTypeFactory.buildAnnotatedType(types[i],
+                                                                    LocationInfo.BASE_LOCATION,
+                                                                    typeAnnotations,
+                                                                    typeAnnotations,
+                                                                    decl);
+            }
+        }
+        return result;
+    }
+
+    // Class helpers
+
+    /**
+     * Build an AnnotatedType for the class decl's supertype.
+     *
+     * @param rawAnnotations the byte[] encoding of all type annotations on this declaration
+     * @param cp the ConstantPool needed to parse the embedded Annotation
+     * @param decl the Class which annotated supertype is being built
+     */
+    public static AnnotatedType buildAnnotatedSuperclass(byte[] rawAnnotations,
+            ConstantPool cp,
+            Class<?> decl) {
+        Type supertype = decl.getGenericSuperclass();
+        if (supertype == null)
+            return AnnotatedTypeFactory.EMPTY_ANNOTATED_TYPE;
+        return buildAnnotatedType(rawAnnotations,
+                                  cp,
+                                  decl,
+                                  decl,
+                                  supertype,
+                                  TypeAnnotationTarget.CLASS_EXTENDS);
+    }
+
+    /**
+     * Build an array of AnnotatedTypes for the class decl's implemented
+     * interfaces.
+     *
+     * @param rawAnnotations the byte[] encoding of all type annotations on this declaration
+     * @param cp the ConstantPool needed to parse the embedded Annotation
+     * @param decl the Class whose annotated implemented interfaces is being built
+     */
+    public static AnnotatedType[] buildAnnotatedInterfaces(byte[] rawAnnotations,
+            ConstantPool cp,
+            Class<?> decl) {
+        return buildAnnotatedTypes(rawAnnotations,
+                                   cp,
+                                   decl,
+                                   decl,
+                                   decl.getGenericInterfaces(),
+                                   TypeAnnotationTarget.CLASS_IMPLEMENTS);
+    }
+
+    // TypeVariable helpers
+
+    /**
+     * Parse regular annotations on a TypeVariable declared on genericDecl.
+     *
+     * Regular Annotations on TypeVariables are stored in the type
+     * annotation byte[] in the class file.
+     *
+     * @param genericsDecl the declaration declaring the type variable
+     * @param typeVarIndex the 0-based index of this type variable in the declaration
+     */
+    public static <D extends GenericDeclaration> Annotation[] parseTypeVariableAnnotations(D genericDecl,
+            int typeVarIndex) {
+        AnnotatedElement decl;
+        TypeAnnotationTarget predicate;
+        if (genericDecl instanceof Class) {
+            decl = (Class<?>)genericDecl;
+            predicate = TypeAnnotationTarget.CLASS_TYPE_PARAMETER;
+        } else if (genericDecl instanceof Executable) {
+            decl = (Executable)genericDecl;
+            predicate = TypeAnnotationTarget.METHOD_TYPE_PARAMETER;
+        } else {
+            throw new AssertionError("Unknown GenericDeclaration " + genericDecl + "\nthis should not happen.");
+        }
+        List<TypeAnnotation> typeVarAnnos = TypeAnnotation.filter(parseAllTypeAnnotations(decl),
+                                                                  predicate);
+        List<Annotation> res = new ArrayList<>(typeVarAnnos.size());
+        for (TypeAnnotation t : typeVarAnnos)
+            if (t.getTargetInfo().getCount() == typeVarIndex)
+                res.add(t.getAnnotation());
+        return res.toArray(new Annotation[0]);
+    }
+
+    /**
+     * Build an array of AnnotatedTypes for the declaration decl's bounds.
+     *
+     * @param bounds the bounds corresponding to the annotated bounds
+     * @param decl the declaration whose annotated bounds is being built
+     * @param typeVarIndex the index of this type variable on the decl
+     */
+    public static <D extends GenericDeclaration> AnnotatedType[] parseAnnotatedBounds(Type[] bounds,
+            D decl,
+            int typeVarIndex) {
+        return parseAnnotatedBounds(bounds, decl, typeVarIndex, LocationInfo.BASE_LOCATION);
+    }
+    //helper for above
+    static <D extends GenericDeclaration> AnnotatedType[] parseAnnotatedBounds(Type[] bounds,
+            D decl,
+            int typeVarIndex,
+            LocationInfo loc) {
+        List<TypeAnnotation> candidates = fetchBounds(decl);
+        if (bounds != null) {
+            int startIndex = 0;
+            AnnotatedType[] res = new AnnotatedType[bounds.length];
+            Arrays.fill(res, AnnotatedTypeFactory.EMPTY_ANNOTATED_TYPE);
+
+            // Adjust bounds index
+            //
+            // Figure out if the type annotations for this bound starts with 0
+            // or 1. The spec says within a bound the 0:th type annotation will
+            // always be on an bound of a Class type (not Interface type). So
+            // if the programmer starts with an Interface type for the first
+            // (and following) bound(s) the implicit Object bound is considered
+            // the first (that is 0:th) bound and type annotations start on
+            // index 1.
+            if (bounds.length > 0) {
+                Type b0 = bounds[0];
+                if (!(b0 instanceof Class<?>)) {
+                    startIndex = 1;
+                } else {
+                    Class<?> c = (Class<?>)b0;
+                    if (c.isInterface()) {
+                        startIndex = 1;
+                    }
+                }
+            }
+
+            for (int i = 0; i < bounds.length; i++) {
+                List<TypeAnnotation> l = new ArrayList<>(candidates.size());
+                for (TypeAnnotation t : candidates) {
+                    TypeAnnotationTargetInfo tInfo = t.getTargetInfo();
+                    if (tInfo.getSecondaryIndex() == i + startIndex &&
+                            tInfo.getCount() == typeVarIndex) {
+                        l.add(t);
+                    }
+                    res[i] = AnnotatedTypeFactory.buildAnnotatedType(bounds[i],
+                                                                     loc,
+                                                                     l.toArray(new TypeAnnotation[0]),
+                                                                     candidates.toArray(new TypeAnnotation[0]),
+                                                                     (AnnotatedElement)decl);
+                }
+            }
+            return res;
+        }
+        return new AnnotatedType[0];
+    }
+    private static <D extends GenericDeclaration> List<TypeAnnotation> fetchBounds(D decl) {
+        AnnotatedElement boundsDecl;
+        TypeAnnotationTarget target;
+        if (decl instanceof Class) {
+            target = TypeAnnotationTarget.CLASS_PARAMETER_BOUND;
+            boundsDecl = (Class)decl;
+        } else {
+            target = TypeAnnotationTarget.METHOD_PARAMETER_BOUND;
+            boundsDecl = (Executable)decl;
+        }
+        return TypeAnnotation.filter(TypeAnnotationParser.parseAllTypeAnnotations(boundsDecl), target);
+    }
+
+    /*
+     * Parse all type annotations on the declaration supplied. This is needed
+     * when you go from for example an annotated return type on a method that
+     * is a type variable declared on the class. In this case you need to
+     * 'jump' to the decl of the class and parse all type annotations there to
+     * find the ones that are applicable to the type variable.
+     */
+    static TypeAnnotation[] parseAllTypeAnnotations(AnnotatedElement decl) {
+        Class<?> container;
+        byte[] rawBytes;
+        JavaLangAccess javaLangAccess = sun.misc.SharedSecrets.getJavaLangAccess();
+        if (decl instanceof Class) {
+            container = (Class<?>)decl;
+            rawBytes = javaLangAccess.getRawClassTypeAnnotations(container);
+        } else if (decl instanceof Executable) {
+            container = ((Executable)decl).getDeclaringClass();
+            rawBytes = javaLangAccess.getRawExecutableTypeAnnotations((Executable)decl);
+        } else {
+            // Should not reach here. Assert?
+            return EMPTY_TYPE_ANNOTATION_ARRAY;
+        }
+        return parseTypeAnnotations(rawBytes, javaLangAccess.getConstantPool(container),
+                                    decl, container);
+    }
+
+    /* Parse type annotations encoded as an array of bytes */
+    private static TypeAnnotation[] parseTypeAnnotations(byte[] rawAnnotations,
+            ConstantPool cp,
+            AnnotatedElement baseDecl,
+            Class<?> container) {
+        if (rawAnnotations == null)
+            return EMPTY_TYPE_ANNOTATION_ARRAY;
+
+        ByteBuffer buf = ByteBuffer.wrap(rawAnnotations);
+        int annotationCount = buf.getShort() & 0xFFFF;
+        List<TypeAnnotation> typeAnnotations = new ArrayList<>(annotationCount);
+
+        // Parse each TypeAnnotation
+        for (int i = 0; i < annotationCount; i++) {
+             TypeAnnotation ta = parseTypeAnnotation(buf, cp, baseDecl, container);
+             if (ta != null)
+                 typeAnnotations.add(ta);
+        }
+
+        return typeAnnotations.toArray(EMPTY_TYPE_ANNOTATION_ARRAY);
+    }
+
+
+    // Helper
+    static Map<Class<? extends Annotation>, Annotation> mapTypeAnnotations(TypeAnnotation[] typeAnnos) {
+        Map<Class<? extends Annotation>, Annotation> result =
+            new LinkedHashMap<>();
+        for (TypeAnnotation t : typeAnnos) {
+            Annotation a = t.getAnnotation();
+            Class<? extends Annotation> klass = a.annotationType();
+            AnnotationType type = AnnotationType.getInstance(klass);
+            if (type.retention() == RetentionPolicy.RUNTIME)
+                if (result.put(klass, a) != null)
+                    throw new AnnotationFormatError("Duplicate annotation for class: "+klass+": " + a);
+        }
+        return result;
+    }
+
+    // Position codes
+    // Regular type parameter annotations
+    private static final byte CLASS_TYPE_PARAMETER = 0x00;
+    private static final byte METHOD_TYPE_PARAMETER = 0x01;
+    // Type Annotations outside method bodies
+    private static final byte CLASS_EXTENDS = 0x10;
+    private static final byte CLASS_TYPE_PARAMETER_BOUND = 0x11;
+    private static final byte METHOD_TYPE_PARAMETER_BOUND = 0x12;
+    private static final byte FIELD = 0x13;
+    private static final byte METHOD_RETURN = 0x14;
+    private static final byte METHOD_RECEIVER = 0x15;
+    private static final byte METHOD_FORMAL_PARAMETER = 0x16;
+    private static final byte THROWS = 0x17;
+    // Type Annotations inside method bodies
+    private static final byte LOCAL_VARIABLE = (byte)0x40;
+    private static final byte RESOURCE_VARIABLE = (byte)0x41;
+    private static final byte EXCEPTION_PARAMETER = (byte)0x42;
+    private static final byte CAST = (byte)0x43;
+    private static final byte INSTANCEOF = (byte)0x44;
+    private static final byte NEW = (byte)0x45;
+    private static final byte CONSTRUCTOR_REFERENCE_RECEIVER = (byte)0x46;
+    private static final byte METHOD_REFERENCE_RECEIVER = (byte)0x47;
+    private static final byte LAMBDA_FORMAL_PARAMETER = (byte)0x48;
+    private static final byte METHOD_REFERENCE = (byte)0x49;
+    private static final byte METHOD_REFERENCE_TYPE_ARGUMENT = (byte)0x50;
+
+    private static TypeAnnotation parseTypeAnnotation(ByteBuffer buf,
+            ConstantPool cp,
+            AnnotatedElement baseDecl,
+            Class<?> container) {
+        TypeAnnotationTargetInfo ti = parseTargetInfo(buf);
+        LocationInfo locationInfo = LocationInfo.parseLocationInfo(buf);
+        Annotation a = AnnotationParser.parseAnnotation(buf, cp, container, false);
+        if (ti == null) // Inside a method for example
+            return null;
+        return new TypeAnnotation(ti, locationInfo, a, baseDecl);
+    }
+
+    private static TypeAnnotationTargetInfo parseTargetInfo(ByteBuffer buf) {
+        byte posCode = buf.get();
+        switch(posCode) {
+        case CLASS_TYPE_PARAMETER:
+        case METHOD_TYPE_PARAMETER: {
+            byte index = buf.get();
+            TypeAnnotationTargetInfo res;
+            if (posCode == CLASS_TYPE_PARAMETER)
+                res = new TypeAnnotationTargetInfo(TypeAnnotationTarget.CLASS_TYPE_PARAMETER,
+                        index);
+            else
+                res = new TypeAnnotationTargetInfo(TypeAnnotationTarget.METHOD_TYPE_PARAMETER,
+                        index);
+            return res;
+            } // unreachable break;
+        case CLASS_EXTENDS: {
+            short index = buf.getShort();
+            if (index == -1) {
+                return new TypeAnnotationTargetInfo(TypeAnnotationTarget.CLASS_EXTENDS);
+            } else if (index >= 0) {
+                TypeAnnotationTargetInfo res = new TypeAnnotationTargetInfo(TypeAnnotationTarget.CLASS_IMPLEMENTS,
+                        index);
+                return res;
+            }} break;
+        case CLASS_TYPE_PARAMETER_BOUND:
+            return parse2ByteTarget(TypeAnnotationTarget.CLASS_PARAMETER_BOUND, buf);
+        case METHOD_TYPE_PARAMETER_BOUND:
+            return parse2ByteTarget(TypeAnnotationTarget.METHOD_PARAMETER_BOUND, buf);
+        case FIELD:
+            return new TypeAnnotationTargetInfo(TypeAnnotationTarget.FIELD_TYPE);
+        case METHOD_RETURN:
+            return new TypeAnnotationTargetInfo(TypeAnnotationTarget.METHOD_RETURN_TYPE);
+        case METHOD_RECEIVER:
+            return new TypeAnnotationTargetInfo(TypeAnnotationTarget.METHOD_RECEIVER_TYPE);
+        case METHOD_FORMAL_PARAMETER: {
+            // Todo
+            byte index = buf.get();
+            } break;
+        case THROWS:
+            return parseShortTarget(TypeAnnotationTarget.THROWS, buf);
+
+        /*
+         * The ones below are inside method bodies, we don't care about them for core reflection
+         * other than adjusting for them in the byte stream.
+         */
+        case LOCAL_VARIABLE:
+        case RESOURCE_VARIABLE:
+            short length = buf.getShort();
+            for (int i = 0; i < length; ++i) {
+                short offset = buf.getShort();
+                short varLength = buf.getShort();
+                short index = buf.getShort();
+            }
+            break;
+        case EXCEPTION_PARAMETER: {
+            byte index = buf.get();
+            } break;
+        case CAST:
+        case INSTANCEOF:
+        case NEW: {
+            short offset = buf.getShort();
+            } break;
+        case CONSTRUCTOR_REFERENCE_RECEIVER:
+        case METHOD_REFERENCE_RECEIVER: {
+            short offset = buf.getShort();
+            byte index = buf.get();
+            } break;
+        case LAMBDA_FORMAL_PARAMETER: {
+            byte index = buf.get();
+            } break;
+        case METHOD_REFERENCE:
+            // This one isn't in the spec yet
+            break;
+        case METHOD_REFERENCE_TYPE_ARGUMENT: {
+            short offset = buf.getShort();
+            byte index = buf.get();
+            } break;
+
+        default:
+            // will throw error below
+            break;
+        }
+        throw new AnnotationFormatError("Could not parse bytes for type annotations");
+    }
+
+    private static TypeAnnotationTargetInfo parseShortTarget(TypeAnnotationTarget target, ByteBuffer buf) {
+        short index = buf.getShort();
+        return new TypeAnnotationTargetInfo(target, index);
+    }
+    private static TypeAnnotationTargetInfo parse2ByteTarget(TypeAnnotationTarget target, ByteBuffer buf) {
+        byte count = buf.get();
+        byte secondaryIndex = buf.get();
+        return new TypeAnnotationTargetInfo(target,
+                                            count,
+                                            secondaryIndex);
+    }
+}
--- a/jdk/src/share/classes/sun/reflect/generics/reflectiveObjects/TypeVariableImpl.java	Sat Jan 26 16:57:02 2013 +0000
+++ b/jdk/src/share/classes/sun/reflect/generics/reflectiveObjects/TypeVariableImpl.java	Tue Jan 29 10:32:49 2013 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2003, 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 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
@@ -25,13 +25,18 @@
 
 package sun.reflect.generics.reflectiveObjects;
 
-import java.lang.annotation.Annotation;
+import java.lang.annotation.*;
+import java.lang.reflect.AnnotatedType;
 import java.lang.reflect.Array;
 import java.lang.reflect.GenericDeclaration;
 import java.lang.reflect.Type;
 import java.lang.reflect.TypeVariable;
+import java.util.LinkedHashMap;
+import java.util.Map;
 import java.util.Objects;
-
+import sun.reflect.annotation.AnnotationSupport;
+import sun.reflect.annotation.TypeAnnotationParser;
+import sun.reflect.annotation.AnnotationType;
 import sun.reflect.generics.factory.GenericsFactory;
 import sun.reflect.generics.tree.FieldTypeSignature;
 import sun.reflect.generics.visitor.Reifier;
@@ -182,45 +187,75 @@
         return genericDeclaration.hashCode() ^ name.hashCode();
     }
 
-    // Currently vacuous implementations of AnnotatedElement methods.
+    // Implementations of AnnotatedElement methods.
     public boolean isAnnotationPresent(Class<? extends Annotation> annotationClass) {
         Objects.requireNonNull(annotationClass);
         return false;
     }
 
+    @SuppressWarnings("unchecked")
     public <T extends Annotation> T getAnnotation(Class<T> annotationClass) {
         Objects.requireNonNull(annotationClass);
-        return null;
+        // T is an Annotation type, the return value of get will be an annotation
+        return (T)mapAnnotations(getAnnotations()).get(annotationClass);
     }
 
     public <T extends Annotation> T getDeclaredAnnotation(Class<T> annotationClass) {
         Objects.requireNonNull(annotationClass);
-        return null;
+        return getAnnotation(annotationClass);
     }
 
-    @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);
+        return AnnotationSupport.getMultipleAnnotations(mapAnnotations(getAnnotations()), annotationClass);
     }
 
-    @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);
+        return getAnnotations(annotationClass);
     }
 
     public Annotation[] getAnnotations() {
-        // Since zero-length, don't need defensive clone
-        return EMPTY_ANNOTATION_ARRAY;
+        int myIndex = typeVarIndex();
+        if (myIndex < 0)
+            throw new AssertionError("Index must be non-negative.");
+        return TypeAnnotationParser.parseTypeVariableAnnotations(getGenericDeclaration(), myIndex);
     }
 
     public Annotation[] getDeclaredAnnotations() {
-        // Since zero-length, don't need defensive clone
-        return EMPTY_ANNOTATION_ARRAY;
+        return getAnnotations();
+    }
+
+    public AnnotatedType[] getAnnotatedBounds() {
+        return TypeAnnotationParser.parseAnnotatedBounds(getBounds(),
+                                                         getGenericDeclaration(),
+                                                         typeVarIndex());
     }
 
     private static final Annotation[] EMPTY_ANNOTATION_ARRAY = new Annotation[0];
+
+    // Helpers for annotation methods
+    private int typeVarIndex() {
+        TypeVariable<?>[] tVars = getGenericDeclaration().getTypeParameters();
+        int i = -1;
+        for (TypeVariable<?> v : tVars) {
+            i++;
+            if (equals(v))
+                return i;
+        }
+        return -1;
+    }
+
+    private static Map<Class<? extends Annotation>, Annotation> mapAnnotations(Annotation[] annos) {
+        Map<Class<? extends Annotation>, Annotation> result =
+            new LinkedHashMap<>();
+        for (Annotation a : annos) {
+            Class<? extends Annotation> klass = a.annotationType();
+            AnnotationType type = AnnotationType.getInstance(klass);
+            if (type.retention() == RetentionPolicy.RUNTIME)
+                if (result.put(klass, a) != null)
+                    throw new AnnotationFormatError("Duplicate annotation for class: "+klass+": " + a);
+        }
+        return result;
+    }
 }
--- a/jdk/src/share/javavm/export/jvm.h	Sat Jan 26 16:57:02 2013 +0000
+++ b/jdk/src/share/javavm/export/jvm.h	Tue Jan 29 10:32:49 2013 +0100
@@ -465,6 +465,12 @@
 JNIEXPORT jbyteArray JNICALL
 JVM_GetClassAnnotations(JNIEnv *env, jclass cls);
 
+/* Type use annotations support (JDK 1.8) */
+
+JNIEXPORT jbyteArray JNICALL
+JVM_GetClassTypeAnnotations(JNIEnv *env, jclass cls);
+
+
 /*
  * New (JDK 1.4) reflection implementation
  */
--- a/jdk/src/share/native/java/lang/Class.c	Sat Jan 26 16:57:02 2013 +0000
+++ b/jdk/src/share/native/java/lang/Class.c	Tue Jan 29 10:32:49 2013 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1994, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1994, 2013, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -75,7 +75,8 @@
     {"getRawAnnotations",      "()" BA,        (void *)&JVM_GetClassAnnotations},
     {"getConstantPool",     "()" CPL,       (void *)&JVM_GetClassConstantPool},
     {"desiredAssertionStatus0","("CLS")Z",(void *)&JVM_DesiredAssertionStatus},
-    {"getEnclosingMethod0", "()[" OBJ,      (void *)&JVM_GetEnclosingMethodInfo}
+    {"getEnclosingMethod0", "()[" OBJ,      (void *)&JVM_GetEnclosingMethodInfo},
+    {"getRawTypeAnnotations", "()" BA,      (void *)&JVM_GetClassTypeAnnotations},
 };
 
 #undef OBJ
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/lang/annotation/TypeAnnotationReflection.java	Tue Jan 29 10:32:49 2013 +0100
@@ -0,0 +1,428 @@
+/*
+ * 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 8004698
+ * @summary Unit test for type annotations
+ */
+
+import java.util.*;
+import java.lang.annotation.*;
+import java.lang.reflect.*;
+import java.io.Serializable;
+
+public class TypeAnnotationReflection {
+    public static void main(String[] args) throws Exception {
+        testSuper();
+        testInterfaces();
+        testReturnType();
+        testNested();
+        testArray();
+        testRunException();
+        testClassTypeVarBounds();
+        testMethodTypeVarBounds();
+        testFields();
+        testClassTypeVar();
+        testMethodTypeVar();
+        testParameterizedType();
+        testNestedParameterizedType();
+        testWildcardType();
+    }
+
+    private static void check(boolean b) {
+        if (!b)
+            throw new RuntimeException();
+    }
+
+    private static void testSuper() throws Exception {
+        check(Object.class.getAnnotatedSuperclass().getAnnotations().length == 0);
+        check(Class.class.getAnnotatedSuperclass().getAnnotations().length == 0);
+
+        AnnotatedType a;
+        a = TestClassArray.class.getAnnotatedSuperclass();
+        Annotation[] annos = a.getAnnotations();
+        check(annos.length == 2);
+        check(annos[0].annotationType().equals(TypeAnno.class));
+        check(annos[1].annotationType().equals(TypeAnno2.class));
+        check(((TypeAnno)annos[0]).value().equals("extends"));
+        check(((TypeAnno2)annos[1]).value().equals("extends2"));
+    }
+
+    private static void testInterfaces() throws Exception {
+        AnnotatedType[] as;
+        as = TestClassArray.class.getAnnotatedInterfaces();
+        check(as.length == 3);
+        check(as[1].getAnnotations().length == 0);
+
+        Annotation[] annos;
+        annos = as[0].getAnnotations();
+        check(annos.length == 2);
+        check(annos[0].annotationType().equals(TypeAnno.class));
+        check(annos[1].annotationType().equals(TypeAnno2.class));
+        check(((TypeAnno)annos[0]).value().equals("implements serializable"));
+        check(((TypeAnno2)annos[1]).value().equals("implements2 serializable"));
+
+        annos = as[2].getAnnotations();
+        check(annos.length == 2);
+        check(annos[0].annotationType().equals(TypeAnno.class));
+        check(annos[1].annotationType().equals(TypeAnno2.class));
+        check(((TypeAnno)annos[0]).value().equals("implements cloneable"));
+        check(((TypeAnno2)annos[1]).value().equals("implements2 cloneable"));
+    }
+
+    private static void testReturnType() throws Exception {
+        Method m = TestClassArray.class.getDeclaredMethod("foo", (Class<?>[])null);
+        Annotation[] annos = m.getAnnotatedReturnType().getAnnotations();
+        check(annos.length == 1);
+        check(annos[0].annotationType().equals(TypeAnno.class));
+        check(((TypeAnno)annos[0]).value().equals("return1"));
+    }
+
+    private static void testNested() throws Exception {
+        Method m = TestClassNested.class.getDeclaredMethod("foo", (Class<?>[])null);
+        Annotation[] annos = m.getAnnotatedReturnType().getAnnotations();
+        check(annos.length == 1);
+        check(annos[0].annotationType().equals(TypeAnno.class));
+        check(((TypeAnno)annos[0]).value().equals("array"));
+
+        AnnotatedType t = m.getAnnotatedReturnType();
+        t = ((AnnotatedArrayType)t).getAnnotatedGenericComponentType();
+        annos = t.getAnnotations();
+        check(annos.length == 1);
+        check(annos[0].annotationType().equals(TypeAnno.class));
+        check(((TypeAnno)annos[0]).value().equals("Inner"));
+    }
+
+    private static void testArray() throws Exception {
+        Method m = TestClassArray.class.getDeclaredMethod("foo", (Class<?>[])null);
+        AnnotatedArrayType t = (AnnotatedArrayType) m.getAnnotatedReturnType();
+        Annotation[] annos = t.getAnnotations();
+        check(annos.length == 1);
+        check(annos[0].annotationType().equals(TypeAnno.class));
+        check(((TypeAnno)annos[0]).value().equals("return1"));
+
+        t = (AnnotatedArrayType)t.getAnnotatedGenericComponentType();
+        annos = t.getAnnotations();
+        check(annos.length == 0);
+
+        t = (AnnotatedArrayType)t.getAnnotatedGenericComponentType();
+        annos = t.getAnnotations();
+        check(annos.length == 1);
+        check(annos[0].annotationType().equals(TypeAnno.class));
+        check(((TypeAnno)annos[0]).value().equals("return3"));
+
+        AnnotatedType tt = t.getAnnotatedGenericComponentType();
+        check(!(tt instanceof AnnotatedArrayType));
+        annos = tt.getAnnotations();
+        check(annos.length == 1);
+        check(annos[0].annotationType().equals(TypeAnno.class));
+        check(((TypeAnno)annos[0]).value().equals("return4"));
+    }
+
+    private static void testRunException() throws Exception {
+        Method m = TestClassException.class.getDeclaredMethod("foo", (Class<?>[])null);
+        AnnotatedType[] ts = m.getAnnotatedExceptionTypes();
+        check(ts.length == 3);
+
+        AnnotatedType t;
+        Annotation[] annos;
+        t = ts[0];
+        annos = t.getAnnotations();
+        check(annos.length == 2);
+        check(annos[0].annotationType().equals(TypeAnno.class));
+        check(annos[1].annotationType().equals(TypeAnno2.class));
+        check(((TypeAnno)annos[0]).value().equals("RE"));
+        check(((TypeAnno2)annos[1]).value().equals("RE2"));
+
+        t = ts[1];
+        annos = t.getAnnotations();
+        check(annos.length == 0);
+
+        t = ts[2];
+        annos = t.getAnnotations();
+        check(annos.length == 1);
+        check(annos[0].annotationType().equals(TypeAnno.class));
+        check(((TypeAnno)annos[0]).value().equals("AIOOBE"));
+    }
+
+    private static void testClassTypeVarBounds() throws Exception {
+        Method m = TestClassTypeVarAndField.class.getDeclaredMethod("foo", (Class<?>[])null);
+        AnnotatedType ret = m.getAnnotatedReturnType();
+        Annotation[] annos = ret.getAnnotations();
+        check(annos.length == 2);
+
+        AnnotatedType[] annotatedBounds = ((AnnotatedTypeVariable)ret).getAnnotatedBounds();
+        check(annotatedBounds.length == 2);
+
+        annos = annotatedBounds[0].getAnnotations();
+        check(annos.length == 1);
+        check(annos[0].annotationType().equals(TypeAnno.class));
+        check(((TypeAnno)annos[0]).value().equals("Object1"));
+
+        annos = annotatedBounds[1].getAnnotations();
+        check(annos.length == 2);
+        check(annos[0].annotationType().equals(TypeAnno.class));
+        check(annos[1].annotationType().equals(TypeAnno2.class));
+        check(((TypeAnno)annos[0]).value().equals("Runnable1"));
+        check(((TypeAnno2)annos[1]).value().equals("Runnable2"));
+    }
+
+    private static void testMethodTypeVarBounds() throws Exception {
+        Method m2 = TestClassTypeVarAndField.class.getDeclaredMethod("foo2", (Class<?>[])null);
+        AnnotatedType ret2 = m2.getAnnotatedReturnType();
+        AnnotatedType[] annotatedBounds2 = ((AnnotatedTypeVariable)ret2).getAnnotatedBounds();
+        check(annotatedBounds2.length == 1);
+
+        Annotation[] annos = annotatedBounds2[0].getAnnotations();
+        check(annos.length == 1);
+        check(annos[0].annotationType().equals(TypeAnno.class));
+        check(((TypeAnno)annos[0]).value().equals("M Runnable"));
+    }
+
+    private static void testFields() throws Exception {
+        Field f1 = TestClassTypeVarAndField.class.getDeclaredField("field1");
+        AnnotatedType at;
+        Annotation[] annos;
+
+        at = f1.getAnnotatedType();
+        annos = at.getAnnotations();
+        check(annos.length == 2);
+        check(annos[0].annotationType().equals(TypeAnno.class));
+        check(annos[1].annotationType().equals(TypeAnno2.class));
+        check(((TypeAnno)annos[0]).value().equals("T1 field"));
+        check(((TypeAnno2)annos[1]).value().equals("T2 field"));
+
+        Field f2 = TestClassTypeVarAndField.class.getDeclaredField("field2");
+        at = f2.getAnnotatedType();
+        annos = at.getAnnotations();
+        check(annos.length == 0);
+
+        Field f3 = TestClassTypeVarAndField.class.getDeclaredField("field3");
+        at = f3.getAnnotatedType();
+        annos = at.getAnnotations();
+        check(annos.length == 1);
+        check(annos[0].annotationType().equals(TypeAnno.class));
+        check(((TypeAnno)annos[0]).value().equals("Object field"));
+    }
+
+    private static void testClassTypeVar() throws Exception {
+        TypeVariable[] typeVars = TestClassTypeVarAndField.class.getTypeParameters();
+        Annotation[] annos;
+        check(typeVars.length == 2);
+
+        // First TypeVar
+        AnnotatedType[] annotatedBounds = typeVars[0].getAnnotatedBounds();
+        check(annotatedBounds.length == 2);
+
+        annos = annotatedBounds[0].getAnnotations();
+        check(annos.length == 1);
+        check(annos[0].annotationType().equals(TypeAnno.class));
+        check(((TypeAnno)annos[0]).value().equals("Object1"));
+
+        annos = annotatedBounds[1].getAnnotations();
+        check(annos.length == 2);
+        check(annos[0].annotationType().equals(TypeAnno.class));
+        check(annos[1].annotationType().equals(TypeAnno2.class));
+        check(((TypeAnno)annos[0]).value().equals("Runnable1"));
+        check(((TypeAnno2)annos[1]).value().equals("Runnable2"));
+
+        // second TypeVar regular anno
+        Annotation[] regularAnnos = typeVars[1].getAnnotations();
+        check(regularAnnos.length == 1);
+        check(typeVars[1].getAnnotation(TypeAnno.class).value().equals("EE"));
+
+        // second TypeVar
+        annotatedBounds = typeVars[1].getAnnotatedBounds();
+        check(annotatedBounds.length == 1);
+
+        annos = annotatedBounds[0].getAnnotations();
+        check(annos.length == 1);
+        check(annos[0].annotationType().equals(TypeAnno2.class));
+        check(((TypeAnno2)annos[0]).value().equals("EEBound"));
+    }
+
+    private static void testMethodTypeVar() throws Exception {
+        Method m2 = TestClassTypeVarAndField.class.getDeclaredMethod("foo2", (Class<?>[])null);
+        TypeVariable[] t = m2.getTypeParameters();
+        check(t.length == 1);
+        Annotation[] annos = t[0].getAnnotations();
+        check(annos.length == 0);
+
+        AnnotatedType[] annotatedBounds2 = t[0].getAnnotatedBounds();
+        check(annotatedBounds2.length == 1);
+
+        annos = annotatedBounds2[0].getAnnotations();
+        check(annos.length == 1);
+        check(annos[0].annotationType().equals(TypeAnno.class));
+        check(((TypeAnno)annos[0]).value().equals("M Runnable"));
+
+        // Second method
+        m2 = TestClassTypeVarAndField.class.getDeclaredMethod("foo3", (Class<?>[])null);
+        t = m2.getTypeParameters();
+        check(t.length == 1);
+        annos = t[0].getAnnotations();
+        check(annos.length == 1);
+        check(annos[0].annotationType().equals(TypeAnno.class));
+        check(((TypeAnno)annos[0]).value().equals("K"));
+
+        annotatedBounds2 = t[0].getAnnotatedBounds();
+        check(annotatedBounds2.length == 1);
+
+        annos = annotatedBounds2[0].getAnnotations();
+        check(annos.length == 0);
+    }
+
+    private static void testParameterizedType() {
+        // Base
+        AnnotatedType[] as;
+        as = TestParameterizedType.class.getAnnotatedInterfaces();
+        check(as.length == 1);
+        check(as[0].getAnnotations().length == 1);
+        check(as[0].getAnnotation(TypeAnno.class).value().equals("M"));
+
+        Annotation[] annos;
+        as = ((AnnotatedParameterizedType)as[0]).getAnnotatedActualTypeArguments();
+        check(as.length == 2);
+        annos = as[0].getAnnotations();
+        check(annos.length == 1);
+        check(as[0].getAnnotation(TypeAnno.class).value().equals("S"));
+        check(as[0].getAnnotation(TypeAnno2.class) == null);
+
+        annos = as[1].getAnnotations();
+        check(annos.length == 2);
+        check(((TypeAnno)annos[0]).value().equals("I"));
+        check(as[1].getAnnotation(TypeAnno2.class).value().equals("I2"));
+    }
+
+    private static void testNestedParameterizedType() throws Exception {
+        Method m = TestParameterizedType.class.getDeclaredMethod("foo2", (Class<?>[])null);
+        AnnotatedType ret = m.getAnnotatedReturnType();
+        Annotation[] annos;
+        annos = ret.getAnnotations();
+        check(annos.length == 1);
+        check(((TypeAnno)annos[0]).value().equals("I"));
+
+        AnnotatedType[] args = ((AnnotatedParameterizedType)ret).getAnnotatedActualTypeArguments();
+        check(args.length == 1);
+        annos = args[0].getAnnotations();
+        check(annos.length == 2);
+        check(((TypeAnno)annos[0]).value().equals("I1"));
+        check(args[0].getAnnotation(TypeAnno2.class).value().equals("I2"));
+    }
+
+    private static void testWildcardType() throws Exception {
+        Method m = TestWildcardType.class.getDeclaredMethod("foo", (Class<?>[])null);
+        AnnotatedType ret = m.getAnnotatedReturnType();
+        AnnotatedType[] t;
+        t = ((AnnotatedParameterizedType)ret).getAnnotatedActualTypeArguments();
+        check(t.length == 1);
+        ret = t[0];
+
+        Field f = TestWildcardType.class.getDeclaredField("f1");
+        AnnotatedWildcardType w = (AnnotatedWildcardType)((AnnotatedParameterizedType)f
+            .getAnnotatedType()).getAnnotatedActualTypeArguments()[0];
+        t = w.getAnnotatedLowerBounds();
+        check(t.length == 0);
+        t = w.getAnnotatedUpperBounds();
+        check(t.length == 1);
+        Annotation[] annos;
+        annos = t[0].getAnnotations();
+        check(annos.length == 1);
+        check(((TypeAnno)annos[0]).value().equals("2"));
+
+        f = TestWildcardType.class.getDeclaredField("f2");
+        w = (AnnotatedWildcardType)((AnnotatedParameterizedType)f
+            .getAnnotatedType()).getAnnotatedActualTypeArguments()[0];
+        t = w.getAnnotatedUpperBounds();
+        check(t.length == 0);
+        t = w.getAnnotatedLowerBounds();
+        check(t.length == 1);
+    }
+}
+
+abstract class TestWildcardType {
+    public <T> List<? super T> foo() { return null;}
+    public Class<@TypeAnno("1") ? extends @TypeAnno("2") Annotation> f1;
+    public Class<@TypeAnno("3") ? super @TypeAnno("4") Annotation> f2;
+}
+
+abstract class TestParameterizedType implements @TypeAnno("M") Map<@TypeAnno("S")String, @TypeAnno("I") @TypeAnno2("I2")Integer> {
+    public ParameterizedOuter<String>.ParameterizedInner<Integer> foo() {return null;}
+    public @TypeAnno("O") ParameterizedOuter<@TypeAnno("S1") @TypeAnno2("S2") String>.
+               @TypeAnno("I") ParameterizedInner<@TypeAnno("I1") @TypeAnno2("I2")Integer> foo2() {
+        return null;
+    }
+}
+
+class ParameterizedOuter <T> {
+    class ParameterizedInner <U> {}
+}
+
+abstract class TestClassArray extends @TypeAnno("extends") @TypeAnno2("extends2") Object
+    implements @TypeAnno("implements serializable") @TypeAnno2("implements2 serializable") Serializable,
+    Readable,
+    @TypeAnno("implements cloneable") @TypeAnno2("implements2 cloneable") Cloneable {
+    public @TypeAnno("return4") Object @TypeAnno("return1") [][] @TypeAnno("return3")[] foo() { return null; }
+}
+
+abstract class TestClassNested {
+    public @TypeAnno("Outer") Outer.@TypeAnno("Inner")Inner @TypeAnno("array")[] foo() { return null; }
+}
+
+class Outer {
+    class Inner {
+    }
+}
+
+abstract class TestClassException {
+    public Object foo() throws @TypeAnno("RE") @TypeAnno2("RE2") RuntimeException,
+                                                                 NullPointerException,
+                                             @TypeAnno("AIOOBE") ArrayIndexOutOfBoundsException {
+        return null;
+    }
+}
+
+abstract class TestClassTypeVarAndField <T extends @TypeAnno("Object1") Object
+                                          & @TypeAnno("Runnable1") @TypeAnno2("Runnable2") Runnable,
+                                        @TypeAnno("EE")EE extends @TypeAnno2("EEBound") Runnable > {
+    @TypeAnno("T1 field") @TypeAnno2("T2 field") T field1;
+    T field2;
+    @TypeAnno("Object field") Object field3;
+
+    public @TypeAnno("t1") @TypeAnno2("t2") T foo(){ return null; }
+    public <M extends @TypeAnno("M Runnable") Runnable> M foo2() {return null;}
+    public <@TypeAnno("K") K extends Cloneable> K foo3() {return null;}
+}
+
+@Target(ElementType.TYPE_USE)
+@Retention(RetentionPolicy.RUNTIME)
+@interface TypeAnno {
+    String value();
+}
+
+@Target(ElementType.TYPE_USE)
+@Retention(RetentionPolicy.RUNTIME)
+@interface TypeAnno2 {
+    String value();
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/lang/annotation/TypeParamAnnotation.java	Tue Jan 29 10:32:49 2013 +0100
@@ -0,0 +1,120 @@
+/*
+ * 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 8004698
+ * @summary Unit test for annotations on TypeVariables
+ */
+
+import java.util.*;
+import java.lang.annotation.*;
+import java.lang.reflect.*;
+import java.io.Serializable;
+
+public class TypeParamAnnotation {
+    public static void main(String[] args) throws Exception {
+        testOnClass();
+        testOnMethod();
+        testGetAnno();
+        testGetAnnos();
+    }
+
+    private static void check(boolean b) {
+        if (!b)
+            throw new RuntimeException();
+    }
+
+    private static void testOnClass() {
+        TypeVariable<?>[] ts = TypeParam.class.getTypeParameters();
+        check(ts.length == 3);
+
+        Annotation[] as;
+
+        as = ts[0].getAnnotations();
+        check(as.length == 2);
+        check(((ParamAnno)as[0]).value().equals("t"));
+        check(((ParamAnno2)as[1]).value() == 1);
+
+        as = ts[1].getAnnotations();
+        check(as.length == 0);
+
+        as = ts[2].getAnnotations();
+        check(as.length == 2);
+        check(((ParamAnno)as[0]).value().equals("v"));
+        check(((ParamAnno2)as[1]).value() == 2);
+    }
+    private static void testOnMethod() throws Exception {
+        TypeVariable<?>[] ts = TypeParam.class.getDeclaredMethod("foo").getTypeParameters();
+        check(ts.length == 3);
+
+        Annotation[] as;
+
+        as = ts[0].getAnnotations();
+        check(as.length == 2);
+        check(((ParamAnno)as[0]).value().equals("x"));
+        check(((ParamAnno2)as[1]).value() == 3);
+
+        as = ts[1].getAnnotations();
+        check(as.length == 0);
+
+        as = ts[2].getAnnotations();
+        check(as.length == 2);
+        check(((ParamAnno)as[0]).value().equals("z"));
+        check(((ParamAnno2)as[1]).value() == 4);
+    }
+
+    private static void testGetAnno() {
+        TypeVariable<?>[] ts = TypeParam.class.getTypeParameters();
+        ParamAnno a;
+        a = ts[0].getAnnotation(ParamAnno.class);
+        check(a.value().equals("t"));
+    }
+    private static void testGetAnnos() throws Exception {
+        TypeVariable<?>[] ts = TypeParam.class.getDeclaredMethod("foo").getTypeParameters();
+        ParamAnno2[] as;
+        as = ts[0].getAnnotations(ParamAnno2.class);
+        check(as.length == 1);
+        check(as[0].value() == 3);
+    }
+}
+
+class TypeParam <@ParamAnno("t") @ParamAnno2(1) T,
+                 U,
+                 @ParamAnno("v") @ParamAnno2(2) V extends Runnable> {
+    public <@ParamAnno("x") @ParamAnno2(3) X,
+            Y,
+            @ParamAnno("z") @ParamAnno2(4) Z extends Cloneable> void foo() {}
+}
+
+@Target(ElementType.TYPE_PARAMETER)
+@Retention(RetentionPolicy.RUNTIME)
+@interface ParamAnno {
+    String value();
+}
+
+@Target(ElementType.TYPE_PARAMETER)
+@Retention(RetentionPolicy.RUNTIME)
+@interface ParamAnno2 {
+    int value();
+}