JDK-8336794 : Remodel TypeAnnotation to "have" instead of "be" an Annotation
  • Type: CSR
  • Component: core-libs
  • Sub-Component: java.lang.classfile
  • Priority: P4
  • Status: Closed
  • Resolution: Approved
  • Fix Versions: 24
  • Submitted: 2024-07-19
  • Updated: 2024-08-17
  • Resolved: 2024-08-16
Related Reports
CSR :  
Relates :  
Relates :  
Relates :  
Description
Summary
-------

`java.lang.classfile.TypeAnnotation` now models a `type_annotation` structure; it no longer inherits `java.lang.classfile.Annotation`, and now has a new method `Annotation annotation()`. The specification of other Annotation model classes are updated.

Problem
-------

1. `TypeAnnotation` is not substitutable as `Annotation` anywhere; for example, in `AnnotationValue.ofAnnotation`, `TypeAnnotation` can be passed, but type information will be lost, which is undesirable.

2. `Annotation` models more than just the declaration annotations that it claims to model. In addition, default values and repeatable annotations need special attention.

3. `Annotation` and `TypeAnnotation` don't clearly indicate which class file structures they correspond to.

4. `AnnotationElement` is element-value pair instead of key-value pair, and there are many other misusage of terms.

5. The conventional element name "value" should be noted for single-element annotations.

Solution
--------

1. Remodel `TypeAnnotation` to no longer extend `Annotation` and instead contain an `Annotation`. Remove the factory methods that take annotation components, and add one that takes a complete `Annotation` as the type annotation.

2. `TypeAnnotation` is specified to model the `type_annotation` structure. It's noted to be able to reconstruct a type annotation with contextual information.

3. `Annotation` is specified to model the `annotation` structure or part of `type_annotation` structure; It's noted to be able to reconstruct an annotation with contextual information. There's added notes about representation of default values and occurrences of multiple repeatable annotations, that they derive from the contextual annotation interface definition. Changed references to "annotation class" to "annotation interface".

4. Change improper terminologies, such as "annotation class" to "annotation interface", "key-value" to "element-value pair", distinguish "annotation" and "annotation interface“, bad usages of "elements" to "values", etc. See the specification.

5. Added links to JVMS, names in JVMS, and specification for comparing with `equals` in annotation structure model classes. (Uses `JVMS {@jvms}` correct format)

6. Added notes for `AnnotationElement::name`, noting about the conventional `value` name.

