diff --git a/src/java.base/share/classes/java/lang/classfile/AnnotationValue.java b/src/java.base/share/classes/java/lang/classfile/AnnotationValue.java index 919c8a0441d..a4a1c218ac1 100644 --- a/src/java.base/share/classes/java/lang/classfile/AnnotationValue.java +++ b/src/java.base/share/classes/java/lang/classfile/AnnotationValue.java @@ -26,6 +26,7 @@ package java.lang.classfile; import java.lang.classfile.constantpool.AnnotationConstantValueEntry; import java.lang.classfile.constantpool.DoubleEntry; +import java.lang.classfile.constantpool.DynamicConstantPoolEntry; import java.lang.classfile.constantpool.FloatEntry; import java.lang.classfile.constantpool.IntegerEntry; import java.lang.classfile.constantpool.LongEntry; @@ -34,7 +35,7 @@ import jdk.internal.classfile.impl.AnnotationImpl; import jdk.internal.classfile.impl.TemporaryConstantPool; import java.lang.constant.ClassDesc; -import java.lang.constant.ConstantDesc; +import java.lang.constant.Constable; import java.util.ArrayList; import java.util.List; import jdk.internal.javac.PreviewFeature; @@ -49,191 +50,373 @@ import jdk.internal.javac.PreviewFeature; * @since 22 */ @PreviewFeature(feature = PreviewFeature.Feature.CLASSFILE_API) -public sealed interface AnnotationValue - permits AnnotationValue.OfAnnotation, AnnotationValue.OfArray, - AnnotationValue.OfConstant, AnnotationValue.OfClass, - AnnotationValue.OfEnum { +public sealed interface AnnotationValue { /** - * Models an annotation-valued element + * Models an annotation-valued element. + * The {@linkplain #tag tag} of this element is {@value ClassFile#AEV_ANNOTATION}. * * @since 22 */ @PreviewFeature(feature = PreviewFeature.Feature.CLASSFILE_API) sealed interface OfAnnotation extends AnnotationValue permits AnnotationImpl.OfAnnotationImpl { - /** {@return the annotation} */ + /** {@return the annotation value} */ Annotation annotation(); } /** - * Models an array-valued element + * Models an array-valued element. + * The {@linkplain #tag tag} of this element is {@value ClassFile#AEV_ARRAY}. * * @since 22 */ @PreviewFeature(feature = PreviewFeature.Feature.CLASSFILE_API) sealed interface OfArray extends AnnotationValue permits AnnotationImpl.OfArrayImpl { - /** {@return the values} */ + /** + * {@return the array elements of the array value} + * + * @apiNote + * All array elements derived from Java source code have the same type, + * which must not be an array type. ({@jls 9.6.1}) + */ List values(); } /** - * Models a constant-valued element + * Models a constant-valued element. * * @sealedGraph * @since 22 */ @PreviewFeature(feature = PreviewFeature.Feature.CLASSFILE_API) - sealed interface OfConstant extends AnnotationValue - permits AnnotationValue.OfString, AnnotationValue.OfDouble, - AnnotationValue.OfFloat, AnnotationValue.OfLong, - AnnotationValue.OfInteger, AnnotationValue.OfShort, - AnnotationValue.OfCharacter, AnnotationValue.OfByte, - AnnotationValue.OfBoolean, AnnotationImpl.OfConstantImpl { - /** {@return the constant} */ + sealed interface OfConstant + extends AnnotationValue + permits OfString, OfDouble, OfFloat, OfLong, OfInt, OfShort, OfChar, OfByte, + OfBoolean, AnnotationImpl.OfConstantImpl { + /** + * {@return the constant pool entry backing this constant element} + * + * @apiNote + * Different types of constant values may share the same type of entry. + * For example, {@link OfInt} and {@link OfChar} are both + * backed by {@link IntegerEntry}. Use {@link #resolvedValue + * resolvedValue()} for a value of accurate type. + */ AnnotationConstantValueEntry constant(); - /** {@return the constant} */ - ConstantDesc constantValue(); + + /** + * {@return the resolved live constant value, as an object} The type of + * the returned value may be a wrapper class or {@link String}. + * + * @apiNote + * The returned object, despite being {@link Constable}, may not + * {@linkplain Constable#describeConstable() describe} the right constant + * for encoding the annotation value in a class file. For example, + * {@link Character} returned by {@link OfChar} describes itself as a + * {@link DynamicConstantPoolEntry}, but it is actually backed by + * {@link IntegerEntry} in annotation format. + * Use {@link #constant constant()} for a correct constant pool representation. + */ + Constable resolvedValue(); } /** - * Models a constant-valued element + * Models a string-valued element. + * The {@linkplain #tag tag} of this element is {@value ClassFile#AEV_STRING}. * * @since 22 */ @PreviewFeature(feature = PreviewFeature.Feature.CLASSFILE_API) - sealed interface OfString extends AnnotationValue.OfConstant + sealed interface OfString extends OfConstant permits AnnotationImpl.OfStringImpl { - /** {@return the constant} */ + /** {@return the backing UTF8 entry} */ + @Override + Utf8Entry constant(); + + /** {@return the constant string value} */ String stringValue(); + + /** + * {@return the resolved string value} + * + * @implSpec + * This method returns the same as {@link #stringValue()}. + */ + @Override + default String resolvedValue() { + return stringValue(); + } } /** - * Models a constant-valued element + * Models a double-valued element. + * The {@linkplain #tag tag} of this element is {@value ClassFile#AEV_DOUBLE}. * * @since 22 */ @PreviewFeature(feature = PreviewFeature.Feature.CLASSFILE_API) - sealed interface OfDouble extends AnnotationValue.OfConstant + sealed interface OfDouble extends OfConstant permits AnnotationImpl.OfDoubleImpl { - /** {@return the constant} */ + /** {@return the backing double entry} */ + @Override + DoubleEntry constant(); + + /** {@return the constant double value} */ double doubleValue(); + + /** + * {@return the resolved double value} + * + * @implSpec + * This method returns the same as {@link #doubleValue()}. + */ + @Override + default Double resolvedValue() { + return doubleValue(); + } } /** - * Models a constant-valued element + * Models a float-valued element. + * The {@linkplain #tag tag} of this element is {@value ClassFile#AEV_FLOAT}. * * @since 22 */ @PreviewFeature(feature = PreviewFeature.Feature.CLASSFILE_API) - sealed interface OfFloat extends AnnotationValue.OfConstant + sealed interface OfFloat extends OfConstant permits AnnotationImpl.OfFloatImpl { - /** {@return the constant} */ + /** {@return the backing float entry} */ + @Override + FloatEntry constant(); + + /** {@return the constant float value} */ float floatValue(); + + /** + * {@return the resolved float value} + * + * @implSpec + * This method returns the same as {@link #floatValue()}. + */ + @Override + default Float resolvedValue() { + return floatValue(); + } } /** - * Models a constant-valued element + * Models a long-valued element. + * The {@linkplain #tag tag} of this element is {@value ClassFile#AEV_LONG}. * * @since 22 */ @PreviewFeature(feature = PreviewFeature.Feature.CLASSFILE_API) - sealed interface OfLong extends AnnotationValue.OfConstant + sealed interface OfLong extends OfConstant permits AnnotationImpl.OfLongImpl { - /** {@return the constant} */ + /** {@return the backing long entry} */ + @Override + LongEntry constant(); + + /** {@return the constant long value} */ long longValue(); + + /** + * {@return the resolved long value} + * + * @implSpec + * This method returns the same as {@link #longValue()}. + */ + @Override + default Long resolvedValue() { + return longValue(); + } } /** - * Models a constant-valued element + * Models an int-valued element. + * The {@linkplain #tag tag} of this element is {@value ClassFile#AEV_INT}. * * @since 22 */ @PreviewFeature(feature = PreviewFeature.Feature.CLASSFILE_API) - sealed interface OfInteger extends AnnotationValue.OfConstant - permits AnnotationImpl.OfIntegerImpl { - /** {@return the constant} */ + sealed interface OfInt extends OfConstant + permits AnnotationImpl.OfIntImpl { + /** {@return the backing integer entry} */ + @Override + IntegerEntry constant(); + + /** {@return the constant int value} */ int intValue(); + + /** + * {@return the resolved int value} + * + * @implSpec + * This method returns the same as {@link #intValue()}. + */ + @Override + default Integer resolvedValue() { + return intValue(); + } } /** - * Models a constant-valued element + * Models a short-valued element. + * The {@linkplain #tag tag} of this element is {@value ClassFile#AEV_SHORT}. * * @since 22 */ @PreviewFeature(feature = PreviewFeature.Feature.CLASSFILE_API) - sealed interface OfShort extends AnnotationValue.OfConstant + sealed interface OfShort extends OfConstant permits AnnotationImpl.OfShortImpl { - /** {@return the constant} */ + /** {@return the backing integer entry} */ + @Override + IntegerEntry constant(); + + /** + * {@return the constant short value} + * @jvms 2.11.1 Types and the Java Virtual Machine + */ short shortValue(); + + /** + * {@return the resolved short value} + * + * @implSpec + * This method returns the same as {@link #shortValue()}. + */ + @Override + default Short resolvedValue() { + return shortValue(); + } } /** - * Models a constant-valued element + * Models a char-valued element. + * The {@linkplain #tag tag} of this element is {@value ClassFile#AEV_CHAR}. * * @since 22 */ @PreviewFeature(feature = PreviewFeature.Feature.CLASSFILE_API) - sealed interface OfCharacter extends AnnotationValue.OfConstant - permits AnnotationImpl.OfCharacterImpl { - /** {@return the constant} */ + sealed interface OfChar extends OfConstant + permits AnnotationImpl.OfCharImpl { + /** {@return the backing integer entry} */ + @Override + IntegerEntry constant(); + + /** + * {@return the constant char value} + * @jvms 2.11.1 Types and the Java Virtual Machine + */ char charValue(); + + /** + * {@return the resolved char value} + * + * @implSpec + * This method returns the same as {@link #charValue()}. + */ + @Override + default Character resolvedValue() { + return charValue(); + } } /** - * Models a constant-valued element + * Models a byte-valued element. + * The {@linkplain #tag tag} of this element is {@value ClassFile#AEV_BYTE}. * * @since 22 */ @PreviewFeature(feature = PreviewFeature.Feature.CLASSFILE_API) - sealed interface OfByte extends AnnotationValue.OfConstant + sealed interface OfByte extends OfConstant permits AnnotationImpl.OfByteImpl { - /** {@return the constant} */ + /** {@return the backing integer entry} */ + @Override + IntegerEntry constant(); + + /** + * {@return the constant byte value} + * @jvms 2.11.1 Types and the Java Virtual Machine + */ byte byteValue(); + + /** + * {@return the resolved byte value} + * + * @implSpec + * This method returns the same as {@link #byteValue()}. + */ + @Override + default Byte resolvedValue() { + return byteValue(); + } } /** - * Models a constant-valued element + * Models a boolean-valued element. + * The {@linkplain #tag tag} of this element is {@value ClassFile#AEV_BOOLEAN}. * * @since 22 */ @PreviewFeature(feature = PreviewFeature.Feature.CLASSFILE_API) - sealed interface OfBoolean extends AnnotationValue.OfConstant + sealed interface OfBoolean extends OfConstant permits AnnotationImpl.OfBooleanImpl { - /** {@return the constant} */ + /** {@return the backing integer entry} */ + @Override + IntegerEntry constant(); + + /** + * {@return the constant boolean value} + * @jvms 2.3.4 The boolean Type + */ boolean booleanValue(); + + /** + * {@return the resolved boolean value} + * + * @implSpec + * This method returns the same as {@link #booleanValue()}. + */ + @Override + default Boolean resolvedValue() { + return booleanValue(); + } } /** - * Models a class-valued element + * Models a class-valued element. + * The {@linkplain #tag tag} of this element is {@value ClassFile#AEV_CLASS}. * * @since 22 */ @PreviewFeature(feature = PreviewFeature.Feature.CLASSFILE_API) sealed interface OfClass extends AnnotationValue permits AnnotationImpl.OfClassImpl { - /** {@return the class name} */ + /** {@return the class descriptor string} */ Utf8Entry className(); - /** {@return the class symbol} */ + /** {@return the class descriptor} */ default ClassDesc classSymbol() { return ClassDesc.ofDescriptor(className().stringValue()); } } /** - * Models an enum-valued element + * Models an enum-valued element. + * The {@linkplain #tag tag} of this element is {@value ClassFile#AEV_ENUM}. * * @since 22 */ @PreviewFeature(feature = PreviewFeature.Feature.CLASSFILE_API) sealed interface OfEnum extends AnnotationValue permits AnnotationImpl.OfEnumImpl { - /** {@return the enum class name} */ + /** {@return the enum class descriptor string} */ Utf8Entry className(); - /** {@return the enum class symbol} */ + /** {@return the enum class descriptor} */ default ClassDesc classSymbol() { return ClassDesc.ofDescriptor(className().stringValue()); } @@ -249,7 +432,7 @@ public sealed interface AnnotationValue /** * {@return an annotation element for a enum-valued element} - * @param className the name of the enum class + * @param className the descriptor string of the enum class * @param constantName the name of the enum constant */ static OfEnum ofEnum(Utf8Entry className, @@ -259,7 +442,7 @@ public sealed interface AnnotationValue /** * {@return an annotation element for a enum-valued element} - * @param className the name of the enum class + * @param className the descriptor of the enum class * @param constantName the name of the enum constant */ static OfEnum ofEnum(ClassDesc className, String constantName) { @@ -269,7 +452,7 @@ public sealed interface AnnotationValue /** * {@return an annotation element for a class-valued element} - * @param className the name of the enum class + * @param className the descriptor string of the class */ static OfClass ofClass(Utf8Entry className) { return new AnnotationImpl.OfClassImpl(className); @@ -277,7 +460,7 @@ public sealed interface AnnotationValue /** * {@return an annotation element for a class-valued element} - * @param className the name of the enum class + * @param className the descriptor of the class */ static OfClass ofClass(ClassDesc className) { return ofClass(TemporaryConstantPool.INSTANCE.utf8Entry(className.descriptorString())); @@ -287,7 +470,7 @@ public sealed interface AnnotationValue * {@return an annotation element for a string-valued element} * @param value the string */ - static OfConstant ofString(Utf8Entry value) { + static OfString ofString(Utf8Entry value) { return new AnnotationImpl.OfStringImpl(value); } @@ -295,7 +478,7 @@ public sealed interface AnnotationValue * {@return an annotation element for a string-valued element} * @param value the string */ - static OfConstant ofString(String value) { + static OfString ofString(String value) { return ofString(TemporaryConstantPool.INSTANCE.utf8Entry(value)); } @@ -303,7 +486,7 @@ public sealed interface AnnotationValue * {@return an annotation element for a double-valued element} * @param value the double value */ - static OfConstant ofDouble(DoubleEntry value) { + static OfDouble ofDouble(DoubleEntry value) { return new AnnotationImpl.OfDoubleImpl(value); } @@ -311,7 +494,7 @@ public sealed interface AnnotationValue * {@return an annotation element for a double-valued element} * @param value the double value */ - static OfConstant ofDouble(double value) { + static OfDouble ofDouble(double value) { return ofDouble(TemporaryConstantPool.INSTANCE.doubleEntry(value)); } @@ -319,7 +502,7 @@ public sealed interface AnnotationValue * {@return an annotation element for a float-valued element} * @param value the float value */ - static OfConstant ofFloat(FloatEntry value) { + static OfFloat ofFloat(FloatEntry value) { return new AnnotationImpl.OfFloatImpl(value); } @@ -327,7 +510,7 @@ public sealed interface AnnotationValue * {@return an annotation element for a float-valued element} * @param value the float value */ - static OfConstant ofFloat(float value) { + static OfFloat ofFloat(float value) { return ofFloat(TemporaryConstantPool.INSTANCE.floatEntry(value)); } @@ -335,7 +518,7 @@ public sealed interface AnnotationValue * {@return an annotation element for a long-valued element} * @param value the long value */ - static OfConstant ofLong(LongEntry value) { + static OfLong ofLong(LongEntry value) { return new AnnotationImpl.OfLongImpl(value); } @@ -343,7 +526,7 @@ public sealed interface AnnotationValue * {@return an annotation element for a long-valued element} * @param value the long value */ - static OfConstant ofLong(long value) { + static OfLong ofLong(long value) { return ofLong(TemporaryConstantPool.INSTANCE.longEntry(value)); } @@ -351,15 +534,15 @@ public sealed interface AnnotationValue * {@return an annotation element for an int-valued element} * @param value the int value */ - static OfConstant ofInt(IntegerEntry value) { - return new AnnotationImpl.OfIntegerImpl(value); + static OfInt ofInt(IntegerEntry value) { + return new AnnotationImpl.OfIntImpl(value); } /** * {@return an annotation element for an int-valued element} * @param value the int value */ - static OfConstant ofInt(int value) { + static OfInt ofInt(int value) { return ofInt(TemporaryConstantPool.INSTANCE.intEntry(value)); } @@ -367,7 +550,7 @@ public sealed interface AnnotationValue * {@return an annotation element for a short-valued element} * @param value the short value */ - static OfConstant ofShort(IntegerEntry value) { + static OfShort ofShort(IntegerEntry value) { return new AnnotationImpl.OfShortImpl(value); } @@ -375,7 +558,7 @@ public sealed interface AnnotationValue * {@return an annotation element for a short-valued element} * @param value the short value */ - static OfConstant ofShort(short value) { + static OfShort ofShort(short value) { return ofShort(TemporaryConstantPool.INSTANCE.intEntry(value)); } @@ -383,15 +566,15 @@ public sealed interface AnnotationValue * {@return an annotation element for a char-valued element} * @param value the char value */ - static OfConstant ofChar(IntegerEntry value) { - return new AnnotationImpl.OfCharacterImpl(value); + static OfChar ofChar(IntegerEntry value) { + return new AnnotationImpl.OfCharImpl(value); } /** * {@return an annotation element for a char-valued element} * @param value the char value */ - static OfConstant ofChar(char value) { + static OfChar ofChar(char value) { return ofChar(TemporaryConstantPool.INSTANCE.intEntry(value)); } @@ -399,7 +582,7 @@ public sealed interface AnnotationValue * {@return an annotation element for a byte-valued element} * @param value the byte value */ - static OfConstant ofByte(IntegerEntry value) { + static OfByte ofByte(IntegerEntry value) { return new AnnotationImpl.OfByteImpl(value); } @@ -407,7 +590,7 @@ public sealed interface AnnotationValue * {@return an annotation element for a byte-valued element} * @param value the byte value */ - static OfConstant ofByte(byte value) { + static OfByte ofByte(byte value) { return ofByte(TemporaryConstantPool.INSTANCE.intEntry(value)); } @@ -415,7 +598,7 @@ public sealed interface AnnotationValue * {@return an annotation element for a boolean-valued element} * @param value the boolean value */ - static OfConstant ofBoolean(IntegerEntry value) { + static OfBoolean ofBoolean(IntegerEntry value) { return new AnnotationImpl.OfBooleanImpl(value); } @@ -423,7 +606,7 @@ public sealed interface AnnotationValue * {@return an annotation element for a boolean-valued element} * @param value the boolean value */ - static OfConstant ofBoolean(boolean value) { + static OfBoolean ofBoolean(boolean value) { int i = value ? 1 : 0; return ofBoolean(TemporaryConstantPool.INSTANCE.intEntry(i)); } @@ -438,7 +621,7 @@ public sealed interface AnnotationValue /** * {@return an annotation element for an array-valued element} - * @param values the values + * @param values the array elements */ static OfArray ofArray(List values) { return new AnnotationImpl.OfArrayImpl(values); @@ -446,7 +629,7 @@ public sealed interface AnnotationValue /** * {@return an annotation element for an array-valued element} - * @param values the values + * @param values the array elements */ static OfArray ofArray(AnnotationValue... values) { return ofArray(List.of(values)); diff --git a/src/java.base/share/classes/java/lang/classfile/constantpool/AnnotationConstantValueEntry.java b/src/java.base/share/classes/java/lang/classfile/constantpool/AnnotationConstantValueEntry.java index 3a7053a49f5..d405f68570e 100644 --- a/src/java.base/share/classes/java/lang/classfile/constantpool/AnnotationConstantValueEntry.java +++ b/src/java.base/share/classes/java/lang/classfile/constantpool/AnnotationConstantValueEntry.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2022, 2024, 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 @@ -24,13 +24,23 @@ */ package java.lang.classfile.constantpool; +import java.lang.classfile.AnnotationValue; import java.lang.constant.ConstantDesc; import jdk.internal.javac.PreviewFeature; /** - * A constant pool entry that may be used as an annotation constant, - * which includes the four kinds of primitive constants, and UTF8 constants. + * A constant pool entry that may be used by annotation constant values, + * which includes the four kinds of primitive constants and UTF8 constants. + * These entries are also the only entries that do not refer to other + * constant pool entries. * + * @apiNote + * An annotation constant value entry alone is not sufficient to determine + * the annotation constant; for example, an {@link IntegerEntry} of {@code 1} + * can mean {@code true} in {@link AnnotationValue.OfBoolean} or {@code 1} + * in {@link AnnotationValue.OfInt}. + * + * @see AnnotationValue.OfConstant * @sealedGraph * @since 22 */ @@ -40,7 +50,8 @@ public sealed interface AnnotationConstantValueEntry extends PoolEntry /** * {@return the constant value} The constant value will be an {@link Integer}, - * {@link Long}, {@link Float}, {@link Double}, or {@link String}. + * {@link Long}, {@link Float}, {@link Double} for the primitive constants, + * or {@link String} for UTF8 constants. */ ConstantDesc constantValue(); } diff --git a/src/java.base/share/classes/java/lang/classfile/constantpool/ConstantPoolBuilder.java b/src/java.base/share/classes/java/lang/classfile/constantpool/ConstantPoolBuilder.java index c0927175476..db77f8e2e8a 100644 --- a/src/java.base/share/classes/java/lang/classfile/constantpool/ConstantPoolBuilder.java +++ b/src/java.base/share/classes/java/lang/classfile/constantpool/ConstantPoolBuilder.java @@ -510,25 +510,6 @@ public sealed interface ConstantPoolBuilder throw new IllegalArgumentException("Illegal type: " + (c == null ? null : c.getClass())); } - /** - * {@return An {@link AnnotationConstantValueEntry} describing the provided - * constant} The constant should be an Integer, String, Long, Float, - * Double, ClassDesc (for a Class constant), or MethodTypeDesc (for a MethodType - * constant.) - * - * @param c the constant - */ - default AnnotationConstantValueEntry annotationConstantValueEntry(ConstantDesc c) { - if (c instanceof Integer i) return intEntry(i); - if (c instanceof String s) return utf8Entry(s); - if (c instanceof Long l) return longEntry(l); - if (c instanceof Float f) return floatEntry(f); - if (c instanceof Double d) return doubleEntry(d); - if (c instanceof ClassDesc cd) return utf8Entry(cd); - if (c instanceof MethodTypeDesc mtd) return utf8Entry(mtd); - throw new IllegalArgumentException("Illegal type: " + (c == null ? null : c.getClass())); - } - /** * {@return a {@link BootstrapMethodEntry} describing the provided * bootstrap method and static arguments} diff --git a/src/java.base/share/classes/jdk/internal/classfile/impl/AnnotationImpl.java b/src/java.base/share/classes/jdk/internal/classfile/impl/AnnotationImpl.java index 03353e272a6..794e7915960 100644 --- a/src/java.base/share/classes/jdk/internal/classfile/impl/AnnotationImpl.java +++ b/src/java.base/share/classes/jdk/internal/classfile/impl/AnnotationImpl.java @@ -27,7 +27,6 @@ package jdk.internal.classfile.impl; import java.lang.classfile.*; import java.lang.classfile.constantpool.*; -import java.lang.constant.ConstantDesc; import java.util.List; import static java.lang.classfile.ClassFile.*; @@ -80,12 +79,7 @@ public record AnnotationImpl(Utf8Entry className, List elemen } } - public sealed interface OfConstantImpl extends AnnotationValue.OfConstant, Util.Writable - permits AnnotationImpl.OfStringImpl, AnnotationImpl.OfDoubleImpl, - AnnotationImpl.OfFloatImpl, AnnotationImpl.OfLongImpl, - AnnotationImpl.OfIntegerImpl, AnnotationImpl.OfShortImpl, - AnnotationImpl.OfCharacterImpl, AnnotationImpl.OfByteImpl, - AnnotationImpl.OfBooleanImpl { + public sealed interface OfConstantImpl extends AnnotationValue.OfConstant, Util.Writable { @Override default void writeTo(BufWriterImpl buf) { @@ -93,15 +87,10 @@ public record AnnotationImpl(Utf8Entry className, List elemen buf.writeIndex(constant()); } - @Override - default ConstantDesc constantValue() { - return constant().constantValue(); - } - } public record OfStringImpl(Utf8Entry constant) - implements AnnotationImpl.OfConstantImpl, AnnotationValue.OfString { + implements OfConstantImpl, AnnotationValue.OfString { @Override public char tag() { @@ -115,7 +104,7 @@ public record AnnotationImpl(Utf8Entry className, List elemen } public record OfDoubleImpl(DoubleEntry constant) - implements AnnotationImpl.OfConstantImpl, AnnotationValue.OfDouble { + implements OfConstantImpl, AnnotationValue.OfDouble { @Override public char tag() { @@ -129,7 +118,7 @@ public record AnnotationImpl(Utf8Entry className, List elemen } public record OfFloatImpl(FloatEntry constant) - implements AnnotationImpl.OfConstantImpl, AnnotationValue.OfFloat { + implements OfConstantImpl, AnnotationValue.OfFloat { @Override public char tag() { @@ -143,7 +132,7 @@ public record AnnotationImpl(Utf8Entry className, List elemen } public record OfLongImpl(LongEntry constant) - implements AnnotationImpl.OfConstantImpl, AnnotationValue.OfLong { + implements OfConstantImpl, AnnotationValue.OfLong { @Override public char tag() { @@ -156,8 +145,8 @@ public record AnnotationImpl(Utf8Entry className, List elemen } } - public record OfIntegerImpl(IntegerEntry constant) - implements AnnotationImpl.OfConstantImpl, AnnotationValue.OfInteger { + public record OfIntImpl(IntegerEntry constant) + implements OfConstantImpl, AnnotationValue.OfInt { @Override public char tag() { @@ -171,7 +160,7 @@ public record AnnotationImpl(Utf8Entry className, List elemen } public record OfShortImpl(IntegerEntry constant) - implements AnnotationImpl.OfConstantImpl, AnnotationValue.OfShort { + implements OfConstantImpl, AnnotationValue.OfShort { @Override public char tag() { @@ -180,12 +169,12 @@ public record AnnotationImpl(Utf8Entry className, List elemen @Override public short shortValue() { - return (short)constant().intValue(); + return (short) constant().intValue(); } } - public record OfCharacterImpl(IntegerEntry constant) - implements AnnotationImpl.OfConstantImpl, AnnotationValue.OfCharacter { + public record OfCharImpl(IntegerEntry constant) + implements OfConstantImpl, AnnotationValue.OfChar { @Override public char tag() { @@ -194,12 +183,12 @@ public record AnnotationImpl(Utf8Entry className, List elemen @Override public char charValue() { - return (char)constant().intValue(); + return (char) constant().intValue(); } } public record OfByteImpl(IntegerEntry constant) - implements AnnotationImpl.OfConstantImpl, AnnotationValue.OfByte { + implements OfConstantImpl, AnnotationValue.OfByte { @Override public char tag() { @@ -208,12 +197,12 @@ public record AnnotationImpl(Utf8Entry className, List elemen @Override public byte byteValue() { - return (byte)constant().intValue(); + return (byte) constant().intValue(); } } public record OfBooleanImpl(IntegerEntry constant) - implements AnnotationImpl.OfConstantImpl, AnnotationValue.OfBoolean { + implements OfConstantImpl, AnnotationValue.OfBoolean { @Override public char tag() { @@ -222,15 +211,15 @@ public record AnnotationImpl(Utf8Entry className, List elemen @Override public boolean booleanValue() { - return constant().intValue() == 1; + return constant().intValue() != 0; } } public record OfArrayImpl(List values) implements AnnotationValue.OfArray, Util.Writable { - public OfArrayImpl(List values) { - this.values = List.copyOf(values); + public OfArrayImpl { + values = List.copyOf(values); } @Override diff --git a/src/java.base/share/classes/jdk/internal/classfile/impl/AnnotationReader.java b/src/java.base/share/classes/jdk/internal/classfile/impl/AnnotationReader.java index 2ada13aaba8..e21938bbc0c 100644 --- a/src/java.base/share/classes/jdk/internal/classfile/impl/AnnotationReader.java +++ b/src/java.base/share/classes/jdk/internal/classfile/impl/AnnotationReader.java @@ -60,10 +60,10 @@ public final class AnnotationReader { ++p; return switch (tag) { case AEV_BYTE -> new AnnotationImpl.OfByteImpl(classReader.readEntry(p, IntegerEntry.class)); - case AEV_CHAR -> new AnnotationImpl.OfCharacterImpl(classReader.readEntry(p, IntegerEntry.class)); + case AEV_CHAR -> new AnnotationImpl.OfCharImpl(classReader.readEntry(p, IntegerEntry.class)); case AEV_DOUBLE -> new AnnotationImpl.OfDoubleImpl(classReader.readEntry(p, DoubleEntry.class)); case AEV_FLOAT -> new AnnotationImpl.OfFloatImpl(classReader.readEntry(p, FloatEntry.class)); - case AEV_INT -> new AnnotationImpl.OfIntegerImpl(classReader.readEntry(p, IntegerEntry.class)); + case AEV_INT -> new AnnotationImpl.OfIntImpl(classReader.readEntry(p, IntegerEntry.class)); case AEV_LONG -> new AnnotationImpl.OfLongImpl(classReader.readEntry(p, LongEntry.class)); case AEV_SHORT -> new AnnotationImpl.OfShortImpl(classReader.readEntry(p, IntegerEntry.class)); case AEV_BOOLEAN -> new AnnotationImpl.OfBooleanImpl(classReader.readEntry(p, IntegerEntry.class)); diff --git a/src/java.base/share/classes/jdk/internal/classfile/impl/ClassPrinterImpl.java b/src/java.base/share/classes/jdk/internal/classfile/impl/ClassPrinterImpl.java index fac2eba95fe..75346dd5998 100644 --- a/src/java.base/share/classes/jdk/internal/classfile/impl/ClassPrinterImpl.java +++ b/src/java.base/share/classes/jdk/internal/classfile/impl/ClassPrinterImpl.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2022, 2024, 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 @@ -507,15 +507,15 @@ public final class ClassPrinterImpl { private static Node[] elementValueToTree(AnnotationValue v) { return switch (v) { - case OfString cv -> leafs("string", String.valueOf(cv.constantValue())); - case OfDouble cv -> leafs("double", String.valueOf(cv.constantValue())); - case OfFloat cv -> leafs("float", String.valueOf(cv.constantValue())); - case OfLong cv -> leafs("long", String.valueOf(cv.constantValue())); - case OfInteger cv -> leafs("int", String.valueOf(cv.constantValue())); - case OfShort cv -> leafs("short", String.valueOf(cv.constantValue())); - case OfCharacter cv -> leafs("char", String.valueOf(cv.constantValue())); - case OfByte cv -> leafs("byte", String.valueOf(cv.constantValue())); - case OfBoolean cv -> leafs("boolean", String.valueOf((int)cv.constantValue() != 0)); + case OfString cv -> leafs("string", String.valueOf(cv.stringValue())); + case OfDouble cv -> leafs("double", String.valueOf(cv.doubleValue())); + case OfFloat cv -> leafs("float", String.valueOf(cv.floatValue())); + case OfLong cv -> leafs("long", String.valueOf(cv.longValue())); + case OfInt cv -> leafs("int", String.valueOf(cv.intValue())); + case OfShort cv -> leafs("short", String.valueOf(cv.shortValue())); + case OfChar cv -> leafs("char", String.valueOf(cv.charValue())); + case OfByte cv -> leafs("byte", String.valueOf(cv.byteValue())); + case OfBoolean cv -> leafs("boolean", String.valueOf(cv.booleanValue())); case OfClass clv -> leafs("class", clv.className().stringValue()); case OfEnum ev -> leafs("enum class", ev.className().stringValue(), "constant name", ev.constantName().stringValue()); diff --git a/test/jdk/jdk/classfile/AnnotationTest.java b/test/jdk/jdk/classfile/AnnotationTest.java index 4ed3b2141ad..6b6b88b3de1 100644 --- a/test/jdk/jdk/classfile/AnnotationTest.java +++ b/test/jdk/jdk/classfile/AnnotationTest.java @@ -28,6 +28,8 @@ */ import java.lang.constant.ClassDesc; import static java.lang.constant.ConstantDescs.*; + +import java.lang.constant.ConstantDesc; import java.lang.constant.MethodTypeDesc; import java.util.AbstractMap; import java.util.ArrayList; @@ -39,6 +41,8 @@ import java.util.Set; import java.lang.classfile.attribute.RuntimeVisibleAnnotationsAttribute; import java.lang.classfile.*; import java.lang.classfile.constantpool.ConstantPoolBuilder; +import java.util.stream.Stream; + import org.junit.jupiter.api.Test; import static java.util.stream.Collectors.toList; @@ -53,26 +57,30 @@ import static org.junit.jupiter.api.Assertions.*; class AnnotationTest { enum E {C}; - private static Map constants + // name -> (value, poolValue) + private static final Map> constants = Map.ofEntries( - new AbstractMap.SimpleImmutableEntry<>("i", 1), - new AbstractMap.SimpleImmutableEntry<>("j", 1L), - new AbstractMap.SimpleImmutableEntry<>("s", 1), - new AbstractMap.SimpleImmutableEntry<>("b", 1), - new AbstractMap.SimpleImmutableEntry<>("f", 1.0f), - new AbstractMap.SimpleImmutableEntry<>("d", 1.0d), - new AbstractMap.SimpleImmutableEntry<>("z", 1), - new AbstractMap.SimpleImmutableEntry<>("c", (int) '1'), - new AbstractMap.SimpleImmutableEntry<>("st", "1"), - new AbstractMap.SimpleImmutableEntry<>("cl", ClassDesc.of("foo.Bar")), - new AbstractMap.SimpleImmutableEntry<>("en", E.C), - new AbstractMap.SimpleImmutableEntry<>("arr", new Object[] {1, "1", 1.0f}) + Map.entry("i", Map.entry(1, 1)), + Map.entry("j", Map.entry(1L, 1L)), + Map.entry("s", Map.entry((short) 1, 1)), + Map.entry("b", Map.entry((byte) 1, 1)), + Map.entry("f", Map.entry(1.0f, 1.0f)), + Map.entry("d", Map.entry(1.0d, 1.0d)), + Map.entry("z", Map.entry(true, 1)), + Map.entry("c", Map.entry('1', (int) '1')), + Map.entry("st", Map.entry("1", "1")) ); - private static final List constantElements = + private static final List constantElements = Stream.concat( constants.entrySet().stream() - .map(e -> AnnotationElement.of(e.getKey(), AnnotationValue.of(e.getValue()))) - .toList(); + .map(e -> Map.entry(e.getKey(), e.getValue().getKey())), + Stream.of( + Map.entry("cl", ClassDesc.of("foo.Bar")), + Map.entry("en", E.C), + Map.entry("arr", new Object[] {1, "1", 1.0f}) + )) + .map(e -> AnnotationElement.of(e.getKey(), AnnotationValue.of(e.getValue()))) + .toList(); private static List elements() { List list = new ArrayList<>(constantElements); @@ -88,9 +96,12 @@ class AnnotationTest { names.add(evp.name().stringValue()); switch (evp.name().stringValue()) { case "i", "j", "s", "b", "f", "d", "z", "c", "st": - assertTrue (evp.value() instanceof AnnotationValue.OfConstant c); - assertEquals(((AnnotationValue.OfConstant) evp.value()).constantValue(), - constants.get(evp.name().stringValue())); + if (!(evp.value() instanceof AnnotationValue.OfConstant c)) + return fail(); + assertEquals(c.resolvedValue(), + constants.get(evp.name().stringValue()).getKey()); + assertEquals(c.constant().constantValue(), + constants.get(evp.name().stringValue()).getValue()); break; case "cl": assertTrue (evp.value() instanceof AnnotationValue.OfClass c @@ -105,8 +116,9 @@ class AnnotationTest { && assertAnno(c.annotation(), "LBar;", false)); break; case "arr": - assertTrue (evp.value() instanceof AnnotationValue.OfArray); - List values = ((AnnotationValue.OfArray) evp.value()).values(); + if (!(evp.value() instanceof AnnotationValue.OfArray arr)) + return fail(); + List values = arr.values(); assertEquals(values.stream().map(v -> ((AnnotationValue.OfConstant) v).constant().constantValue()).collect(toSet()), Set.of(1, 1.0f, "1")); break; diff --git a/test/jdk/jdk/classfile/ClassPrinterTest.java b/test/jdk/jdk/classfile/ClassPrinterTest.java index 9c25ff7e13a..7668648f829 100644 --- a/test/jdk/jdk/classfile/ClassPrinterTest.java +++ b/test/jdk/jdk/classfile/ClassPrinterTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2022, 2024, 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 @@ -23,6 +23,7 @@ /* * @test + * @bug 8335927 * @summary Testing ClassFile ClassPrinter. * @run junit ClassPrinterTest */ @@ -249,7 +250,7 @@ class ClassPrinterTest { flags: [PROTECTED] method type: (ZLjava/lang/Throwable;)Ljava/lang/Void; attributes: [AnnotationDefault, RuntimeVisibleParameterAnnotations, RuntimeInvisibleParameterAnnotations, Exceptions, Code] - annotation default: {array: [{boolean: true}, {byte: 12}, {char: 99}, {class: LPhee;}, {double: 1.3}, {enum class: LBoo;, constant name: BOO}, {float: 3.7}, {int: 33}, {long: 3333}, {short: 25}, {string: BOO}, {annotation class: LPhoo;}]} + annotation default: {array: [{boolean: true}, {byte: 12}, {char: c}, {class: LPhee;}, {double: 1.3}, {enum class: LBoo;, constant name: BOO}, {float: 3.7}, {int: 33}, {long: 3333}, {short: 25}, {string: BOO}, {annotation class: LPhoo;}]} visible parameter annotations: parameter 1: [{annotation class: LPhoo;, values: [{name: flfl, value: {float: 22.0}}, {name: frfl, value: {float: 11.0}}]}] invisible parameter annotations: @@ -500,7 +501,7 @@ class ClassPrinterTest { "flags": ["PROTECTED"], "method type": "(ZLjava/lang/Throwable;)Ljava/lang/Void;", "attributes": ["AnnotationDefault", "RuntimeVisibleParameterAnnotations", "RuntimeInvisibleParameterAnnotations", "Exceptions", "Code"], - "annotation default": {"array": [{"boolean": "true"}, {"byte": "12"}, {"char": "99"}, {"class": "LPhee;"}, {"double": "1.3"}, {"enum class": "LBoo;", "constant name": "BOO"}, {"float": "3.7"}, {"int": "33"}, {"long": "3333"}, {"short": "25"}, {"string": "BOO"}, {"annotation class": "LPhoo;"}]}, + "annotation default": {"array": [{"boolean": "true"}, {"byte": "12"}, {"char": "c"}, {"class": "LPhee;"}, {"double": "1.3"}, {"enum class": "LBoo;", "constant name": "BOO"}, {"float": "3.7"}, {"int": "33"}, {"long": "3333"}, {"short": "25"}, {"string": "BOO"}, {"annotation class": "LPhoo;"}]}, "visible parameter annotations": { "parameter 1": [{"annotation class": "LPhoo;", "values": [{"name": "flfl", "value": {"float": "22.0"}}, {"name": "frfl", "value": {"float": "11.0"}}]}]}, "invisible parameter annotations": { @@ -756,7 +757,7 @@ class ClassPrinterTest { PROTECTED (ZLjava/lang/Throwable;)Ljava/lang/Void; AnnotationDefaultRuntimeVisibleParameterAnnotationsRuntimeInvisibleParameterAnnotationsExceptionsCode - true1299LPhee;1.3LBoo;BOO3.733333325BOOLPhoo; + true12cLPhee;1.3LBoo;BOO3.733333325BOOLPhoo; LPhoo;flfl22.0frfl11.0 @@ -907,6 +908,6 @@ class ClassPrinterTest { // System.out.println("-----------------"); // System.out.println(out.toString()); // System.out.println("-----------------"); - assertArrayEquals(out.toString().trim().split(" *\r?\n"), expected.trim().split("\n")); + assertArrayEquals(expected.trim().split("\n"), out.toString().trim().split(" *\r?\n")); } } diff --git a/test/jdk/jdk/classfile/helpers/RebuildingTransformation.java b/test/jdk/jdk/classfile/helpers/RebuildingTransformation.java index 2af3cd9410f..7667403aaab 100644 --- a/test/jdk/jdk/classfile/helpers/RebuildingTransformation.java +++ b/test/jdk/jdk/classfile/helpers/RebuildingTransformation.java @@ -165,9 +165,9 @@ class RebuildingTransformation { case AnnotationValue.OfDouble v -> AnnotationValue.of(v.doubleValue()); case AnnotationValue.OfFloat v -> AnnotationValue.of(v.floatValue()); case AnnotationValue.OfLong v -> AnnotationValue.of(v.longValue()); - case AnnotationValue.OfInteger v -> AnnotationValue.of(v.intValue()); + case AnnotationValue.OfInt v -> AnnotationValue.of(v.intValue()); case AnnotationValue.OfShort v -> AnnotationValue.of(v.shortValue()); - case AnnotationValue.OfCharacter v -> AnnotationValue.of(v.charValue()); + case AnnotationValue.OfChar v -> AnnotationValue.of(v.charValue()); case AnnotationValue.OfByte v -> AnnotationValue.of(v.byteValue()); case AnnotationValue.OfBoolean v -> AnnotationValue.of(v.booleanValue()); case AnnotationValue.OfClass oc -> AnnotationValue.of(oc.classSymbol()); diff --git a/test/langtools/tools/javac/annotations/typeAnnotations/classfile/AnonymousClassTest.java b/test/langtools/tools/javac/annotations/typeAnnotations/classfile/AnonymousClassTest.java index 64c33ed9fd9..94610ddf055 100644 --- a/test/langtools/tools/javac/annotations/typeAnnotations/classfile/AnonymousClassTest.java +++ b/test/langtools/tools/javac/annotations/typeAnnotations/classfile/AnonymousClassTest.java @@ -246,7 +246,7 @@ public class AnonymousClassTest { private static String elementValueDebugString(AnnotationValue value) { if (value.tag() == 'I') { - return Integer.toString(((AnnotationValue.OfInteger) value).intValue()); + return Integer.toString(((AnnotationValue.OfInt) value).intValue()); } else { throw new UnsupportedOperationException(String.format("%c", value.tag())); } diff --git a/test/langtools/tools/javac/classfiles/attributes/AnnotationDefault/AnnotationDefaultVerifier.java b/test/langtools/tools/javac/classfiles/attributes/AnnotationDefault/AnnotationDefaultVerifier.java index d85b37aa3a3..8efb13ccbdf 100644 --- a/test/langtools/tools/javac/classfiles/attributes/AnnotationDefault/AnnotationDefaultVerifier.java +++ b/test/langtools/tools/javac/classfiles/attributes/AnnotationDefault/AnnotationDefaultVerifier.java @@ -103,7 +103,7 @@ public class AnnotationDefaultVerifier { case AnnotationValue.OfByte ev -> { testCase.checkEquals((int)ev.byteValue(), Integer.parseInt(values[0]), "const_value_index"); } - case AnnotationValue.OfCharacter ev -> { + case AnnotationValue.OfChar ev -> { testCase.checkEquals((int)ev.charValue(), Integer.parseInt(values[0]), "const_value_index"); } case AnnotationValue.OfShort ev -> { @@ -113,7 +113,7 @@ public class AnnotationDefaultVerifier { testCase.checkEquals(ev.booleanValue()? 1: 0, Integer.parseInt(values[0]), "const_value_index"); } default -> { - testCase.checkEquals(((AnnotationValue.OfInteger) element_value).intValue(), Integer.parseInt(values[0]), "const_value_index"); + testCase.checkEquals(((AnnotationValue.OfInt) element_value).intValue(), Integer.parseInt(values[0]), "const_value_index"); } } } diff --git a/test/langtools/tools/javac/classfiles/attributes/annotations/TestAnnotationInfo.java b/test/langtools/tools/javac/classfiles/attributes/annotations/TestAnnotationInfo.java index 5bf587d1b8b..3f422b541c0 100644 --- a/test/langtools/tools/javac/classfiles/attributes/annotations/TestAnnotationInfo.java +++ b/test/langtools/tools/javac/classfiles/attributes/annotations/TestAnnotationInfo.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2024, 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 @@ -123,7 +123,7 @@ public class TestAnnotationInfo { testResult.checkEquals((int)((AnnotationValue.OfShort) element_value).shortValue(), value, "const_value_index : " + value); break; default: - testResult.checkEquals(((AnnotationValue.OfInteger) element_value).intValue(), value, "const_value_index : " + value); + testResult.checkEquals(((AnnotationValue.OfInt) element_value).intValue(), value, "const_value_index : " + value); } } @@ -169,8 +169,8 @@ public class TestAnnotationInfo { ClassModel classFile, AnnotationValue element_value) { testTag(testResult, element_value.tag()); - AnnotationValue.OfCharacter ev = - (AnnotationValue.OfCharacter) element_value; + AnnotationValue.OfChar ev = + (AnnotationValue.OfChar) element_value; testResult.checkEquals(ev.charValue(), value, "const_value_index : " + value); }