Specification
-------------
    --- a/src/java.base/share/classes/java/lang/classfile/Annotation.java
    +++ b/src/java.base/share/classes/java/lang/classfile/Annotation.java
    @@ -37,43 +37,60 @@
     import jdk.internal.javac.PreviewFeature;
     
     /**
    - * Models an annotation on a declaration.
    + * Models an {@code annotation} structure (JVMS {@jvms 4.7.16}) or part of a {@code
    + * type_annotation} structure (JVMS {@jvms 4.7.20}). This model indicates the
    + * interface of the annotation and a set of element-value pairs.
    + * <p>
    + * This model can reconstruct an annotation, given the location of the modeled structure
    + * in the class file and the definition of the annotation interface.
    + * <p>
    + * Two {@code Annotation} objects should be compared using the {@link
    + * Object#equals(Object) equals} method.
    + *
    + * @apiNote
    + * For Java programs, the location of the modeled structure indicates the source code
    + * element or type (JLS {@jls 9.7.4}) on which the reconstructed annotation appears,
    + * and the annotation interface definition determines whether the reconstructed annotation has
    + * elements with default values (JLS {@jls 9.6.2}), and whether the reconstructed annotation
    + * is a container annotation for multiple annotations (JLS {@jls 9.7.5}).
      *
      * @see AnnotationElement
      * @see AnnotationValue
    + * @see TypeAnnotation
      * @see RuntimeVisibleAnnotationsAttribute
      * @see RuntimeInvisibleAnnotationsAttribute
      * @see RuntimeVisibleParameterAnnotationsAttribute
      * @see RuntimeInvisibleParameterAnnotationsAttribute
      *
    - * @sealedGraph
      * @since 22
      */
     @PreviewFeature(feature = PreviewFeature.Feature.CLASSFILE_API)
     public sealed interface Annotation
    -        permits TypeAnnotation, AnnotationImpl {
    +        permits AnnotationImpl {
     
         /**
    -     * {@return the class of the annotation}
    +     * {@return the constant pool entry holding the {@linkplain Class#descriptorString
    +     * descriptor string} of the annotation interface}
          */
         Utf8Entry className();
     
         /**
    -     * {@return the class of the annotation, as a symbolic descriptor}
    +     * {@return the annotation interface, as a symbolic descriptor}
          */
         default ClassDesc classSymbol() {
             return ClassDesc.ofDescriptor(className().stringValue());
         }
     
         /**
    -     * {@return the elements of the annotation}
    +     * {@return the element-value pairs of the annotation}
          */
         List<AnnotationElement> elements();
     
         /**
          * {@return an annotation}
    -     * @param annotationClass the class of the annotation
    -     * @param elements the elements of the annotation
    +     * @param annotationClass the constant pool entry holding the descriptor string
    +     *                        of the annotation interface
    +     * @param elements the element-value pairs of the annotation
          */
         static Annotation of(Utf8Entry annotationClass,
                              List<AnnotationElement> elements) {
    @@ -82,8 +99,9 @@ static Annotation of(Utf8Entry annotationClass,
     
         /**
          * {@return an annotation}
    -     * @param annotationClass the class of the annotation
    -     * @param elements the elements of the annotation
    +     * @param annotationClass the constant pool entry holding the descriptor string
    +     *                        of the annotation interface
    +     * @param elements the element-value pairs of the annotation
          */
         static Annotation of(Utf8Entry annotationClass,
                              AnnotationElement... elements) {
    @@ -92,8 +110,8 @@ static Annotation of(Utf8Entry annotationClass,
     
         /**
          * {@return an annotation}
    -     * @param annotationClass the class of the annotation
    -     * @param elements the elements of the annotation
    +     * @param annotationClass the descriptor of the annotation interface
    +     * @param elements the element-value pairs of the annotation
          */
         static Annotation of(ClassDesc annotationClass,
                              List<AnnotationElement> elements) {
    @@ -102,8 +120,8 @@ static Annotation of(ClassDesc annotationClass,
     
         /**
          * {@return an annotation}
    -     * @param annotationClass the class of the annotation
    -     * @param elements the elements of the annotation
    +     * @param annotationClass the descriptor of the annotation interface
    +     * @param elements the element-value pairs of the annotation
          */
         static Annotation of(ClassDesc annotationClass,
                              AnnotationElement... elements) {
    --- a/src/java.base/share/classes/java/lang/classfile/AnnotationElement.java
    +++ b/src/java.base/share/classes/java/lang/classfile/AnnotationElement.java
    @@ -32,7 +32,13 @@
     import jdk.internal.javac.PreviewFeature;
     
     /**
    - * Models a key-value pair of an annotation.
    + * Models an element-value pair in the {@code element_value_pairs}
    + * table in the {@code annotation} structure defined in JVMS
    + * {@jvms 4.7.16} or the {@code type_annotation} structure defined
    + * in JVMS {@jvms 4.7.20}.
    + * <p>
    + * Two {@code AnnotationElement} objects should be compared using the
    + * {@link Object#equals(Object) equals} method.
      *
      * @see Annotation
      * @see AnnotationValue
    @@ -45,6 +51,12 @@ public sealed interface AnnotationElement
     
         /**
          * {@return the element name}
    +     *
    +     * @apiNote
    +     * In Java source code, by convention, the name of the sole element in a
    +     * single-element annotation interface is {@code value}. (JLS {@jls 9.6.1})
    +     * This is the case for single-element annotations (JLS {@jls 9.7.3}) and
    +     * container annotations for multiple annotations (JLS {@jls 9.6.3}).
          */
         Utf8Entry name();
     
    @@ -54,7 +66,7 @@ public sealed interface AnnotationElement
         AnnotationValue value();
     
         /**
    -     * {@return an annotation key-value pair}
    +     * {@return an element-value pair}
          * @param name the name of the key
          * @param value the associated value
          */
    @@ -64,7 +76,7 @@ static AnnotationElement of(Utf8Entry name,
         }
     
         /**
    -     * {@return an annotation key-value pair}
    +     * {@return an element-value pair}
          * @param name the name of the key
          * @param value the associated value
          */
    @@ -74,9 +86,10 @@ static AnnotationElement of(String name,
         }
     
         /**
    -     * {@return an annotation key-value pair for a class-valued annotation}
    +     * {@return an element-value pair for a class-valued element}
          * @param name the name of the key
          * @param value the associated value
    +     * @see AnnotationValue#ofClass(ClassDesc) AnnotationValue::ofClass
          */
         static AnnotationElement ofClass(String name,
                                          ClassDesc value) {
    @@ -84,9 +97,10 @@ static AnnotationElement ofClass(String name,
         }
     
         /**
    -     * {@return an annotation key-value pair for a string-valued annotation}
    +     * {@return an element-value pair for a string-valued element}
          * @param name the name of the key
          * @param value the associated value
    +     * @see AnnotationValue#ofString(String) AnnotationValue::ofString
          */
         static AnnotationElement ofString(String name,
                                           String value) {
    @@ -94,9 +108,10 @@ static AnnotationElement ofString(String name,
         }
     
         /**
    -     * {@return an annotation key-value pair for a long-valued annotation}
    +     * {@return an element-value pair for a long-valued element}
          * @param name the name of the key
          * @param value the associated value
    +     * @see AnnotationValue#ofLong(long) AnnotationValue::ofLong
          */
         static AnnotationElement ofLong(String name,
                                         long value) {
    @@ -104,9 +119,10 @@ static AnnotationElement ofLong(String name,
         }
     
         /**
    -     * {@return an annotation key-value pair for an int-valued annotation}
    +     * {@return an element-value pair for an int-valued element}
          * @param name the name of the key
          * @param value the associated value
    +     * @see AnnotationValue#ofInt(int) AnnotationValue::ofInt
          */
         static AnnotationElement ofInt(String name,
                                        int value) {
    @@ -114,9 +130,10 @@ static AnnotationElement ofInt(String name,
         }
     
         /**
    -     * {@return an annotation key-value pair for a char-valued annotation}
    +     * {@return an element-value pair for a char-valued element}
          * @param name the name of the key
          * @param value the associated value
    +     * @see AnnotationValue#ofChar(char) AnnotationValue::ofChar
          */
         static AnnotationElement ofChar(String name,
                                         char value) {
    @@ -124,9 +141,10 @@ static AnnotationElement ofChar(String name,
         }
     
         /**
    -     * {@return an annotation key-value pair for a short-valued annotation}
    +     * {@return an element-value pair for a short-valued element}
          * @param name the name of the key
          * @param value the associated value
    +     * @see AnnotationValue#ofShort(short) AnnotationValue::ofShort
          */
         static AnnotationElement ofShort(String name,
                                          short value) {
    @@ -134,29 +152,32 @@ static AnnotationElement ofShort(String name,
         }
     
         /**
    -     * {@return an annotation key-value pair for a byte-valued annotation}
    +     * {@return an element-value pair for a byte-valued element}
          * @param name the name of the key
          * @param value the associated value
    +     * @see AnnotationValue#ofByte(byte) AnnotationValue::ofByte
          */
         static AnnotationElement ofByte(String name,
    -                                      byte value) {
    +                                    byte value) {
             return of(name, AnnotationValue.ofByte(value));
         }
     
         /**
    -     * {@return an annotation key-value pair for a boolean-valued annotation}
    +     * {@return an element-value pair for a boolean-valued element}
          * @param name the name of the key
          * @param value the associated value
    +     * @see AnnotationValue#ofBoolean(boolean) AnnotationValue::ofBoolean
          */
         static AnnotationElement ofBoolean(String name,
    -                                      boolean value) {
    +                                       boolean value) {
             return of(name, AnnotationValue.ofBoolean(value));
         }
     
         /**
    -     * {@return an annotation key-value pair for a double-valued annotation}
    +     * {@return an element-value pair for a double-valued element}
          * @param name the name of the key
          * @param value the associated value
    +     * @see AnnotationValue#ofDouble(double) AnnotationValue::ofDouble
          */
         static AnnotationElement ofDouble(String name,
                                           double value) {
    @@ -164,9 +185,10 @@ static AnnotationElement ofDouble(String name,
         }
     
         /**
    -     * {@return an annotation key-value pair for a float-valued annotation}
    +     * {@return an element-value pair for a float-valued element}
          * @param name the name of the key
          * @param value the associated value
    +     * @see AnnotationValue#ofFloat(float) AnnotationValue::ofFloat
          */
         static AnnotationElement ofFloat(String name,
                                          float value) {
    @@ -174,9 +196,10 @@ static AnnotationElement ofFloat(String name,
         }
     
         /**
    -     * {@return an annotation key-value pair for an annotation-valued annotation}
    +     * {@return an element-value pair for an annotation-valued element}
          * @param name the name of the key
          * @param value the associated value
    +     * @see AnnotationValue#ofAnnotation AnnotationValue::ofAnnotation
          */
         static AnnotationElement ofAnnotation(String name,
                                               Annotation value) {
    @@ -184,9 +207,10 @@ static AnnotationElement ofAnnotation(String name,
         }
     
         /**
    -     * {@return an annotation key-value pair for an array-valued annotation}
    +     * {@return an element-value pair for an array-valued element}
          * @param name the name of the key
          * @param values the associated values
    +     * @see AnnotationValue#ofArray(AnnotationValue...) AnnotationValue::ofArray
          */
         static AnnotationElement ofArray(String name,
                                          AnnotationValue... values) {
    --- a/src/java.base/share/classes/java/lang/classfile/AnnotationValue.java
    +++ b/src/java.base/share/classes/java/lang/classfile/AnnotationValue.java
    @@ -41,7 +41,11 @@
     import jdk.internal.javac.PreviewFeature;
     
     /**
    - * Models the value of a key-value pair of an annotation.
    + * Models an {@code element_value} structure, or a value of an element-value
    + * pair of an annotation, as defined in JVMS {@jvms 4.7.16.1}.
    + * <p>
    + * Two {@code AnnotationValue} objects should be compared using the {@link
    + * Object#equals(Object) equals} method.
      *
      * @see Annotation
      * @see AnnotationElement
    @@ -53,8 +57,8 @@
     public sealed interface AnnotationValue {
     
         /**
    -     * Models an annotation-valued element.
    -     * The {@linkplain #tag tag} of this element is {@value ClassFile#AEV_ANNOTATION}.
    +     * Models an annotation value of an element-value pair.
    +     * The {@linkplain #tag tag} of this value is {@value ClassFile#AEV_ANNOTATION}.
          *
          * @since 22
          */
    @@ -66,8 +70,8 @@ sealed interface OfAnnotation extends AnnotationValue
         }
     
         /**
    -     * Models an array-valued element.
    -     * The {@linkplain #tag tag} of this element is {@value ClassFile#AEV_ARRAY}.
    +     * Models an array value of an element-value pair.
    +     * The {@linkplain #tag tag} of this value is {@value ClassFile#AEV_ARRAY}.
          *
          * @since 22
          */
    @@ -79,13 +83,15 @@ sealed interface OfArray extends AnnotationValue
              *
              * @apiNote
              * All array elements derived from Java source code have the same type,
    -         * which must not be an array type. ({@jls 9.6.1})
    +         * which must not be an array type. ({@jls 9.6.1}) If such elements are
    +         * annotations, they have the same annotation interface; if such elements
    +         * are enum, they belong to the same enum class.
              */
             List<AnnotationValue> values();
         }
     
         /**
    -     * Models a constant-valued element.
    +     * Models a constant value of an element-value pair.
          *
          * @sealedGraph
          * @since 22
    @@ -123,8 +129,8 @@ sealed interface OfConstant
         }
     
         /**
    -     * Models a string-valued element.
    -     * The {@linkplain #tag tag} of this element is {@value ClassFile#AEV_STRING}.
    +     * Models a string value of an element-value pair.
    +     * The {@linkplain #tag tag} of this value is {@value ClassFile#AEV_STRING}.
          *
          * @since 22
          */
    @@ -151,8 +157,8 @@ default String resolvedValue() {
         }
     
         /**
    -     * Models a double-valued element.
    -     * The {@linkplain #tag tag} of this element is {@value ClassFile#AEV_DOUBLE}.
    +     * Models a double value of an element-value pair.
    +     * The {@linkplain #tag tag} of this value is {@value ClassFile#AEV_DOUBLE}.
          *
          * @since 22
          */
    @@ -179,8 +185,8 @@ default Double resolvedValue() {
         }
     
         /**
    -     * Models a float-valued element.
    -     * The {@linkplain #tag tag} of this element is {@value ClassFile#AEV_FLOAT}.
    +     * Models a float value of an element-value pair.
    +     * The {@linkplain #tag tag} of this value is {@value ClassFile#AEV_FLOAT}.
          *
          * @since 22
          */
    @@ -207,8 +213,8 @@ default Float resolvedValue() {
         }
     
         /**
    -     * Models a long-valued element.
    -     * The {@linkplain #tag tag} of this element is {@value ClassFile#AEV_LONG}.
    +     * Models a long value of an element-value pair.
    +     * The {@linkplain #tag tag} of this value is {@value ClassFile#AEV_LONG}.
          *
          * @since 22
          */
    @@ -235,8 +241,8 @@ default Long resolvedValue() {
         }
     
         /**
    -     * Models an int-valued element.
    -     * The {@linkplain #tag tag} of this element is {@value ClassFile#AEV_INT}.
    +     * Models an int value of an element-value pair.
    +     * The {@linkplain #tag tag} of this value is {@value ClassFile#AEV_INT}.
          *
          * @since 22
          */
    @@ -263,8 +269,8 @@ default Integer resolvedValue() {
         }
     
         /**
    -     * Models a short-valued element.
    -     * The {@linkplain #tag tag} of this element is {@value ClassFile#AEV_SHORT}.
    +     * Models a short value of an element-value pair.
    +     * The {@linkplain #tag tag} of this value is {@value ClassFile#AEV_SHORT}.
          *
          * @since 22
          */
    @@ -294,8 +300,8 @@ default Short resolvedValue() {
         }
     
         /**
    -     * Models a char-valued element.
    -     * The {@linkplain #tag tag} of this element is {@value ClassFile#AEV_CHAR}.
    +     * Models a char value of an element-value pair.
    +     * The {@linkplain #tag tag} of this value is {@value ClassFile#AEV_CHAR}.
          *
          * @since 22
          */
    @@ -325,8 +331,8 @@ default Character resolvedValue() {
         }
     
         /**
    -     * Models a byte-valued element.
    -     * The {@linkplain #tag tag} of this element is {@value ClassFile#AEV_BYTE}.
    +     * Models a byte value of an element-value pair.
    +     * The {@linkplain #tag tag} of this value is {@value ClassFile#AEV_BYTE}.
          *
          * @since 22
          */
    @@ -356,8 +362,8 @@ default Byte resolvedValue() {
         }
     
         /**
    -     * Models a boolean-valued element.
    -     * The {@linkplain #tag tag} of this element is {@value ClassFile#AEV_BOOLEAN}.
    +     * Models a boolean value of an element-value pair.
    +     * The {@linkplain #tag tag} of this value is {@value ClassFile#AEV_BOOLEAN}.
          *
          * @since 22
          */
    @@ -387,8 +393,8 @@ default Boolean resolvedValue() {
         }
     
         /**
    -     * Models a class-valued element.
    -     * The {@linkplain #tag tag} of this element is {@value ClassFile#AEV_CLASS}.
    +     * Models a class value of an element-value pair.
    +     * The {@linkplain #tag tag} of this value is {@value ClassFile#AEV_CLASS}.
          *
          * @since 22
          */
    @@ -405,8 +411,8 @@ default ClassDesc classSymbol() {
         }
     
         /**
    -     * Models an enum-valued element.
    -     * The {@linkplain #tag tag} of this element is {@value ClassFile#AEV_ENUM}.
    +     * Models an enum value of an element-value pair.
    +     * The {@linkplain #tag tag} of this value is {@value ClassFile#AEV_ENUM}.
          *
          * @since 22
          */
    @@ -426,12 +432,13 @@ default ClassDesc classSymbol() {
         }
     
         /**
    -     * {@return the tag character for this type as per {@jvms 4.7.16.1}}
    +     * {@return the tag character for this value as per JVMS {@jvms 4.7.16.1}}
    +     * The tag characters have a one-to-one mapping to the types of annotation element values.
          */
         char tag();
     
         /**
    -     * {@return an annotation element for a enum-valued element}
    +     * {@return an enum value for an element-value pair}
          * @param className the descriptor string of the enum class
          * @param constantName the name of the enum constant
          */
    @@ -441,7 +448,7 @@ static OfEnum ofEnum(Utf8Entry className,
         }
     
         /**
    -     * {@return an annotation element for a enum-valued element}
    +     * {@return an enum value for an element-value pair}
          * @param className the descriptor of the enum class
          * @param constantName the name of the enum constant
          */
    @@ -451,7 +458,7 @@ static OfEnum ofEnum(ClassDesc className, String constantName) {
         }
     
         /**
    -     * {@return an annotation element for a class-valued element}
    +     * {@return a class value for an element-value pair}
          * @param className the descriptor string of the class
          */
         static OfClass ofClass(Utf8Entry className) {
    @@ -459,7 +466,7 @@ static OfClass ofClass(Utf8Entry className) {
         }
     
         /**
    -     * {@return an annotation element for a class-valued element}
    +     * {@return a class value for an element-value pair}
          * @param className the descriptor of the class
          */
         static OfClass ofClass(ClassDesc className) {
    @@ -467,7 +474,7 @@ static OfClass ofClass(ClassDesc className) {
         }
     
         /**
    -     * {@return an annotation element for a string-valued element}
    +     * {@return a string value for an element-value pair}
          * @param value the string
          */
         static OfString ofString(Utf8Entry value) {
    @@ -475,7 +482,7 @@ static OfString ofString(Utf8Entry value) {
         }
     
         /**
    -     * {@return an annotation element for a string-valued element}
    +     * {@return a string value for an element-value pair}
          * @param value the string
          */
         static OfString ofString(String value) {
    @@ -483,7 +490,7 @@ static OfString ofString(String value) {
         }
     
         /**
    -     * {@return an annotation element for a double-valued element}
    +     * {@return a double value for an element-value pair}
          * @param value the double value
          */
         static OfDouble ofDouble(DoubleEntry value) {
    @@ -491,7 +498,7 @@ static OfDouble ofDouble(DoubleEntry value) {
         }
     
         /**
    -     * {@return an annotation element for a double-valued element}
    +     * {@return a double value for an element-value pair}
          * @param value the double value
          */
         static OfDouble ofDouble(double value) {
    @@ -499,7 +506,7 @@ static OfDouble ofDouble(double value) {
         }
     
         /**
    -     * {@return an annotation element for a float-valued element}
    +     * {@return a float value for an element-value pair}
          * @param value the float value
          */
         static OfFloat ofFloat(FloatEntry value) {
    @@ -507,7 +514,7 @@ static OfFloat ofFloat(FloatEntry value) {
         }
     
         /**
    -     * {@return an annotation element for a float-valued element}
    +     * {@return a float value for an element-value pair}
          * @param value the float value
          */
         static OfFloat ofFloat(float value) {
    @@ -515,7 +522,7 @@ static OfFloat ofFloat(float value) {
         }
     
         /**
    -     * {@return an annotation element for a long-valued element}
    +     * {@return a long value for an element-value pair}
          * @param value the long value
          */
         static OfLong ofLong(LongEntry value) {
    @@ -523,7 +530,7 @@ static OfLong ofLong(LongEntry value) {
         }
     
         /**
    -     * {@return an annotation element for a long-valued element}
    +     * {@return a long value for an element-value pair}
          * @param value the long value
          */
         static OfLong ofLong(long value) {
    @@ -531,7 +538,7 @@ static OfLong ofLong(long value) {
         }
     
         /**
    -     * {@return an annotation element for an int-valued element}
    +     * {@return an int value for an element-value pair}
          * @param value the int value
          */
         static OfInt ofInt(IntegerEntry value) {
    @@ -539,7 +546,7 @@ static OfInt ofInt(IntegerEntry value) {
         }
     
         /**
    -     * {@return an annotation element for an int-valued element}
    +     * {@return an int value for an element-value pair}
          * @param value the int value
          */
         static OfInt ofInt(int value) {
    @@ -547,7 +554,7 @@ static OfInt ofInt(int value) {
         }
     
         /**
    -     * {@return an annotation element for a short-valued element}
    +     * {@return a short value for an element-value pair}
          * @param value the short value
          */
         static OfShort ofShort(IntegerEntry value) {
    @@ -555,7 +562,7 @@ static OfShort ofShort(IntegerEntry value) {
         }
     
         /**
    -     * {@return an annotation element for a short-valued element}
    +     * {@return a short value for an element-value pair}
          * @param value the short value
          */
         static OfShort ofShort(short value) {
    @@ -563,7 +570,7 @@ static OfShort ofShort(short value) {
         }
     
         /**
    -     * {@return an annotation element for a char-valued element}
    +     * {@return a char value for an element-value pair}
          * @param value the char value
          */
         static OfChar ofChar(IntegerEntry value) {
    @@ -571,7 +578,7 @@ static OfChar ofChar(IntegerEntry value) {
         }
     
         /**
    -     * {@return an annotation element for a char-valued element}
    +     * {@return a char value for an element-value pair}
          * @param value the char value
          */
         static OfChar ofChar(char value) {
    @@ -579,7 +586,7 @@ static OfChar ofChar(char value) {
         }
     
         /**
    -     * {@return an annotation element for a byte-valued element}
    +     * {@return a byte value for an element-value pair}
          * @param value the byte value
          */
         static OfByte ofByte(IntegerEntry value) {
    @@ -587,7 +594,7 @@ static OfByte ofByte(IntegerEntry value) {
         }
     
         /**
    -     * {@return an annotation element for a byte-valued element}
    +     * {@return a byte value for an element-value pair}
          * @param value the byte value
          */
         static OfByte ofByte(byte value) {
    @@ -595,7 +602,7 @@ static OfByte ofByte(byte value) {
         }
     
         /**
    -     * {@return an annotation element for a boolean-valued element}
    +     * {@return a boolean value for an element-value pair}
          * @param value the boolean value
          */
         static OfBoolean ofBoolean(IntegerEntry value) {
    @@ -603,7 +610,7 @@ static OfBoolean ofBoolean(IntegerEntry value) {
         }
     
         /**
    -     * {@return an annotation element for a boolean-valued element}
    +     * {@return a boolean value for an element-value pair}
          * @param value the boolean value
          */
         static OfBoolean ofBoolean(boolean value) {
    @@ -612,7 +619,7 @@ static OfBoolean ofBoolean(boolean value) {
         }
     
         /**
    -     * {@return an annotation element for an annotation-valued element}
    +     * {@return an annotation value for an element-value pair}
          * @param value the annotation
          */
         static OfAnnotation ofAnnotation(Annotation value) {
    @@ -620,7 +627,12 @@ static OfAnnotation ofAnnotation(Annotation value) {
         }
     
         /**
    -     * {@return an annotation element for an array-valued element}
    +     * {@return an array value for an element-value pair}
    +     *
    +     * @apiNote
    +     * See {@link AnnotationValue.OfArray#values() values()} for conventions
    +     * on array values derived from Java source code.
    +     *
          * @param values the array elements
          */
         static OfArray ofArray(List<AnnotationValue> values) {
    @@ -628,7 +640,12 @@ static OfArray ofArray(List<AnnotationValue> values) {
         }
     
         /**
    -     * {@return an annotation element for an array-valued element}
    +     * {@return an array value for an element-value pair}
    +     *
    +     * @apiNote
    +     * See {@link AnnotationValue.OfArray#values() values()} for conventions
    +     * on array values derived from Java source code.
    +     *
          * @param values the array elements
          */
         static OfArray ofArray(AnnotationValue... values) {
    --- a/src/java.base/share/classes/java/lang/classfile/TypeAnnotation.java
    +++ b/src/java.base/share/classes/java/lang/classfile/TypeAnnotation.java
     
     /**
    - * Models an annotation on a type use, as defined in {@jvms 4.7.19} and {@jvms 4.7.20}.
    + * Models a {@code type_annotation} structure (JVMS {@jvms 4.7.20}). This model
    + * indicates the annotated type within a declaration or expression and the part
    + * of the indicated type that is annotated, in addition to what is {@linkplain
    + * #annotation() available} in an {@code Annotation}.
    + * <p>
    + * This model can reconstruct an annotation on a type or a part of a type, given
    + * the location of the {@code type_annotation} structure in the class file and
    + * the definition of the annotation interface.
    + * <p>
    + * Two {@code TypeAnnotation} objects should be compared using the {@link
    + * Object#equals(Object) equals} method.
      *
    + * @see Annotation
      * @see RuntimeVisibleTypeAnnotationsAttribute
      * @see RuntimeInvisibleTypeAnnotationsAttribute
      *
    @@ -69,7 +77,6 @@
      */
     @PreviewFeature(feature = PreviewFeature.Feature.CLASSFILE_API)
     public sealed interface TypeAnnotation
    -        extends Annotation
             permits UnboundAttribute.UnboundTypeAnnotation {
     
         /**
    @@ -170,7 +177,7 @@ public int sizeIfFixed() {
     
         /**
          * {@return information describing precisely which type in a declaration or expression
    -     * is annotated}
    +     * is annotated} This models the {@code target_type} and {@code target_info} items.
          */
         TargetInfo targetInfo();
     
    @@ -180,57 +187,22 @@ public int sizeIfFixed() {
         List<TypePathComponent> targetPath();
     
         /**
    -     * {@return a type annotation}
    -     * @param targetInfo which type in a declaration or expression is annotated
    -     * @param targetPath which part of the type is annotated
    -     * @param annotationClassUtf8Entry the annotation class
    -     * @param annotationElements the annotation elements
    -     */
    -    static TypeAnnotation of(TargetInfo targetInfo, List<TypePathComponent> targetPath,
    -                             Utf8Entry annotationClassUtf8Entry,
    -                             List<AnnotationElement> annotationElements) {
    -        return new UnboundAttribute.UnboundTypeAnnotation(targetInfo, targetPath,
    -                annotationClassUtf8Entry, annotationElements);
    -    }
    -
    -    /**
    -     * {@return a type annotation}
    -     * @param targetInfo which type in a declaration or expression is annotated
    -     * @param targetPath which part of the type is annotated
    -     * @param annotationClass the annotation class
    -     * @param annotationElements the annotation elements
    -     */
    -    static TypeAnnotation of(TargetInfo targetInfo, List<TypePathComponent> targetPath,
    -                             ClassDesc annotationClass,
    -                             AnnotationElement... annotationElements) {
    -        return of(targetInfo, targetPath, annotationClass, List.of(annotationElements));
    -    }
    -
    -    /**
    -     * {@return a type annotation}
    -     * @param targetInfo which type in a declaration or expression is annotated
    -     * @param targetPath which part of the type is annotated
    -     * @param annotationClass the annotation class
    -     * @param annotationElements the annotation elements
    -     */
    -    static TypeAnnotation of(TargetInfo targetInfo, List<TypePathComponent> targetPath,
    -                             ClassDesc annotationClass,
    -                             List<AnnotationElement> annotationElements) {
    -        return of(targetInfo, targetPath,
    -                TemporaryConstantPool.INSTANCE.utf8Entry(annotationClass.descriptorString()), annotationElements);
    -    }
    +     * {@return the annotation applied to the part indicated by {@link #targetPath()}}
    +     * This models the interface of the annotation and the set of element-value pairs,
    +     * the subset of the {@code type_annotation} structure that is identical to the
    +     * {@code annotation} structure.
    +     */
    +    Annotation annotation();
     
         /**
    -     * {@return a type annotation}
    +     * {@return a {@code type_annotation} structure}
          * @param targetInfo which type in a declaration or expression is annotated
          * @param targetPath which part of the type is annotated
    -     * @param annotationClassUtf8Entry the annotation class
    -     * @param annotationElements the annotation elements
    +     * @param annotation the annotation
          */
         static TypeAnnotation of(TargetInfo targetInfo, List<TypePathComponent> targetPath,
    -                             Utf8Entry annotationClassUtf8Entry,
    -                             AnnotationElement... annotationElements) {
    -        return of(targetInfo, targetPath, annotationClassUtf8Entry, List.of(annotationElements));
    +                             Annotation annotation) {
    +        return new UnboundAttribute.UnboundTypeAnnotation(targetInfo, targetPath, annotation);
         }
     
         /**
    
Comments
Moving to Approved; thanks [~liach] for making the additional edits.
16-08-2024

I have vastly simplified the specifications to adhere more closely to the JVMS, and added some JLS-specific notes to the API notes sections as a few short sentences. Users may go to the JLS links if they wish to learn more. Also fixed a few more bad terms in `AnnotationValue` and fixed the JLS and JVMS inline tag formats.
13-08-2024

PS [~liach], please also make the sort of changes being under JDK-8338014 for the PR and CSR for this work.
12-08-2024

Okay, so to make progress on this specific CSR, I recommend replacing + * <p> + * Each {@code annotation} structure denotes an annotation that applies to a + ... with something like. + * apiNote + * For discussion purposes, examples from the Java programming language will be used. Other languages + * may have a different mapping of language-level annotations to structures in the class file. + * Each {@code annotation} structure denotes an annotation that applies to a + ... Additionally, a separate bug can be filed to add a package-level disclaimer contrasting the modeling approach of the class file API with that of core reflection; see the sort of changes done under JDK-8262807. What do you think?
12-08-2024

java.lang.classfile.Annotation instance plus the live annotation interface java.lang.Class object are sufficient to construct a correct implementation of an annotation for core reflection, and there is a specification around such a translation. However, it is not clear if such specification should be associated with ClassFile API or core reflection. Similarly, specifications for the translation of Java source code annotations to class file elements may be either at language specification or the ClassFile API. I believe that the ClassFile API refers to the JVMS for specification, while the information about Java Language Specification or core reflection might reside in respective areas or brought up in API Notes if they are of particular interest (such as repeatable annotations or default values), but not as strong as part of the ClassFile API specification.
09-08-2024

Additional comment: For possible follow-up work, has usage of the class file API so far indicated there would be any utility to build a java.lang.annotation.Annotation annotation from a java.lang.classfile.Annotation?
09-08-2024

Moving to Provisional, not Approved. I think a way to address one point needs to be resolved before this change can be Approved. This API is explicitly for Java *class files* and discuses that in the package-level document and elsewhere. This is a clarify of purpose not found in the core reflection API which, for historical reasons, presents a more blended Java language/Java Virtual machine viewpoint. In any case, I think the discussion of Java *source files* in this API is somewhat off-topic, or at least should contain some disclaimers "The following statements are true of the Java source language. Any similarity to other languages, living or dead, is purely coincidental ..." If there was a general disclaimer in the package-level "At times this API will use examples from the Java source language for convenience. Mapping of other languages to Java class files may or may not follow similar patterns, etc.", that disclaimer could be linked to from here rather than the disclaimer appearing here before the example. Any comments [~abuckley]? If the chosen path would evolve writing a non-trivial amount of new text, I can approve this CSR once a follow-up bug targeted to JDK 24 is filed.
08-08-2024

I have identified a few other points that need improvement and have incorporated them into the CSR, in addition to your suggestion about default values and repeatable annotations. This is up for reviewal again after Alex reviewed the spec wording.
02-08-2024

PS An additional review comment, for text like: 46 * Each {@code annotation} structure denotes an annotation that applies to a 47 * construct in Java source code ({@jls 9.7.4}). 48 * Similarly, each {@code type_annotation} structure denotes an annotation 49 * that applies to a type in Java source code. 50 * In either case, the structure indicates the interface of the annotation 51 * and a set of element-value pairs. it might be worth briefly acknowledging repeated annotations. In particular, to note that in the class file, the container annotation will be present rather than multiply instances of the contained annotation.
30-07-2024

> A true annotation can have some nontrivial amount of processing to fill in defaults, etc. so unless that is being done, there may be some utility in separating something that mean "raw-ish data that is used to create annotation" and actual annotations, especially is creating actual annotations is a possible feature at some point. The ClassFile API is not responsible for creating live annotations, unlike in javac's javax.lang,model API. An annotation interface definition is required to create a live annotation, yet such a definition already carries information necessary to fill in all default values. So this key-value pair model is an annotation, and the Annotation-AnnotationMirror distinction applicable to javac does not apply to the ClassFile API. And in offline conversations, I was informed that the `Annotation` name was already approved in previous CSR reviews for the initial previews and the reviews on earlier prototypes.
30-07-2024

Note that the fact that `Annotation` was approved in earlier iterations of this name does not imply the naming and other aspects of the API aren't subject to additional comments on re-review.
30-07-2024

Over in `javax.lang.model`, we have both `java.lang.annotation.Annotation` object being returned (created independently from core reflection annotation) as well as `AnnotationMirror` objects that more directly model what appears in the source code. A true annotation can have some nontrivial amount of processing to fill in defaults, etc. so unless that is being done, there may be some utility in separating something that mean "raw-ish data that is used to create annotation" and actual annotations, especially is creating actual annotations is a possible feature at some point.
30-07-2024

Maybe your consideration is that `Annotation` simple name is shared by `java.lang.annotation.Annotation` and `java.lang.classfile.Annotation`; similar problem happens with `Signature`, with the one in `java.security`. As far as I know, we have `ClassModel` `MethodModel` etc to avoid name clashes with `Class` and `Method`. In this case, we might rename `Annotation` to `AnnotationModel` like `AnnotationMirror` if this is problematic; there are a few cases where these 2 classes are used together, such as in `java.lang.annotation` tests.
29-07-2024

I think the term "annotation" is the best: - "annotation" is not ambiguous in the class file context too; there is apparently nothing else called annotation in the Class File format. - "annotation struct" refers to `annotation` structure, but `Annotation` can be part of the `type_annotation` structure that overlaps with `annotation` structure as well. - "annotation attribute" is only confusing, as "attribute" is another type of construct in the Class File format; all `annotation` or `type_annotaion` structs appear in different attributes.
29-07-2024

Moving to Provisional, not Approved. Hmm. Is the term best used to describe these types an "annotation" or something like an "annotation struct" or "annotation attrib(ute)"?
29-07-2024

Re-finalized after formatting the updated specs from Alex.
24-07-2024