From bcefab5e55d4527a38dcab550581a734c1564608 Mon Sep 17 00:00:00 2001 From: Chen Liang Date: Wed, 8 Jan 2025 03:37:28 +0000 Subject: [PATCH] 8342468: Improve API documentation for java.lang.classfile.constantpool Reviewed-by: asotona --- .../lang/classfile/BootstrapMethodEntry.java | 30 +- .../java/lang/classfile/ClassFile.java | 53 ++- .../AnnotationConstantValueEntry.java | 16 +- .../classfile/constantpool/ClassEntry.java | 63 ++- .../constantpool/ConstantDynamicEntry.java | 56 ++- .../classfile/constantpool/ConstantPool.java | 32 +- .../constantpool/ConstantPoolBuilder.java | 444 ++++++++++-------- .../constantpool/ConstantPoolException.java | 28 +- .../constantpool/ConstantValueEntry.java | 13 +- .../classfile/constantpool/DoubleEntry.java | 26 +- .../DynamicConstantPoolEntry.java | 55 ++- .../classfile/constantpool/FieldRefEntry.java | 24 +- .../classfile/constantpool/FloatEntry.java | 23 +- .../classfile/constantpool/IntegerEntry.java | 20 +- .../constantpool/InterfaceMethodRefEntry.java | 26 +- .../constantpool/InvokeDynamicEntry.java | 43 +- .../constantpool/LoadableConstantEntry.java | 24 +- .../classfile/constantpool/LongEntry.java | 21 +- .../constantpool/MemberRefEntry.java | 40 +- .../constantpool/MethodHandleEntry.java | 44 +- .../constantpool/MethodRefEntry.java | 24 +- .../constantpool/MethodTypeEntry.java | 30 +- .../classfile/constantpool/ModuleEntry.java | 23 +- .../constantpool/NameAndTypeEntry.java | 36 +- .../classfile/constantpool/PackageEntry.java | 26 +- .../classfile/constantpool/PoolEntry.java | 52 +- .../classfile/constantpool/StringEntry.java | 22 +- .../classfile/constantpool/Utf8Entry.java | 44 +- .../classfile/constantpool/package-info.java | 54 ++- .../snippet-files/PackageSnippets.java | 43 ++ test/jdk/jdk/classfile/SnippetsTest.java | 6 +- 31 files changed, 1070 insertions(+), 371 deletions(-) create mode 100644 src/java.base/share/classes/java/lang/classfile/constantpool/snippet-files/PackageSnippets.java diff --git a/src/java.base/share/classes/java/lang/classfile/BootstrapMethodEntry.java b/src/java.base/share/classes/java/lang/classfile/BootstrapMethodEntry.java index 1608e77bee6..ab246a8653b 100644 --- a/src/java.base/share/classes/java/lang/classfile/BootstrapMethodEntry.java +++ b/src/java.base/share/classes/java/lang/classfile/BootstrapMethodEntry.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2022, 2025, 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,7 +25,9 @@ package java.lang.classfile; +import java.lang.classfile.attribute.BootstrapMethodsAttribute; import java.lang.classfile.constantpool.ConstantPool; +import java.lang.classfile.constantpool.ConstantPoolBuilder; import java.lang.classfile.constantpool.LoadableConstantEntry; import java.lang.classfile.constantpool.MethodHandleEntry; import java.util.List; @@ -34,10 +36,20 @@ /** * Models an entry in the bootstrap method table. The bootstrap method table - * is stored in the {@code BootstrapMethods} attribute, but is modeled by - * the {@link ConstantPool}, since the bootstrap method table is logically - * part of the constant pool. + * is stored in the {@link BootstrapMethodsAttribute BootstrapMethods} + * attribute, but is modeled by the {@link ConstantPool}, since the bootstrap + * method table is logically part of the constant pool. + *

+ * A bootstrap method entry is composite: + * {@snippet lang=text : + * // @link substring="BootstrapMethodEntry" target="ConstantPoolBuilder#bsmEntry(MethodHandleEntry, List)" : + * BootstrapMethodEntry( + * MethodHandleEntry bootstrapMethod, // @link substring="bootstrapMethod" target="#bootstrapMethod" + * List arguments // @link substring="arguments" target="#arguments()" + * ) + * } * + * @see ConstantPoolBuilder#bsmEntry ConstantPoolBuilder::bsmEntry * @since 24 */ public sealed interface BootstrapMethodEntry @@ -45,11 +57,19 @@ public sealed interface BootstrapMethodEntry /** * {@return the constant pool associated with this entry} + * + * @apiNote + * Given a {@link ConstantPoolBuilder} {@code builder} and a {@code + * BootstrapMethodEntry} {@code entry}, use {@link + * ConstantPoolBuilder#canWriteDirect + * builder.canWriteDirect(entry.constantPool())} instead of object equality + * of the constant pool to determine if an entry is compatible. */ ConstantPool constantPool(); /** - * {@return the index into the bootstrap method table corresponding to this entry} + * {@return the index into the bootstrap method table corresponding to this + * entry} */ int bsmIndex(); diff --git a/src/java.base/share/classes/java/lang/classfile/ClassFile.java b/src/java.base/share/classes/java/lang/classfile/ClassFile.java index c98991ecf7a..43fb1927b38 100644 --- a/src/java.base/share/classes/java/lang/classfile/ClassFile.java +++ b/src/java.base/share/classes/java/lang/classfile/ClassFile.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2022, 2025, 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 @@ -140,21 +140,56 @@ static ClassHierarchyResolverOption of(ClassHierarchyResolver classHierarchyReso /** * Option describing whether to preserve the original constant pool when - * transforming a classfile. Reusing the constant pool enables significant - * optimizations in processing time and minimizes differences between the - * original and transformed classfile, but may result in a bigger classfile - * when a classfile is significantly transformed. - * Default is {@code SHARED_POOL} to preserve the original constant - * pool. + * transforming a {@code class} file. Reusing the constant pool enables + * significant optimizations in processing time and minimizes differences + * between the original and transformed {@code class} files, but may result + * in a bigger transformed {@code class} file when many elements of the + * original {@code class} file are dropped and many original constant + * pool entries become unused. Default is {@link #SHARED_POOL} to preserve + * the original constant pool. * + * @see ConstantPoolBuilder + * @see #build(ClassEntry, ConstantPoolBuilder, Consumer) + * @see #transformClass(ClassModel, ClassTransform) * @since 24 */ enum ConstantPoolSharingOption implements Option { - /** Preserves the original constant pool when transforming classfile */ + /** + * Preserves the original constant pool when transforming the {@code + * class} file. + *

+ * These two transformations below are equivalent: + * {@snippet lang=java : + * ClassModel originalClass = null; // @replace substring=null; replacement=... + * ClassDesc resultClassName = null; // @replace substring=null; replacement=... + * ClassTransform classTransform = null; // @replace substring=null; replacement=... + * var resultOne = ClassFile.of(ConstantPoolSharingOption.SHARED_POOL) + * .transformClass(originalClass, resultClassName, classTransform); + * var resultTwo = ClassFile.of().build(resultClassName, ConstantPoolBuilder.of(originalClass), + * clb -> clb.transform(originalClass, classTransform)); + * } + * + * @see ConstantPoolBuilder#of(ClassModel) ConstantPoolBuilder::of(ClassModel) + */ SHARED_POOL, - /** Creates a new constant pool when transforming classfile */ + /** + * Creates a new constant pool when transforming the {@code class} file. + *

+ * These two transformations below are equivalent: + * {@snippet lang=java : + * ClassModel originalClass = null; // @replace substring=null; replacement=... + * ClassDesc resultClassName = null; // @replace substring=null; replacement=... + * ClassTransform classTransform = null; // @replace substring=null; replacement=... + * var resultOne = ClassFile.of(ConstantPoolSharingOption.NEW_POOL) + * .transformClass(originalClass, resultClassName, classTransform); + * var resultTwo = ClassFile.of().build(resultClassName, ConstantPoolBuilder.of(), + * clb -> clb.transform(originalClass, classTransform)); + * } + * + * @see ConstantPoolBuilder#of() ConstantPoolBuilder::of() + */ NEW_POOL } 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 5255ceb1ef7..c4b6546fe20 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, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2022, 2025, 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 @@ -28,10 +28,9 @@ import java.lang.constant.ConstantDesc; /** - * 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. + * Marker interface for constant pool entries that can represent constant values + * associated with elements of annotations. They 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 @@ -40,6 +39,7 @@ * in {@link AnnotationValue.OfInt}. * * @see AnnotationValue.OfConstant + * @jvms 4.7.16.1 The {@code element_value} structure * @sealedGraph * @since 24 */ @@ -47,9 +47,9 @@ public sealed interface AnnotationConstantValueEntry extends PoolEntry permits DoubleEntry, FloatEntry, IntegerEntry, LongEntry, Utf8Entry { /** - * {@return the constant value} The constant value will be an {@link Integer}, - * {@link Long}, {@link Float}, {@link Double} for the primitive constants, - * or {@link String} for UTF8 constants. + * {@return the constant value} The constant value will be an {@link + * Integer}, {@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/ClassEntry.java b/src/java.base/share/classes/java/lang/classfile/constantpool/ClassEntry.java index 2a3bd95da22..5017838d68e 100644 --- a/src/java.base/share/classes/java/lang/classfile/constantpool/ClassEntry.java +++ b/src/java.base/share/classes/java/lang/classfile/constantpool/ClassEntry.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2022, 2025, 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 @@ -30,33 +30,82 @@ import jdk.internal.classfile.impl.AbstractPoolEntry; /** - * Models a {@code CONSTANT_Class_info} constant in the constant pool of a - * classfile. - * @jvms 4.4.1 The CONSTANT_Class_info Structure + * Models a {@code CONSTANT_Class_info} structure, representing a reference + * type, in the constant pool of a {@code class} file. + *

+ * The use of a {@code ClassEntry} is modeled by a {@link ClassDesc} that is not + * primitive. Conversions are through {@link ConstantPoolBuilder#classEntry( + * ClassDesc)} and {@link #asSymbol()}. + *

+ * A {@code ClassEntry} is composite: + * {@snippet lang=text : + * // @link substring="ClassEntry" target="ConstantPoolBuilder#classEntry(Utf8Entry)" : + * ClassEntry(Utf8Entry name) // @link substring="name" target="#name" + * } + * where {@code name} represents: + *

+ * A field descriptor string for an array type can be distinguished by its + * leading {@code '['} character. * + * @apiNote + * The internal form of a binary name, where all occurrences of {@code .} in the + * name are replaced by {@code /}, is informally known as an {@index + * "internal name"}. This concept also applies to package names in + * addition to class and interface names. + * + * @see ConstantPoolBuilder#classEntry ConstantPoolBuilder::classEntry + * @see ClassDesc + * @jvms 4.4.1 The {@code CONSTANT_Class_info} Structure * @since 24 */ public sealed interface ClassEntry extends LoadableConstantEntry permits AbstractPoolEntry.ClassEntryImpl { + /** + * {@inheritDoc} + *

+ * This is equivalent to {@link #asSymbol() asSymbol()}. + */ @Override default ConstantDesc constantValue() { return asSymbol(); } /** - * {@return the UTF8 constant pool entry for the class name} + * {@return the {@code Utf8Entry} referred by this structure} If the + * value of the UTF8 starts with a {@code [}, this represents an array type + * and the value is a descriptor string; otherwise, this represents a class + * or interface and the value is the {@linkplain ##internalname internal + * form} of a binary name. + * + * @see ConstantPoolBuilder#classEntry(Utf8Entry) + * ConstantPoolBuilder::classEntry(Utf8Entry) */ Utf8Entry name(); /** - * {@return the class name, as an internal binary name} + * {@return the represented reference type, as the {@linkplain + * ##internalname internal form} of a binary name or an array descriptor + * string} This is a shortcut for {@link #name() name().stringValue()}. */ String asInternalName(); /** - * {@return the class name, as a symbolic descriptor} + * {@return the represented reference type, as a symbolic descriptor} The + * returned descriptor is never {@linkplain ClassDesc#isPrimitive() + * primitive}. + * + * @see ConstantPoolBuilder#classEntry(ClassDesc) + * ConstantPoolBuilder::classEntry(ClassDesc) */ ClassDesc asSymbol(); } diff --git a/src/java.base/share/classes/java/lang/classfile/constantpool/ConstantDynamicEntry.java b/src/java.base/share/classes/java/lang/classfile/constantpool/ConstantDynamicEntry.java index 72050cd9b8f..bbd03c88292 100644 --- a/src/java.base/share/classes/java/lang/classfile/constantpool/ConstantDynamicEntry.java +++ b/src/java.base/share/classes/java/lang/classfile/constantpool/ConstantDynamicEntry.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2022, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -33,10 +33,36 @@ import jdk.internal.classfile.impl.Util; /** - * Models a {@code CONSTANT_Dynamic_info} constant in the constant pool of a - * classfile. - * @jvms 4.4.10 The CONSTANT_Dynamic_info and CONSTANT_InvokeDynamic_info Structures + * Models a {@code CONSTANT_Dynamic_info} structure, representing a {@index + * "dynamically-computed constant"}, in the constant pool of a {@code + * class} file. + *

+ * The use of a {@code ConstantDynamicEntry} is modeled by a {@link + * DynamicConstantDesc}. Conversions are through {@link #asSymbol()} and {@link + * ConstantPoolBuilder#constantDynamicEntry(DynamicConstantDesc)}. + *

+ * A dynamic constant entry is composite: + * {@snippet lang=text : + * // @link substring="ConstantDynamicEntry" target="ConstantPoolBuilder#constantDynamicEntry(BootstrapMethodEntry, NameAndTypeEntry)" : + * ConstantDynamicEntry( + * BootstrapMethodEntry bootstrap, // @link substring="bootstrap" target="#bootstrap()" + * NameAndTypeEntry nameAndType // @link substring="nameAndType" target="#nameAndType()" + * ) + * } + * where {@link #type() nameAndType.type()} is a {@linkplain #typeSymbol() + * field descriptor} string. * + * @apiNote + * A dynamically-computed constant is frequently called a {@index "dynamic + * constant"}, or a {@index "condy"}, from the abbreviation of + * "constant dynamic". + * + * @see ConstantPoolBuilder#constantDynamicEntry + * ConstantPoolBuilder::constantDynamicEntry + * @see DynamicConstantDesc + * @see java.lang.invoke##condycon Dynamically-computed constants + * @jvms 4.4.10 The {@code CONSTANT_Dynamic_info} and {@code + * CONSTANT_InvokeDynamic_info} Structures * @since 24 */ public sealed interface ConstantDynamicEntry @@ -44,19 +70,28 @@ public sealed interface ConstantDynamicEntry permits AbstractPoolEntry.ConstantDynamicEntryImpl { /** - * {@return a symbolic descriptor for the dynamic constant's type} + * {@return a symbolic descriptor for the {@linkplain #type() field type} of + * this dynamically-computed constant} */ default ClassDesc typeSymbol() { return Util.fieldTypeSymbol(type()); } + /** + * {@inheritDoc} + *

+ * This is equivalent to {@link #asSymbol() asSymbol()}. + */ @Override default ConstantDesc constantValue() { return asSymbol(); } /** - * {@return the symbolic descriptor for the {@code invokedynamic} constant} + * {@return a symbolic descriptor for this dynamically-computed constant} + * + * @see ConstantPoolBuilder#constantDynamicEntry(DynamicConstantDesc) + * ConstantPoolBuilder::constantDynamicEntry(DynamicConstantDesc) */ default DynamicConstantDesc asSymbol() { return DynamicConstantDesc.ofNamed(bootstrap().bootstrapMethod().asSymbol(), @@ -68,10 +103,15 @@ default DynamicConstantDesc asSymbol() { } /** - * {@return the type of the constant} + * {@inheritDoc} + * + * @apiNote + * The data type of a dynamically-computed constant depends on its + * {@linkplain #type() descriptor}, while the data type of all other + * constants can be determined by their {@linkplain #tag() constant type}. */ @Override default TypeKind typeKind() { - return TypeKind.fromDescriptor(type().stringValue()); + return TypeKind.fromDescriptor(type()); } } diff --git a/src/java.base/share/classes/java/lang/classfile/constantpool/ConstantPool.java b/src/java.base/share/classes/java/lang/classfile/constantpool/ConstantPool.java index 91dc8906b7b..6fed8dad8b7 100644 --- a/src/java.base/share/classes/java/lang/classfile/constantpool/ConstantPool.java +++ b/src/java.base/share/classes/java/lang/classfile/constantpool/ConstantPool.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2022, 2025, 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 @@ -27,14 +27,22 @@ import java.lang.classfile.BootstrapMethodEntry; import java.lang.classfile.ClassReader; +import java.lang.classfile.attribute.BootstrapMethodsAttribute; import java.util.Iterator; import java.util.NoSuchElementException; /** - * Provides read access to the constant pool and bootstrap method table of a - * classfile. - * @jvms 4.4 The Constant Pool + * Provides read access to the constant pool and the bootstrap method table of a + * {@code class} file. + * + *

Index in the Constant Pool

+ * The constant pool entries are accessed by index. A valid index is in the + * range of {@link #size() [1, size())}. It is {@linkplain PoolEntry#width() + * unusable} if a {@link LongEntry} or {@link DoubleEntry} is at its previous + * index. * + * @see BootstrapMethodsAttribute + * @jvms 4.4 The Constant Pool * @sealedGraph * @since 24 */ @@ -46,7 +54,7 @@ public sealed interface ConstantPool extends Iterable * * @apiNote * If only a particular type of entry is expected, use {@link #entryByIndex( - * int, Class) entryByIndex(int, Class)}. + * int, Class)}. * * @param index the index within the pool of the desired entry * @throws ConstantPoolException if the index is out of range of the @@ -55,7 +63,11 @@ public sealed interface ConstantPool extends Iterable PoolEntry entryByIndex(int index); /** - * {@return the size of the constant pool} + * {@return the exclusive upper bound of the valid indices of this constant + * pool} The actual number of entries is lower because {@code 0}, {@code + * size()} are not valid, and a valid index may be unusable. + * + * @see ##index Index in the Constant Pool */ int size(); @@ -66,12 +78,17 @@ public sealed interface ConstantPool extends Iterable * @param index the index within the pool of the desired entry * @param cls the entry type * @throws ConstantPoolException if the index is out of range of the - * constant pool, or the entry is not of the given type + * constant pool or considered unusable, or the entry is not + * of the given type */ T entryByIndex(int index, Class cls); /** * {@return an iterator over pool entries} + * + * @apiNote + * This skips any unusable index and is less error-prone than iterating by + * raw index. See {@linkplain ##index Index in the Constant Pool}. */ @Override default Iterator iterator() { @@ -93,7 +110,6 @@ public PoolEntry next() { }; } - /** * {@return the {@link BootstrapMethodEntry} at the specified index within * the bootstrap method table} 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 2dc2a390bd1..e1518ab6a02 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 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2022, 2025, 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,10 +25,16 @@ package java.lang.classfile.constantpool; import java.lang.classfile.BootstrapMethodEntry; -import java.lang.classfile.ClassBuilder; +import java.lang.classfile.ClassFile; +import java.lang.classfile.ClassFileBuilder; import java.lang.classfile.ClassModel; +import java.lang.classfile.CodeBuilder; +import java.lang.classfile.attribute.ConstantValueAttribute; +import java.lang.classfile.instruction.ConstantInstruction; import java.lang.constant.*; +import java.lang.invoke.MethodHandleInfo; import java.util.List; +import java.util.function.Consumer; import jdk.internal.classfile.impl.AbstractPoolEntry.ClassEntryImpl; import jdk.internal.classfile.impl.ClassReaderImpl; @@ -39,14 +45,45 @@ import static java.util.Objects.requireNonNull; /** - * Builder for the constant pool of a classfile. Provides read and write access - * to the constant pool that is being built. Writing is append-only and idempotent - * (entry-bearing methods will return an existing entry if there is one). + * Builder for the constant pool of a {@code class} file. Provides read and + * write access to the constant pool that is {@linkplain ClassFileBuilder#constantPool() + * being built}. Writing is append-only (the index of new entries monotonically + * increase) and idempotent (entry-bearing methods will return an existing entry + * if there is a suitable one). + *

+ * For {@code class} file building, an overload of {@link ClassFile#build( + * ClassEntry, ConstantPoolBuilder, Consumer) ClassFile::build} takes a + * {@code ConstantPoolBuilder}. For {@code class} file transformations via + * {@link ClassFile#transformClass ClassFile::transformClass}, the {@link + * ClassFile.ConstantPoolSharingOption} controls how the constant pool builder + * of the resulting {@code class} is created. * - * A {@linkplain ConstantPoolBuilder} is associated with a {@link ClassBuilder}. - * The {@linkplain ConstantPoolBuilder} also provides access to some of the - * state of the {@linkplain ClassBuilder}, such as classfile processing options. + *

Alien Constant Pool Entries

+ * In {@code class} file building and constant pool building, some constant pool + * entries supplied may be {@linkplain #canWriteDirect(ConstantPool) alien} + * to this constant pool builder of the active class file builder. For example, + * {@link #classEntry(Utf8Entry) classEntry(Utf8Entry)} may be called with an + * alien UTF8 entry. Alien entries will be converted to a pool entry in + * this constant pool builder, reusing equivalent entries or adding new entries + * if there is none. As a result, all pool entries returned by entry-bearing + * methods in this constant pool builder belong to this constant pool. + *

+ * Some {@link ClassFileBuilder} methods may have their outputs adjusted if they + * receive pool entries alien to {@linkplain ClassFileBuilder#constantPool + * their constant pools}. For example, if an {@link ConstantInstruction#ofLoad + * ldc_w} instruction with an alien entry is written to a {@link CodeBuilder}, + * the {@code CodeBuilder} may emit a functionally equivalent {@code ldc} + * instruction instead, if the converted entry can be encoded in such an + * instruction. + *

+ * To avoid the conversion of alien constant pool entries, such as for the + * accuracy of the generated {@code class} file, users can always supply + * constant pool entries obtained by calling the constant pool builder + * entry-bearing methods of the constant pools associated with the {@code + * ClassFileBuilder}. Otherwise, the conversions have no impact on the + * behaviors of the generated {@code class} files. * + * @see ClassFileBuilder#constantPool() * @since 24 */ public sealed interface ConstantPoolBuilder @@ -55,10 +92,14 @@ public sealed interface ConstantPoolBuilder /** * {@return a new constant pool builder} The new constant pool builder will - * be pre-populated with the contents of the constant pool associated with - * the class reader. + * be pre-populated with the contents of the constant pool {@linkplain + * ClassModel#constantPool() associated with} the given class model. The + * index of new entries will start from the {@link ConstantPool#size() + * size()} of the source pool. * * @param classModel the class to copy from + * @see ClassFile#build(ClassEntry, ConstantPoolBuilder, Consumer) + * @see ClassFile.ConstantPoolSharingOption#SHARED_POOL */ static ConstantPoolBuilder of(ClassModel classModel) { return new SplitConstantPool((ClassReaderImpl) classModel.constantPool()); @@ -66,35 +107,47 @@ static ConstantPoolBuilder of(ClassModel classModel) { /** * {@return a new constant pool builder} The new constant pool builder - * will be empty. + * will be empty. The index of new entries will start from {@code 1}. + * + * @see ClassFile.ConstantPoolSharingOption#NEW_POOL */ static ConstantPoolBuilder of() { return new SplitConstantPool(); } /** - * {@return whether the provided constant pool is index-compatible with this - * one} This may be because they are the same constant pool, or because this - * constant pool was copied from the other. + * {@return {@code true} if the index of any entry in the given constant + * pool refers to the same entry in this builder} This may be because they + * are the same builder, or because this builder was {@linkplain + * #of(ClassModel) pre-populated} from the given constant pool. + *

+ * If the constant pool of an entry is not directly writable to this pool, + * it is alien to this pool, and a {@link ClassFileBuilder} associated + * with this constant pool will convert that alien constant pool entry. * - * @param constantPool the other constant pool + * @param constantPool the given constant pool + * @see ClassFileBuilder#constantPool() ClassFileBuilder::constantPool + * @see ##alien Alien Constant Pool Entries */ boolean canWriteDirect(ConstantPool constantPool); /** - * {@return A {@link Utf8Entry} describing the provided {@linkplain String}} - * If a UTF8 entry in the pool already describes this string, it is returned; - * otherwise, a new entry is added and the new entry is returned. + * {@return a {@link Utf8Entry} describing the provided {@link String}} * * @param s the string + * @see Utf8Entry#stringValue() Utf8Entry::stringValue */ Utf8Entry utf8Entry(String s); /** - * {@return A {@link Utf8Entry} describing the field descriptor of the provided - * {@linkplain ClassDesc}} - * If a UTF8 entry in the pool already describes this field descriptor, it is returned; - * otherwise, a new entry is added and the new entry is returned. + * {@return a {@link Utf8Entry} describing the {@linkplain + * ClassDesc#descriptorString() field descriptor string} of the provided + * {@link ClassDesc}} + * + * @apiNote + * The resulting {@code Utf8Entry} is usually not {@linkplain + * #classEntry(Utf8Entry) referable by} a {@link ClassEntry}, which uses + * internal form of binary names. * * @param desc the symbolic descriptor for the class */ @@ -103,10 +156,9 @@ default Utf8Entry utf8Entry(ClassDesc desc) { } /** - * {@return A {@link Utf8Entry} describing the method descriptor of the provided - * {@linkplain MethodTypeDesc}} - * If a UTF8 entry in the pool already describes this field descriptor, it is returned; - * otherwise, a new entry is added and the new entry is returned. + * {@return a {@link Utf8Entry} describing the {@linkplain + * MethodTypeDesc#descriptorString() method descriptor string} of the + * provided {@link MethodTypeDesc}} * * @param desc the symbolic descriptor for the method type */ @@ -115,25 +167,24 @@ default Utf8Entry utf8Entry(MethodTypeDesc desc) { } /** - * {@return A {@link ClassEntry} describing the class whose internal name - * is encoded in the provided {@linkplain Utf8Entry}} - * If a Class entry in the pool already describes this class, - * it is returned; otherwise, a new entry is added and the new entry is - * returned. + * {@return a {@link ClassEntry} referring to the provided {@link + * Utf8Entry}} The {@code Utf8Entry} describes the internal form + * of the binary name of a class or interface or the field descriptor + * string of an array type. * - * @param ne the constant pool entry describing the internal name of the class + * @param ne the {@code Utf8Entry} + * @see ClassEntry#name() ClassEntry::name */ ClassEntry classEntry(Utf8Entry ne); /** - * {@return A {@link ClassEntry} describing the class described by - * provided {@linkplain ClassDesc}} - * If a Class entry in the pool already describes this class, - * it is returned; otherwise, a new entry is added and the new entry is - * returned. + * {@return a {@link ClassEntry} describing the same reference type + * as the provided {@link ClassDesc}} * - * @param classDesc the symbolic descriptor for the class - * @throws IllegalArgumentException if {@code classDesc} represents a primitive type + * @param classDesc the symbolic descriptor for the reference type + * @throws IllegalArgumentException if {@code classDesc} represents a + * primitive type + * @see ClassEntry#asSymbol() ClassEntry::asSymbol */ default ClassEntry classEntry(ClassDesc classDesc) { if (requireNonNull(classDesc).isPrimitive()) { @@ -145,196 +196,191 @@ default ClassEntry classEntry(ClassDesc classDesc) { } /** - * {@return A {@link PackageEntry} describing the class whose internal name - * is encoded in the provided {@linkplain Utf8Entry}} - * If a Package entry in the pool already describes this class, - * it is returned; otherwise, a new entry is added and the new entry is - * returned. + * {@return a {@link PackageEntry} referring to the provided {@link + * Utf8Entry}} The {@code Utf8Entry} describes the internal form + * of the name of a package. * - * @param nameEntry the constant pool entry describing the internal name of - * the package + * @param nameEntry the {@code Utf8Entry} + * @see PackageEntry#name() PackageEntry::name */ PackageEntry packageEntry(Utf8Entry nameEntry); /** - * {@return A {@link PackageEntry} describing the class described by - * provided {@linkplain PackageDesc}} - * If a Package entry in the pool already describes this class, - * it is returned; otherwise, a new entry is added and the new entry is - * returned. + * {@return a {@link PackageEntry} describing the same package as the + * provided {@link PackageDesc}} * - * @param packageDesc the symbolic descriptor for the class + * @param packageDesc the symbolic descriptor for the package + * @see PackageEntry#asSymbol() PackageEntry::asSymbol */ default PackageEntry packageEntry(PackageDesc packageDesc) { return packageEntry(utf8Entry(packageDesc.internalName())); } /** - * {@return A {@link ModuleEntry} describing the module whose name - * is encoded in the provided {@linkplain Utf8Entry}} - * If a module entry in the pool already describes this class, - * it is returned; otherwise, a new entry is added and the new entry is - * returned. + * {@return a {@link ModuleEntry} referring to the provided {@link + * Utf8Entry}} The {@code Utf8Entry} describes the module name. * * @param moduleName the constant pool entry describing the module name + * @see ModuleEntry#name() ModuleEntry::name */ ModuleEntry moduleEntry(Utf8Entry moduleName); /** - * {@return A {@link ModuleEntry} describing the module described by - * provided {@linkplain ModuleDesc}} - * If a module entry in the pool already describes this class, - * it is returned; otherwise, a new entry is added and the new entry is - * returned. + * {@return a {@link ModuleEntry} describing the same module as the provided + * {@link ModuleDesc}} * - * @param moduleDesc the symbolic descriptor for the class + * @param moduleDesc the symbolic descriptor for the module + * @see ModuleEntry#asSymbol() ModuleEntry::asSymbol */ default ModuleEntry moduleEntry(ModuleDesc moduleDesc) { return moduleEntry(utf8Entry(moduleDesc.name())); } /** - * {@return A {@link NameAndTypeEntry} describing the provided name and type} - * If a NameAndType entry in the pool already describes this name and type, - * it is returned; otherwise, a new entry is added and the new entry is - * returned. + * {@return a {@link NameAndTypeEntry} referring to the provided name and + * type {@link Utf8Entry}} The name {@code Utf8Entry} describes an + * unqualified name or the special name {@value ConstantDescs#INIT_NAME}, + * and the type {@code Utf8Entry} describes a field or method descriptor + * string. * - * @param nameEntry the member name - * @param typeEntry the member field or method descriptor + * @param nameEntry the name {@code Utf8Entry} + * @param typeEntry the type {@code Utf8Entry} + * @see NameAndTypeEntry#name() NameAndTypeEntry::name + * @see NameAndTypeEntry#type() NameAndTypeEntry::type */ NameAndTypeEntry nameAndTypeEntry(Utf8Entry nameEntry, Utf8Entry typeEntry); /** - * {@return A {@link NameAndTypeEntry} describing the provided name and type} - * If a NameAndType entry in the pool already describes this name and type, - * it is returned; otherwise, a new entry is added and the new entry is - * returned. + * {@return a {@link NameAndTypeEntry} describing the provided unqualified + * name and field descriptor} * - * @param name the member name - * @param type the symbolic descriptor for a field type + * @param name the unqualified name + * @param type the field descriptor */ default NameAndTypeEntry nameAndTypeEntry(String name, ClassDesc type) { return nameAndTypeEntry(utf8Entry(name), utf8Entry(type)); } /** - * {@return A {@link NameAndTypeEntry} describing the provided name and type} - * If a NameAndType entry in the pool already describes this name and type, - * it is returned; otherwise, a new entry is added and the new entry is - * returned. + * {@return a {@link NameAndTypeEntry} describing the provided name and + * method descriptor} The name can be an unqualified name or the + * special name {@value ConstantDescs#INIT_NAME}. * - * @param name the member name - * @param type the symbolic descriptor for a method type + * @param name the unqualified name, or {@value ConstantDescs#INIT_NAME} + * @param type the method descriptor */ default NameAndTypeEntry nameAndTypeEntry(String name, MethodTypeDesc type) { return nameAndTypeEntry(utf8Entry(name), utf8Entry(type)); } /** - * {@return A {@link FieldRefEntry} describing a field of a class} - * If a FieldRef entry in the pool already describes this field, - * it is returned; otherwise, a new entry is added and the new entry is - * returned. + * {@return a {@link FieldRefEntry} referring to a {@link ClassEntry} and a + * {@link NameAndTypeEntry}} The {@code ClassEntry} describes a class or + * interface that has this field as a member, and the {@code + * NameAndTypeEntry} describes the unqualified name and the field descriptor + * for this field. * - * @param owner the class the field is a member of - * @param nameAndType the name and type of the field + * @param owner the {@code ClassEntry} + * @param nameAndType the {@code NameAndTypeEntry} + * @see FieldRefEntry#owner() FieldRefEntry::owner + * @see FieldRefEntry#nameAndType() FieldRefEntry::nameAndType */ FieldRefEntry fieldRefEntry(ClassEntry owner, NameAndTypeEntry nameAndType); /** - * {@return A {@link FieldRefEntry} describing a field of a class} - * If a FieldRef entry in the pool already describes this field, - * it is returned; otherwise, a new entry is added and the new entry is - * returned. + * {@return a {@link FieldRefEntry} describing a field of a class} * - * @param owner the class the field is a member of - * @param name the name of the field - * @param type the type of the field + * @param owner the class or interface the field is a member of + * @param name the unqualified name of the field + * @param type the field descriptor * @throws IllegalArgumentException if {@code owner} represents a primitive type + * @see FieldRefEntry#typeSymbol() FieldRefEntry::typeSymbol */ default FieldRefEntry fieldRefEntry(ClassDesc owner, String name, ClassDesc type) { return fieldRefEntry(classEntry(owner), nameAndTypeEntry(name, type)); } /** - * {@return A {@link MethodRefEntry} describing a method of a class} - * If a MethodRefEntry entry in the pool already describes this method, - * it is returned; otherwise, a new entry is added and the new entry is - * returned. + * {@return a {@link MethodRefEntry} referring to a {@link ClassEntry} and a + * {@link NameAndTypeEntry}} The {@code ClassEntry} describes a class that + * has this method as a member, and the {@code NameAndTypeEntry} describes + * the unqualified name or the special name {@value ConstantDescs#INIT_NAME} + * and the method descriptor for this method. * - * @param owner the class the method is a member of - * @param nameAndType the name and type of the method + * @param owner the {@code ClassEntry} + * @param nameAndType the {@code NameAndTypeEntry} + * @see MethodRefEntry#owner() MethodRefEntry::owner + * @see MethodRefEntry#nameAndType() MethodRefEntry::nameAndType */ MethodRefEntry methodRefEntry(ClassEntry owner, NameAndTypeEntry nameAndType); /** - * {@return A {@link MethodRefEntry} describing a method of a class} - * If a MethodRefEntry entry in the pool already describes this method, - * it is returned; otherwise, a new entry is added and the new entry is - * returned. + * {@return a {@link MethodRefEntry} describing a method of a class} * * @param owner the class the method is a member of - * @param name the name of the method - * @param type the type of the method + * @param name the unqualified name, or special name {@value + * ConstantDescs#INIT_NAME}, of the method + * @param type the method descriptor * @throws IllegalArgumentException if {@code owner} represents a primitive type + * @see MethodRefEntry#typeSymbol() MethodRefEntry::typeSymbol */ default MethodRefEntry methodRefEntry(ClassDesc owner, String name, MethodTypeDesc type) { return methodRefEntry(classEntry(owner), nameAndTypeEntry(name, type)); } /** - * {@return A {@link InterfaceMethodRefEntry} describing a method of a class} - * If a InterfaceMethodRefEntry entry in the pool already describes this method, - * it is returned; otherwise, a new entry is added and the new entry is - * returned. + * {@return an {@link InterfaceMethodRefEntry} referring to a {@link + * ClassEntry} and a {@link NameAndTypeEntry}} The {@code ClassEntry} + * describes an interface that has this method as a member, and the {@code + * NameAndTypeEntry} describes the unqualified name and the method + * descriptor for this method. * - * @param owner the class the method is a member of - * @param nameAndType the name and type of the method + * @param owner the {@code ClassEntry} + * @param nameAndType the {@code NameAndTypeEntry} + * @see InterfaceMethodRefEntry#owner() InterfaceMethodRefEntry::owner + * @see InterfaceMethodRefEntry#nameAndType() + * InterfaceMethodRefEntry::nameAndType */ InterfaceMethodRefEntry interfaceMethodRefEntry(ClassEntry owner, NameAndTypeEntry nameAndType); /** - * {@return A {@link InterfaceMethodRefEntry} describing a method of a class} - * If a InterfaceMethodRefEntry entry in the pool already describes this method, - * it is returned; otherwise, a new entry is added and the new entry is - * returned. + * {@return an {@link InterfaceMethodRefEntry} describing a method of an + * interface} * - * @param owner the class the method is a member of - * @param name the name of the method - * @param type the type of the method + * @param owner the interface the method is a member of + * @param name the unqualified name of the method + * @param type the method descriptor * @throws IllegalArgumentException if {@code owner} represents a primitive type + * @see InterfaceMethodRefEntry#typeSymbol() InterfaceMethodRefEntry::typeSymbol */ default InterfaceMethodRefEntry interfaceMethodRefEntry(ClassDesc owner, String name, MethodTypeDesc type) { return interfaceMethodRefEntry(classEntry(owner), nameAndTypeEntry(name, type)); } /** - * {@return A {@link MethodTypeEntry} describing a method type} - * If a MethodType entry in the pool already describes this method type, - * it is returned; otherwise, a new entry is added and the new entry is - * returned. + * {@return a {@link MethodTypeEntry} describing the same method type as + * the provided {@link MethodTypeDesc}} * * @param descriptor the symbolic descriptor of the method type + * @see MethodTypeEntry#asSymbol() MethodTypeEntry::asSymbol */ MethodTypeEntry methodTypeEntry(MethodTypeDesc descriptor); /** - * {@return A {@link MethodTypeEntry} describing a method type} - * If a MethodType entry in the pool already describes this method type, - * it is returned; otherwise, a new entry is added and the new entry is - * returned. + * {@return a {@link MethodTypeEntry} referring to a {@link Utf8Entry}} + * The {@code Utf8Entry} represents a method descriptor string. * - * @param descriptor the constant pool entry for the method type descriptor + * @param descriptor the {@code Utf8Entry} + * @see MethodTypeEntry#descriptor() MethodTypeEntry::descriptor */ MethodTypeEntry methodTypeEntry(Utf8Entry descriptor); /** - * {@return A {@link MethodHandleEntry} describing a direct method handle} - * If a MethodHandle entry in the pool already describes this method handle, - * it is returned; otherwise, a new entry is added and the new entry is - * returned. + * {@return a {@link MethodHandleEntry} describing the same method handle as + * the given {@link DirectMethodHandleDesc}} * * @param descriptor the symbolic descriptor of the method handle + * @see MethodHandleEntry#asSymbol() MethodHandleEntry::asSymbol */ default MethodHandleEntry methodHandleEntry(DirectMethodHandleDesc descriptor) { var owner = classEntry(descriptor.owner()); @@ -347,125 +393,133 @@ default MethodHandleEntry methodHandleEntry(DirectMethodHandleDesc descriptor) { } /** - * {@return A {@link MethodHandleEntry} describing a field accessor or method} - * If a MethodHandle entry in the pool already describes this method handle, - * it is returned; otherwise, a new entry is added and the new entry is - * returned. + * {@return a {@link MethodHandleEntry} encoding a reference kind and + * referring to a {@link MemberRefEntry}} The reference kind must be + * in {@code [1, 9]}, and the {@code MemberRefEntry} is subject to + * various restrictions based on the reference kind (JVMS {@jvms 4.4.8}). * - * @param refKind the reference kind of the method handle (JVMS {@jvms 4.4.8}) - * @param reference the constant pool entry describing the field or method + * @param refKind the reference kind of the method handle + * @param reference the {@code MemberRefEntry} + * @see MethodHandleInfo##refKinds Reference kinds + * @see MethodHandleEntry#kind() MethodHandleEntry::kind + * @see MethodHandleEntry#reference() MethodHandleEntry::reference */ MethodHandleEntry methodHandleEntry(int refKind, MemberRefEntry reference); /** - * {@return An {@link InvokeDynamicEntry} describing a dynamic call site} - * If an InvokeDynamic entry in the pool already describes this site, - * it is returned; otherwise, a new entry is added and the new entry is - * returned. + * {@return an {@link InvokeDynamicEntry} describing the same dynamic call + * site as the provided {@link DynamicCallSiteDesc}} * - * @param dcsd the symbolic descriptor of the method handle + * @param dcsd the symbolic descriptor of the dynamic call site + * @see InvokeDynamicEntry#asSymbol() InvokeDynamicEntry::asSymbol */ default InvokeDynamicEntry invokeDynamicEntry(DynamicCallSiteDesc dcsd) { return invokeDynamicEntry(bsmEntry((DirectMethodHandleDesc)dcsd.bootstrapMethod(), List.of(dcsd.bootstrapArgs())), nameAndTypeEntry(dcsd.invocationName(), dcsd.invocationType())); } /** - * {@return An {@link InvokeDynamicEntry} describing a dynamic call site} - * If an InvokeDynamic entry in the pool already describes this site, - * it is returned; otherwise, a new entry is added and the new entry is - * returned. + * {@return an {@link InvokeDynamicEntry} referring to a {@link + * BootstrapMethodEntry} and a {@link NameAndTypeEntry}} + * The {@code BootstrapMethodEntry} describes the bootstrap method + * and its invocation arguments in addition to the name and type, + * and the {@code NameAndTypeEntry} a name and a method descriptor. * - * @param bootstrapMethodEntry the entry in the bootstrap method table - * @param nameAndType the invocation name and type + * @param bootstrapMethodEntry the {@code BootstrapMethodEntry} + * @param nameAndType the {@code NameAndTypeEntry} + * @see InvokeDynamicEntry#bootstrap() InvokeDynamicEntry::bootstrap + * @see InvokeDynamicEntry#nameAndType() InvokeDynamicEntry::nameAndType */ InvokeDynamicEntry invokeDynamicEntry(BootstrapMethodEntry bootstrapMethodEntry, NameAndTypeEntry nameAndType); /** - * {@return A {@link ConstantDynamicEntry} describing a dynamic constant} - * If a ConstantDynamic entry in the pool already describes this site, - * it is returned; otherwise, a new entry is added and the new entry is - * returned. + * {@return a {@link ConstantDynamicEntry} describing the dynamic constant + * as the provided {@link DynamicConstantDesc}} * * @param dcd the symbolic descriptor of the constant + * @see ConstantDynamicEntry#asSymbol() ConstantDynamicEntry::asSymbol */ default ConstantDynamicEntry constantDynamicEntry(DynamicConstantDesc dcd) { return constantDynamicEntry(bsmEntry(dcd.bootstrapMethod(), List.of(dcd.bootstrapArgs())), nameAndTypeEntry(dcd.constantName(), dcd.constantType())); } /** - * {@return A {@link ConstantDynamicEntry} describing a dynamic constant} - * If a ConstantDynamic entry in the pool already describes this site, - * it is returned; otherwise, a new entry is added and the new entry is - * returned. + * {@return a {@link ConstantDynamicEntry} referring to a {@link + * BootstrapMethodEntry} and a {@link NameAndTypeEntry}} + * The {@code BootstrapMethodEntry} describes the bootstrap method + * and its invocation arguments in addition to the name and type, + * and the {@code NameAndTypeEntry} a name and a field descriptor. * - * @param bootstrapMethodEntry the entry in the bootstrap method table - * @param nameAndType the invocation name and type + * @param bootstrapMethodEntry the {@code BootstrapMethodEntry} + * @param nameAndType the {@code NameAndTypeEntry} + * @see ConstantDynamicEntry#bootstrap() ConstantDynamicEntry::bootstrap + * @see ConstantDynamicEntry#nameAndType() ConstantDynamicEntry::nameAndType */ ConstantDynamicEntry constantDynamicEntry(BootstrapMethodEntry bootstrapMethodEntry, NameAndTypeEntry nameAndType); /** - * {@return An {@link IntegerEntry} describing the provided value} - * If an integer entry in the pool already describes this value, it is returned; - * otherwise, a new entry is added and the new entry is returned. + * {@return an {@link IntegerEntry} describing the provided value} * * @param value the value + * @see IntegerEntry#intValue() IntegerEntry::intValue */ IntegerEntry intEntry(int value); /** - * {@return A {@link FloatEntry} describing the provided value} - * If a float entry in the pool already describes this value, it is returned; - * otherwise, a new entry is added and the new entry is returned. + * {@return a {@link FloatEntry} describing the provided value} * * @param value the value + * @see FloatEntry#floatValue() FloatEntry::floatValue */ FloatEntry floatEntry(float value); /** - * {@return A {@link LongEntry} describing the provided value} - * If a long entry in the pool already describes this value, it is returned; - * otherwise, a new entry is added and the new entry is returned. + * {@return a {@link LongEntry} describing the provided value} * * @param value the value + * @see LongEntry#longValue() LongEntry::longValue */ LongEntry longEntry(long value); /** - * {@return A {@link DoubleEntry} describing the provided value} - * If a double entry in the pool already describes this value, it is returned; - * otherwise, a new entry is added and the new entry is returned. + * {@return a {@link DoubleEntry} describing the provided value} * * @param value the value + * @see DoubleEntry#doubleValue() DoubleEntry::doubleValue */ DoubleEntry doubleEntry(double value); /** - * {@return A {@link StringEntry} referencing the provided UTF8 entry} - * If a String entry in the pool already describes this value, it is returned; - * otherwise, a new entry is added and the new entry is returned. + * {@return a {@link StringEntry} referring to a {@link Utf8Entry}} + * The {@code Utf8Entry} describes the string value. * - * @param utf8 the UTF8 entry describing the string + * @param utf8 the {@code Utf8Entry} + * @see StringEntry#utf8() StringEntry::utf8 */ StringEntry stringEntry(Utf8Entry utf8); /** - * {@return A {@link StringEntry} describing the provided value} - * If a string entry in the pool already describes this value, it is returned; - * otherwise, a new entry is added and the new entry is returned. + * {@return a {@link StringEntry} describing the provided value} * * @param value the value + * @see StringEntry#stringValue() StringEntry::stringValue */ default StringEntry stringEntry(String value) { return stringEntry(utf8Entry(value)); } /** - * {@return A {@link ConstantValueEntry} describing the provided - * Integer, Long, Float, Double, or String constant} + * {@return a {@link ConstantValueEntry} describing the provided constant + * {@link Integer}, {@link Long}, {@link Float}, {@link Double}, or {@link + * String} value} * - * @param c the constant - * @see ConstantValueEntry#constantValue() + * @param c the provided constant value + * @throws IllegalArgumentException if the value is not one of {@code + * Integer}, {@code Long}, {@code Float}, {@code Double}, or {@code + * String} + * @see ConstantValueEntry#constantValue() ConstantValueEntry::constantValue + * @see ConstantValueAttribute#of(ConstantDesc) + * ConstantValueAttribute::of(ConstantDesc) */ default ConstantValueEntry constantValueEntry(ConstantDesc c) { if (c instanceof Integer i) return intEntry(i); @@ -477,13 +531,10 @@ default ConstantValueEntry constantValueEntry(ConstantDesc c) { } /** - * {@return A {@link LoadableConstantEntry} describing the provided - * constant} The constant should be an Integer, String, Long, Float, - * Double, ClassDesc (for a Class constant), MethodTypeDesc (for a MethodType - * constant), DirectMethodHandleDesc (for a MethodHandle constant), or - * a DynamicConstantDesc (for a dynamic constant.) + * {@return a {@link LoadableConstantEntry} describing the provided constant + * value} * - * @param c the constant + * @param c the nominal descriptor for the constant */ default LoadableConstantEntry loadableConstantEntry(ConstantDesc c) { if (c instanceof Integer i) return intEntry(i); @@ -500,10 +551,10 @@ default LoadableConstantEntry loadableConstantEntry(ConstantDesc c) { /** * {@return a {@link BootstrapMethodEntry} describing the provided - * bootstrap method and static arguments} + * bootstrap method and arguments} * * @param methodReference the bootstrap method - * @param arguments the bootstrap arguments + * @param arguments the arguments */ default BootstrapMethodEntry bsmEntry(DirectMethodHandleDesc methodReference, List arguments) { @@ -512,11 +563,16 @@ default BootstrapMethodEntry bsmEntry(DirectMethodHandleDesc methodReference, } /** - * {@return a {@link BootstrapMethodEntry} describing the provided - * bootstrap method and static arguments} + * {@return a {@link BootstrapMethodEntry} referring to a {@link + * MethodHandleEntry} and a list of {@link LoadableConstantEntry}} + * The {@code MethodHandleEntry} is the bootstrap method, and the + * list of {@code LoadableConstantEntry} is the arguments. * - * @param methodReference the bootstrap method - * @param arguments the bootstrap arguments + * @param methodReference the {@code MethodHandleEntry} + * @param arguments the list of {@code LoadableConstantEntry} + * @see BootstrapMethodEntry#bootstrapMethod() + * BootstrapMethodEntry::bootstrapMethod + * @see BootstrapMethodEntry#arguments() BootstrapMethodEntry::arguments */ BootstrapMethodEntry bsmEntry(MethodHandleEntry methodReference, List arguments); diff --git a/src/java.base/share/classes/java/lang/classfile/constantpool/ConstantPoolException.java b/src/java.base/share/classes/java/lang/classfile/constantpool/ConstantPoolException.java index ce5ed26c4c9..bb3b33ba21c 100644 --- a/src/java.base/share/classes/java/lang/classfile/constantpool/ConstantPoolException.java +++ b/src/java.base/share/classes/java/lang/classfile/constantpool/ConstantPoolException.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2023, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2023, 2025, 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 @@ -27,7 +27,9 @@ /** * Thrown to indicate that requested entry cannot be obtained from the constant - * pool. + * pool or the bootstrap method table. This is also thrown when the lazy + * evaluation of constant pool or bootstrap method table entries encounter + * format errors. * * @since 24 */ @@ -47,7 +49,8 @@ public ConstantPoolException() { * Constructs a {@code ConstantPoolException} with the specified detail * message. * - * @param message the detail message. + * @param message the detail message, may be {@code null} for no detail + * message */ public ConstantPoolException(String message) { super(message); @@ -55,11 +58,10 @@ public ConstantPoolException(String message) { /** * Constructs a {@code ConstantPoolException} with the specified cause and - * a detail message of {@code (cause==null ? null : cause.toString())}. - * @param cause the cause (which is saved for later retrieval by the - * {@link Throwable#getCause()} method). (A {@code null} value is - * permitted, and indicates that the cause is nonexistent or - * unknown.) + * a detail message of {@code cause == null ? null : cause.toString()}. + * + * @param cause the cause, may be {@code null} for nonexistent or unknown + * cause */ public ConstantPoolException(Throwable cause) { super(cause); @@ -69,12 +71,10 @@ public ConstantPoolException(Throwable cause) { * Constructs a {@code ConstantPoolException} with the specified detail * message and cause. * - * @param message the detail message (which is saved for later retrieval - * by the {@link Throwable#getMessage()} method). - * @param cause the cause (which is saved for later retrieval by the - * {@link Throwable#getCause()} method). (A {@code null} value - * is permitted, and indicates that the cause is nonexistent or - * unknown.) + * @param message the detail message, may be {@code null} for no detail + * message + * @param cause the cause, may be {@code null} for nonexistent or unknown + * cause */ public ConstantPoolException(String message, Throwable cause) { super(message, cause); diff --git a/src/java.base/share/classes/java/lang/classfile/constantpool/ConstantValueEntry.java b/src/java.base/share/classes/java/lang/classfile/constantpool/ConstantValueEntry.java index ae746042aa4..8613fdd2cb9 100644 --- a/src/java.base/share/classes/java/lang/classfile/constantpool/ConstantValueEntry.java +++ b/src/java.base/share/classes/java/lang/classfile/constantpool/ConstantValueEntry.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2022, 2025, 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 @@ -28,10 +28,11 @@ import java.lang.constant.ConstantDesc; /** - * Models a constant pool entry that can be used as the constant in a - * {@link Attributes#constantValue() ConstantValue} attribute; this includes the four - * primitive constant types and {@linkplain String} constants. + * Marker interface for constant pool entries that can represent constant values + * in the {@link Attributes#constantValue() ConstantValue} attribute. * + * @see ConstantPoolBuilder#constantValueEntry + * ConstantPoolBuilder::constantValueEntry * @sealedGraph * @since 24 */ @@ -39,8 +40,8 @@ public sealed interface ConstantValueEntry extends LoadableConstantEntry permits DoubleEntry, FloatEntry, IntegerEntry, LongEntry, StringEntry { /** - * {@return the constant value} The constant value will be an {@link Integer}, - * {@link Long}, {@link Float}, {@link Double}, or {@link String}. + * {@return the constant value} The constant value will be an {@link + * Integer}, {@link Long}, {@link Float}, {@link Double}, or {@link String}. * * @see ConstantPoolBuilder#constantValueEntry(ConstantDesc) */ diff --git a/src/java.base/share/classes/java/lang/classfile/constantpool/DoubleEntry.java b/src/java.base/share/classes/java/lang/classfile/constantpool/DoubleEntry.java index ebc3a837bb0..bc6956b5bf5 100644 --- a/src/java.base/share/classes/java/lang/classfile/constantpool/DoubleEntry.java +++ b/src/java.base/share/classes/java/lang/classfile/constantpool/DoubleEntry.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2022, 2025, 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 @@ -29,10 +29,20 @@ import jdk.internal.classfile.impl.AbstractPoolEntry; /** - * Models a {@code CONSTANT_Double_info} constant in the constant pool of a - * classfile. - * @jvms 4.4.5 The CONSTANT_Long_info and CONSTANT_Double_info Structures + * Models a {@code CONSTANT_Double_info} structure, representing a {@code + * double} constant, in the constant pool of a {@code class} file. + *

+ * The use of a {@code DoubleEntry} is modeled by a {@code double}. Conversions + * are through {@link ConstantPoolBuilder#doubleEntry} and {@link #doubleValue()}. + * In the conversions, all NaN values of the {@code double} may be collapsed + * into a single {@linkplain Double#NaN "canonical" NaN value}. + *

+ * A double entry has a {@linkplain #width() width} of {@code 2}, making its + * subsequent constant pool index valid and unusable. * + * @see ConstantPoolBuilder#doubleEntry ConstantPoolBuilder::doubleEntry + * @jvms 4.4.5 The {@code CONSTANT_Long_info} and {@code CONSTANT_Double_info} + * Structures * @since 24 */ public sealed interface DoubleEntry @@ -40,13 +50,13 @@ public sealed interface DoubleEntry permits AbstractPoolEntry.DoubleEntryImpl { /** - * {@return the double value} + * {@return the {@code double} value} + * + * @see ConstantPoolBuilder#doubleEntry(double) + * ConstantPoolBuilder::doubleEntry(double) */ double doubleValue(); - /** - * {@return the type of the constant} - */ @Override default TypeKind typeKind() { return TypeKind.DOUBLE; diff --git a/src/java.base/share/classes/java/lang/classfile/constantpool/DynamicConstantPoolEntry.java b/src/java.base/share/classes/java/lang/classfile/constantpool/DynamicConstantPoolEntry.java index 3ec4fbbdbee..b72424db44e 100644 --- a/src/java.base/share/classes/java/lang/classfile/constantpool/DynamicConstantPoolEntry.java +++ b/src/java.base/share/classes/java/lang/classfile/constantpool/DynamicConstantPoolEntry.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2022, 2025, 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 @@ -27,10 +27,27 @@ import java.lang.classfile.BootstrapMethodEntry; /** - * Models a dynamic constant pool entry, which is either {@link ConstantDynamicEntry} - * or {@link InvokeDynamicEntry}. - * @jvms 4.4.10 The CONSTANT_Dynamic_info and CONSTANT_InvokeDynamic_info Structures + * Superinterface modeling dynamically-computed constant pool entries, which + * include {@link ConstantDynamicEntry} and {@link InvokeDynamicEntry}, in the + * constant pool of a {@code class} file. + *

+ * Different types of dynamically-computed constant pool entries bear structural + * similarities, but they appear in distinct locations. As a result, their uses + * are represented by different symbolic descriptors, specific to each subtype. + *

+ * A dynamic constant entry is composite: + * {@snippet lang=text : + * DynamicConstantPoolEntry( + * BootstrapMethodEntry bootstrap, // @link substring="bootstrap" target="#bootstrap()" + * NameAndTypeEntry nameAndType // @link substring="nameAndType" target="#nameAndType()" + * ) + * } * + * @see java.lang.invoke##jvm_mods Dynamic resolution of call sites and + * constants + * @jvms 4.4.10 The {@code CONSTANT_Dynamic_info} and {@code + * CONSTANT_InvokeDynamic_info} Structures + * @jvms 5.4.3.6 Dynamically-Computed Constant and Call Site Resolution * @sealedGraph * @since 24 */ @@ -39,28 +56,50 @@ public sealed interface DynamicConstantPoolEntry extends PoolEntry /** * {@return the entry in the bootstrap method table for this constant} + * + * @see java.lang.invoke##bsm Execution of bootstrap methods + * @see ConstantPoolBuilder#constantDynamicEntry(BootstrapMethodEntry, NameAndTypeEntry) + * ConstantPoolBuilder::constantDynamicEntry(BootstrapMethodEntry, NameAndTypeEntry) + * @see ConstantPoolBuilder#invokeDynamicEntry(BootstrapMethodEntry, NameAndTypeEntry) + * ConstantPoolBuilder::invokeDynamicEntry(BootstrapMethodEntry, NameAndTypeEntry) */ BootstrapMethodEntry bootstrap(); /** - * {@return index of the entry in the bootstrap method table for this constant} + * {@return index of the entry in the bootstrap method table for this + * constant} The return value is equivalent to {@code + * bootstrap().bsmIndex()}. */ int bootstrapMethodIndex(); /** - * {@return the invocation name and type} + * {@return the name and the descriptor string indicated by this symbolic + * reference} + * + * @see java.lang.invoke##bsm Execution of bootstrap methods + * @see ConstantPoolBuilder#constantDynamicEntry(BootstrapMethodEntry, NameAndTypeEntry) + * ConstantPoolBuilder::constantDynamicEntry(BootstrapMethodEntry, NameAndTypeEntry) + * @see ConstantPoolBuilder#invokeDynamicEntry(BootstrapMethodEntry, NameAndTypeEntry) + * ConstantPoolBuilder::invokeDynamicEntry(BootstrapMethodEntry, NameAndTypeEntry) */ NameAndTypeEntry nameAndType(); /** - * {@return the invocation name} + * {@return the name indicated by this symbolic reference} */ default Utf8Entry name() { return nameAndType().name(); } /** - * {@return the invocation type} + * {@return the descriptor string indicated by this symbolic reference} + * This is a field descriptor string if this entry is a {@link + * ConstantDynamicEntry}, or a method descriptor string if this entry is a + * {@link InvokeDynamicEntry}. + * + * @apiNote + * Each subinterface has its specific accessor named {@code typeSymbol} for + * the symbolic descriptor derived from this descriptor string. */ default Utf8Entry type() { return nameAndType().type(); diff --git a/src/java.base/share/classes/java/lang/classfile/constantpool/FieldRefEntry.java b/src/java.base/share/classes/java/lang/classfile/constantpool/FieldRefEntry.java index 47f5b6710d8..9f984acd7ba 100644 --- a/src/java.base/share/classes/java/lang/classfile/constantpool/FieldRefEntry.java +++ b/src/java.base/share/classes/java/lang/classfile/constantpool/FieldRefEntry.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2022, 2025, 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 @@ -30,17 +30,31 @@ import jdk.internal.classfile.impl.Util; /** - * Models a {@code CONSTANT_Fieldref_info} constant in the constant pool of a - * classfile. - * @jvms 4.4.2 The CONSTANT_Fieldref_info, CONSTANT_Methodref_info, and CONSTANT_InterfaceMethodref_info Structures + * Models a {@code CONSTANT_Fieldref_info} structure, or a symbolic reference + * to a field, in the constant pool of a {@code class} file. + *

+ * A field reference constant pool entry is composite: + * {@snippet lang=text : + * // @link substring="FieldRefEntry" target="ConstantPoolBuilder#fieldRefEntry(ClassEntry, NameAndTypeEntry)" : + * FieldRefEntry( + * ClassEntry owner, // @link substring="owner" target="#owner()" + * NameAndTypeEntry nameAndType // @link substring="nameAndType" target="#nameAndType()" + * ) + * } + * where the {@link #type() nameAndType.type()} represents a {@linkplain + * #typeSymbol() field descriptor} string. * + * @see ConstantPoolBuilder#fieldRefEntry ConstantPoolBuilder::fieldRefEntry + * @jvms 4.4.2 The {@code CONSTANT_Fieldref_info}, {@code + * CONSTANT_Methodref_info}, and {@code + * CONSTANT_InterfaceMethodref_info} Structures * @since 24 */ public sealed interface FieldRefEntry extends MemberRefEntry permits AbstractPoolEntry.FieldRefEntryImpl { /** - * {@return a symbolic descriptor for the field's type} + * {@return a symbolic descriptor for the {@linkplain #type() field type}} */ default ClassDesc typeSymbol() { return Util.fieldTypeSymbol(type()); diff --git a/src/java.base/share/classes/java/lang/classfile/constantpool/FloatEntry.java b/src/java.base/share/classes/java/lang/classfile/constantpool/FloatEntry.java index eeb44e92b7c..2ccf3fb94e4 100644 --- a/src/java.base/share/classes/java/lang/classfile/constantpool/FloatEntry.java +++ b/src/java.base/share/classes/java/lang/classfile/constantpool/FloatEntry.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2022, 2025, 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 @@ -29,10 +29,17 @@ import jdk.internal.classfile.impl.AbstractPoolEntry; /** - * Models a {@code CONSTANT_Float_info} constant in the constant pool of a - * classfile. - * @jvms 4.4.4 The CONSTANT_Integer_info and CONSTANT_Float_info Structures + * Models a {@code CONSTANT_Float_info} structure, or a {@code float} constant, + * in the constant pool of a {@code class} file. + *

+ * The use of a {@code FloatEntry} is modeled by a {@code float}. Conversions + * are through {@link ConstantPoolBuilder#floatEntry} and {@link #floatValue()}. + * In the conversions, all NaN values of the {@code float} may be collapsed into + * a single {@linkplain Float#NaN "canonical" NaN value}. * + * @see ConstantPoolBuilder#floatEntry ConstantPoolBuilder::floatEntry + * @jvms 4.4.4 The {@code CONSTANT_Integer_info} and {@code CONSTANT_Float_info} + * Structures * @since 24 */ public sealed interface FloatEntry @@ -40,14 +47,12 @@ public sealed interface FloatEntry permits AbstractPoolEntry.FloatEntryImpl { /** - * {@return the float value} + * {@return the {@code float} value} + * + * @see ConstantPoolBuilder#floatEntry(float) */ - float floatValue(); - /** - * {@return the type of the constant} - */ @Override default TypeKind typeKind() { return TypeKind.FLOAT; diff --git a/src/java.base/share/classes/java/lang/classfile/constantpool/IntegerEntry.java b/src/java.base/share/classes/java/lang/classfile/constantpool/IntegerEntry.java index 908f17d1cb7..d6d2c28ed57 100644 --- a/src/java.base/share/classes/java/lang/classfile/constantpool/IntegerEntry.java +++ b/src/java.base/share/classes/java/lang/classfile/constantpool/IntegerEntry.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2022, 2025, 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 @@ -29,10 +29,15 @@ import jdk.internal.classfile.impl.AbstractPoolEntry; /** - * Models a {@code CONSTANT_Integer_info} constant in the constant pool of a - * classfile. - * @jvms 4.4.4 The CONSTANT_Integer_info and CONSTANT_Float_info Structures + * Models a {@code CONSTANT_Integer_info} structure, or an {@code int} constant, + * in the constant pool of a {@code class} file. + *

+ * The use of a {@code IntegerEntry} is modeled by an {@code int}. Conversions + * are through {@link ConstantPoolBuilder#intEntry(int)} and {@link #intValue()}. * + * @see ConstantPoolBuilder#intEntry ConstantPoolBuilder::intEntry + * @jvms 4.4.4 The {@code CONSTANT_Integer_info} and {@code CONSTANT_Float_info} + * Structures * @since 24 */ public sealed interface IntegerEntry @@ -40,13 +45,12 @@ public sealed interface IntegerEntry permits AbstractPoolEntry.IntegerEntryImpl { /** - * {@return the integer value} + * {@return the {@code int} value} + * + * @see ConstantPoolBuilder#intEntry(int) */ int intValue(); - /** - * {@return the type of the constant} - */ @Override default TypeKind typeKind() { return TypeKind.INT; diff --git a/src/java.base/share/classes/java/lang/classfile/constantpool/InterfaceMethodRefEntry.java b/src/java.base/share/classes/java/lang/classfile/constantpool/InterfaceMethodRefEntry.java index 7b1a94f123a..e29c9f5b6f9 100644 --- a/src/java.base/share/classes/java/lang/classfile/constantpool/InterfaceMethodRefEntry.java +++ b/src/java.base/share/classes/java/lang/classfile/constantpool/InterfaceMethodRefEntry.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2022, 2025, 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 @@ -30,10 +30,26 @@ import jdk.internal.classfile.impl.Util; /** - * Models a {@code CONSTANT_InterfaceMethodRef_info} constant in the constant pool of a - * classfile. - * @jvms 4.4.2 The CONSTANT_Fieldref_info, CONSTANT_Methodref_info, and CONSTANT_InterfaceMethodref_info Structures + * Models a {@code CONSTANT_InterfaceMethodRef_info} structure, or a symbolic + * reference to an interface method, in the constant pool of a {@code class} + * file. + *

+ * An interface method reference entry is composite: + * {@snippet lang=text : + * // @link substring="InterfaceMethodRefEntry" target="ConstantPoolBuilder#interfaceMethodRefEntry(ClassEntry, NameAndTypeEntry)" : + * InterfaceMethodRefEntry( + * ClassEntry owner, // @link substring="owner" target="#owner()" + * NameAndTypeEntry nameAndType // @link substring="nameAndType" target="#nameAndType()" + * ) + * } + * where the {@link #type() type} in the {@code nameAndType} is a {@linkplain + * #typeSymbol() method descriptor} string. * + * @see ConstantPoolBuilder#interfaceMethodRefEntry + * ConstantPoolBuilder::interfaceMethodRefEntry + * @jvms 4.4.2 The {@code CONSTANT_Fieldref_info}, {@code + * CONSTANT_Methodref_info}, and {@code + * CONSTANT_InterfaceMethodref_info} Structures * @since 24 */ public sealed interface InterfaceMethodRefEntry @@ -41,7 +57,7 @@ public sealed interface InterfaceMethodRefEntry permits AbstractPoolEntry.InterfaceMethodRefEntryImpl { /** - * {@return a symbolic descriptor for the interface method's type} + * {@return a symbolic descriptor for the {@linkplain #type() method type}} */ default MethodTypeDesc typeSymbol() { return Util.methodTypeSymbol(type()); diff --git a/src/java.base/share/classes/java/lang/classfile/constantpool/InvokeDynamicEntry.java b/src/java.base/share/classes/java/lang/classfile/constantpool/InvokeDynamicEntry.java index 0cc8b6823df..02c2fce2e02 100644 --- a/src/java.base/share/classes/java/lang/classfile/constantpool/InvokeDynamicEntry.java +++ b/src/java.base/share/classes/java/lang/classfile/constantpool/InvokeDynamicEntry.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2022, 2025, 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 @@ -32,9 +32,38 @@ import jdk.internal.classfile.impl.Util; /** - * Models a constant pool entry for a dynamic call site. - * @jvms 4.4.10 The CONSTANT_Dynamic_info and CONSTANT_InvokeDynamic_info Structures + * Models a {@code CONSTANT_InvokeDynamic_info} structure, or the symbolic + * reference to a {@index "dynamically-computed call site"}, in the + * constant pool of a {@code class} file. + *

+ * The use of a {@code InvokeDynamicEntry} is modeled by a {@link + * DynamicCallSiteDesc} symbolic descriptor. It can be obtained from {@link + * #asSymbol() InvokeDynamicEntry::asSymbol} and converted back to a constant + * pool entry through {@link ConstantPoolBuilder#invokeDynamicEntry(DynamicCallSiteDesc) + * ConstantPoolBuilder::invokeDynamicEntry}. + *

+ * An invoke dynamic entry is composite: + * {@snippet lang=text : + * // @link substring="InvokeDynamicEntry" target="ConstantPoolBuilder#invokeDynamicEntry(BootstrapMethodEntry, NameAndTypeEntry)" : + * InvokeDynamicEntry( + * BootstrapMethodEntry bootstrap, // @link substring="bootstrap" target="#bootstrap()" + * NameAndTypeEntry nameAndType // @link substring="nameAndType" target="#nameAndType()" + * ) + * } + * where the {@link #type() type} in the {@code nameAndType} is a {@linkplain + * #typeSymbol() method descriptor} string. * + * @apiNote + * A dynamically-computed call site is frequently called a {@index "dynamic + * call site"}, or an {@index "indy"}, from the abbreviation of + * "invoke dynamic". + * + * @see ConstantPoolBuilder#invokeDynamicEntry + * ConstantPoolBuilder::invokeDynamicEntry + * @see DynamicCallSiteDesc + * @see java.lang.invoke##indyinsn Dynamically-computed call sites + * @jvms 4.4.10 The {@code CONSTANT_Dynamic_info} and {@code + * CONSTANT_InvokeDynamic_info} Structures * @since 24 */ public sealed interface InvokeDynamicEntry @@ -42,14 +71,18 @@ public sealed interface InvokeDynamicEntry permits AbstractPoolEntry.InvokeDynamicEntryImpl { /** - * {@return a symbolic descriptor for the call site's invocation type} + * {@return a symbolic descriptor for the {@linkplain #type() invocation + * type} of this dynamic call site} */ default MethodTypeDesc typeSymbol() { return Util.methodTypeSymbol(type()); } /** - * {@return a symbolic descriptor for the dynamic call site} + * {@return a symbolic descriptor for this dynamic call site} + * + * @see ConstantPoolBuilder#invokeDynamicEntry(DynamicCallSiteDesc) + * ConstantPoolBuilder::invokeDynamicEntry(DynamicCallSiteDesc) */ default DynamicCallSiteDesc asSymbol() { return DynamicCallSiteDesc.of(bootstrap().bootstrapMethod().asSymbol(), diff --git a/src/java.base/share/classes/java/lang/classfile/constantpool/LoadableConstantEntry.java b/src/java.base/share/classes/java/lang/classfile/constantpool/LoadableConstantEntry.java index 32f85f64c7e..9137bebea35 100644 --- a/src/java.base/share/classes/java/lang/classfile/constantpool/LoadableConstantEntry.java +++ b/src/java.base/share/classes/java/lang/classfile/constantpool/LoadableConstantEntry.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2022, 2025, 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,22 @@ */ package java.lang.classfile.constantpool; +import java.lang.classfile.CodeBuilder; +import java.lang.classfile.Opcode; import java.lang.classfile.TypeKind; +import java.lang.classfile.instruction.ConstantInstruction; import java.lang.constant.ConstantDesc; /** * Marker interface for constant pool entries suitable for loading via the - * {@code LDC} instructions. + * {@link ConstantInstruction.LoadConstantInstruction ldc} instructions. + *

+ * The use of a {@code LoadableConstantEntry} is modeled by a {@link ConstantDesc}. + * Conversions are through {@link ConstantPoolBuilder#loadableConstantEntry(ConstantDesc)} + * and {@link #constantValue()}. * + * @see CodeBuilder#ldc(LoadableConstantEntry) + * @jvms 4.4 The Constant Pool * @sealedGraph * @since 24 */ @@ -38,12 +47,19 @@ public sealed interface LoadableConstantEntry extends PoolEntry permits ClassEntry, ConstantDynamicEntry, ConstantValueEntry, MethodHandleEntry, MethodTypeEntry { /** - * {@return the constant described by this entry} + * {@return a symbolic descriptor of this constant} + * + * @see ConstantPoolBuilder#loadableConstantEntry(ConstantDesc) */ ConstantDesc constantValue(); /** - * {@return the type of the constant} + * {@return the data type of this constant} + *

+ * If the data type is of {@linkplain TypeKind#slotSize() category} 2, this + * constant must be loaded with {@link Opcode#LDC2_W ldc2_w}; otherwise, the + * data type is of category 1, and this constant must be loaded with {@link + * Opcode#LDC ldc} or {@link Opcode#LDC_W ldc_w}. */ default TypeKind typeKind() { return TypeKind.REFERENCE; diff --git a/src/java.base/share/classes/java/lang/classfile/constantpool/LongEntry.java b/src/java.base/share/classes/java/lang/classfile/constantpool/LongEntry.java index cd38dcfe014..dbf947d1f1d 100644 --- a/src/java.base/share/classes/java/lang/classfile/constantpool/LongEntry.java +++ b/src/java.base/share/classes/java/lang/classfile/constantpool/LongEntry.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2022, 2025, 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 @@ -29,10 +29,18 @@ import jdk.internal.classfile.impl.AbstractPoolEntry; /** - * Models a {@code CONSTANT_Long_info} constant in the constant pool of a - * classfile. - * @jvms 4.4.5 The CONSTANT_Long_info and CONSTANT_Double_info Structures + * Models a {@code CONSTANT_Long_info} structure, or a {@code long} constant, in + * the constant pool of a {@code class} file. + *

+ * The use of a {@code LongEntry} is modeled by a {@code long}. Conversions are + * through {@link ConstantPoolBuilder#longEntry(long)} and {@link #longValue()}. + *

+ * A long entry has a {@linkplain #width() width} of {@code 2}, making its + * subsequent constant pool index valid and unusable. * + * @see ConstantPoolBuilder#longEntry ConstantPoolBuilder::longEntry + * @jvms 4.4.5 The {@code CONSTANT_Long_info} and {@code CONSTANT_Double_info} + * Structures * @since 24 */ public sealed interface LongEntry @@ -40,7 +48,10 @@ public sealed interface LongEntry permits AbstractPoolEntry.LongEntryImpl { /** - * {@return the long value} + * {@return the {@code long} value} + * + * @see ConstantPoolBuilder#longEntry(long) + * ConstantPoolBuilder::longEntry(long) */ long longValue(); diff --git a/src/java.base/share/classes/java/lang/classfile/constantpool/MemberRefEntry.java b/src/java.base/share/classes/java/lang/classfile/constantpool/MemberRefEntry.java index 12d68796dd7..3d59a3c96c9 100644 --- a/src/java.base/share/classes/java/lang/classfile/constantpool/MemberRefEntry.java +++ b/src/java.base/share/classes/java/lang/classfile/constantpool/MemberRefEntry.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2022, 2025, 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,24 +24,45 @@ */ package java.lang.classfile.constantpool; +import java.lang.classfile.Opcode; + import jdk.internal.classfile.impl.AbstractPoolEntry; /** - * Models a member reference constant in the constant pool of a classfile, - * which includes references to fields, methods, and interface methods. + * Superinterface modeling symbolic references to a member of a class or interface + * in the constant pool of a {@code class} file, which include references to + * {@linkplain FieldRefEntry fields}, {@linkplain MethodRefEntry class methods}, + * and {@linkplain InterfaceMethodRefEntry interface methods}. + *

+ * Different types of symbolic references to a member of a class or interface + * bear structural similarities and share parts of the resolution processes, and + * they can sometimes appear in the same locations. For example, both {@link + * MethodRefEntry} and {@link InterfaceMethodRefEntry} can appear in an {@link + * Opcode#INVOKESTATIC invokestatic} instruction. + *

+ * A member reference entry is composite: + * {@snippet lang=text : + * MemberRefEntry( + * ClassEntry owner, // @link substring="owner" target="#owner()" + * NameAndTypeEntry nameAndType // @link substring="nameAndType" target="#nameAndType()" + * ) + * } * + * @jvms 4.4.2 The {@code CONSTANT_Fieldref_info}, {@code + * CONSTANT_Methodref_info}, and {@code + * CONSTANT_InterfaceMethodref_info} Structures * @sealedGraph * @since 24 */ public sealed interface MemberRefEntry extends PoolEntry permits FieldRefEntry, InterfaceMethodRefEntry, MethodRefEntry, AbstractPoolEntry.AbstractMemberRefEntry { /** - * {@return the class in which this member ref lives} + * {@return the class or interface which this member belongs to} */ ClassEntry owner(); /** - * {@return the name and type of the member} + * {@return the name and descriptor string of the member} */ NameAndTypeEntry nameAndType(); @@ -53,7 +74,14 @@ default Utf8Entry name() { } /** - * {@return the type of the member} + * {@return the descriptor string of the member} This is a field descriptor + * string if this entry is a {@link FieldRefEntry}, or a method descriptor + * string if this entry is a {@link MethodRefEntry} or {@link + * InterfaceMethodRefEntry}. + * + * @apiNote + * Each subinterface defines a {@code typeSymbol()} accessor for the + * symbolic descriptor for the member type. */ default Utf8Entry type() { return nameAndType().type(); diff --git a/src/java.base/share/classes/java/lang/classfile/constantpool/MethodHandleEntry.java b/src/java.base/share/classes/java/lang/classfile/constantpool/MethodHandleEntry.java index d2e08ef178c..22c07236e8a 100644 --- a/src/java.base/share/classes/java/lang/classfile/constantpool/MethodHandleEntry.java +++ b/src/java.base/share/classes/java/lang/classfile/constantpool/MethodHandleEntry.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2022, 2025, 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,13 +26,35 @@ import java.lang.constant.ConstantDesc; import java.lang.constant.DirectMethodHandleDesc; +import java.lang.invoke.MethodHandle; +import java.lang.invoke.MethodHandleInfo; import jdk.internal.classfile.impl.AbstractPoolEntry; /** - * Models a {@code CONSTANT_MethodHandle_info} constant in the constant pool of a - * classfile. - * @jvms 4.4.8 The CONSTANT_MethodHandle_info Structure + * Models a {@code CONSTANT_MethodHandle_info} structure, or a symbolic + * reference to a {@linkplain MethodHandle method handle}, in the constant pool + * of a {@code class} file. The method handle directly accesses an accessible + * method, field, or constructor. + *

+ * The use of a {@code MethodHandleEntry} is modeled by a {@link + * DirectMethodHandleDesc}. Conversions are through {@link + * ConstantPoolBuilder#methodHandleEntry(DirectMethodHandleDesc)} and {@link + * #asSymbol()}. + *

+ * A method handle entry is composite: + * {@snippet lang=text : + * // @link substring="MethodHandleEntry" target="ConstantPoolBuilder#methodHandleEntry(int, MemberRefEntry)" : + * MethodHandleEntry( + * int refKind, // @link substring="refKind" target="#kind()" + * MemberRefEntry reference // @link substring="reference" target="#reference()" + * ) + * } + * where {@code refKind} is in the range {@code [1, 9]}. + * + * @see ConstantPoolBuilder#methodHandleEntry + * ConstantPoolBuilder::methodHandleEntry + * @jvms 4.4.8 The {@code CONSTANT_MethodHandle_info} Structure * * @since 24 */ @@ -40,6 +62,11 @@ public sealed interface MethodHandleEntry extends LoadableConstantEntry permits AbstractPoolEntry.MethodHandleEntryImpl { + /** + * {@inheritDoc} + *

+ * This is equivalent to {@link #asSymbol() asSymbol()}. + */ @Override default ConstantDesc constantValue() { return asSymbol(); @@ -47,17 +74,22 @@ default ConstantDesc constantValue() { /** * {@return the reference kind of this method handle (JVMS {@jvms 4.4.8})} - * @see java.lang.invoke.MethodHandleInfo + * + * @see MethodHandleInfo##refkinds Reference kinds */ int kind(); /** - * {@return the constant pool entry describing the method} + * {@return the constant pool entry describing the field or method, + * according to the {@linkplain #kind() reference kind}} */ MemberRefEntry reference(); /** * {@return a symbolic descriptor for this method handle} + * + * @see ConstantPoolBuilder#methodHandleEntry(DirectMethodHandleDesc) + * ConstantPoolBuilder::methodHandleEntry(DirectMethodHandleDesc) */ DirectMethodHandleDesc asSymbol(); } diff --git a/src/java.base/share/classes/java/lang/classfile/constantpool/MethodRefEntry.java b/src/java.base/share/classes/java/lang/classfile/constantpool/MethodRefEntry.java index 5be9e88fa2f..29503741ec3 100644 --- a/src/java.base/share/classes/java/lang/classfile/constantpool/MethodRefEntry.java +++ b/src/java.base/share/classes/java/lang/classfile/constantpool/MethodRefEntry.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2022, 2025, 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 @@ -30,17 +30,31 @@ import jdk.internal.classfile.impl.Util; /** - * Models a {@code CONSTANT_MethodRef_info} constant in the constant pool of a - * classfile. - * @jvms 4.4.2 The CONSTANT_Fieldref_info, CONSTANT_Methodref_info, and CONSTANT_InterfaceMethodref_info Structures + * Models a {@code CONSTANT_MethodRef_info} structure, or a symbolic reference + * to a class method, in the constant pool of a {@code class} file. + *

+ * A class method reference entry is composite: + * {@snippet lang=text : + * // @link substring="MethodRefEntry" target="ConstantPoolBuilder#methodRefEntry(ClassEntry, NameAndTypeEntry)" : + * MethodRefEntry( + * ClassEntry owner, // @link substring="owner" target="#owner()" + * NameAndTypeEntry nameAndType // @link substring="nameAndType" target="#nameAndType()" + * ) + * } + * where the type in the {@code NameAndTypeEntry} is a {@linkplain #typeSymbol() + * method descriptor} string. * + * @see ConstantPoolBuilder#methodRefEntry ConstantPoolBuilder::methodRefEntry + * @jvms 4.4.2 The {@code CONSTANT_Fieldref_info}, {@code + * CONSTANT_Methodref_info}, and {@code + * CONSTANT_InterfaceMethodref_info} Structures * @since 24 */ public sealed interface MethodRefEntry extends MemberRefEntry permits AbstractPoolEntry.MethodRefEntryImpl { /** - * {@return a symbolic descriptor for the method's type} + * {@return a symbolic descriptor for the {@linkplain #type() method type}} */ default MethodTypeDesc typeSymbol() { return Util.methodTypeSymbol(type()); diff --git a/src/java.base/share/classes/java/lang/classfile/constantpool/MethodTypeEntry.java b/src/java.base/share/classes/java/lang/classfile/constantpool/MethodTypeEntry.java index b6fad856358..5da36502678 100644 --- a/src/java.base/share/classes/java/lang/classfile/constantpool/MethodTypeEntry.java +++ b/src/java.base/share/classes/java/lang/classfile/constantpool/MethodTypeEntry.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2022, 2025, 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 @@ -30,28 +30,46 @@ import jdk.internal.classfile.impl.AbstractPoolEntry; /** - * Models a {@code CONSTANT_MethodType_info} constant in the constant pool of a - * classfile. - * @jvms 4.4.9 The CONSTANT_MethodType_info Structure + * Models a {@code CONSTANT_MethodType_info} structure, or a symbolic reference + * to a method type, in the constant pool of a {@code class} file. + *

+ * The use of a {@code MethodTypeEntry} is modeled by a {@link MethodTypeDesc}. + * Conversions are through {@link ConstantPoolBuilder#methodTypeEntry(MethodTypeDesc)} + * and {@link #asSymbol()}. + *

+ * A method type entry is composite: + * {@snippet lang=text : + * // @link substring="MethodTypeEntry" target="ConstantPoolBuilder#methodTypeEntry(Utf8Entry)" : + * MethodTypeEntry(Utf8Entry descriptor) // @link substring="descriptor" target="#descriptor()" + * } + * where {@code descriptor} is a {@linkplain #asSymbol() method descriptor} + * string. * + * @jvms 4.4.9 The {@code CONSTANT_MethodType_info} Structure * @since 24 */ public sealed interface MethodTypeEntry extends LoadableConstantEntry permits AbstractPoolEntry.MethodTypeEntryImpl { + /** + * {@inheritDoc} + *

+ * This is equivalent to {@link #asSymbol() asSymbol()}. + */ @Override default ConstantDesc constantValue() { return asSymbol(); } /** - * {@return the constant pool entry describing the method type} + * {@return the {@linkplain #asSymbol() method descriptor} string} */ Utf8Entry descriptor(); /** - * {@return a symbolic descriptor for the method type} + * {@return a symbolic descriptor for the {@linkplain #descriptor() method + * type}} */ MethodTypeDesc asSymbol(); } diff --git a/src/java.base/share/classes/java/lang/classfile/constantpool/ModuleEntry.java b/src/java.base/share/classes/java/lang/classfile/constantpool/ModuleEntry.java index d0cdae5678f..fd920aa1231 100644 --- a/src/java.base/share/classes/java/lang/classfile/constantpool/ModuleEntry.java +++ b/src/java.base/share/classes/java/lang/classfile/constantpool/ModuleEntry.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2022, 2025, 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 @@ -29,21 +29,32 @@ import jdk.internal.classfile.impl.AbstractPoolEntry; /** - * Models a {@code CONSTANT_Module_info} constant in the constant pool of a - * classfile. - * @jvms 4.4.11 The CONSTANT_Module_info Structure + * Models a {@code CONSTANT_Module_info} structure, denoting a module, in the + * constant pool of a {@code class} file. + *

+ * The use of a {@code ModuleEntry} is modeled by a {@link ModuleDesc}. + * Conversions are through {@link ConstantPoolBuilder#moduleEntry(ModuleDesc)} + * and {@link #asSymbol()}. + *

+ * A module entry is composite: + * {@snippet lang=text : + * // @link substring="ModuleEntry" target="ConstantPoolBuilder#moduleEntry(Utf8Entry)" : + * ModuleEntry(Utf8Entry name) // @link substring="name" target="#name()" + * } + * where {@code name} is a {@linkplain #asSymbol() module name}. * + * @jvms 4.4.11 The {@code CONSTANT_Module_info} Structure * @since 24 */ public sealed interface ModuleEntry extends PoolEntry permits AbstractPoolEntry.ModuleEntryImpl { /** - * {@return the name of the module} + * {@return the name of the {@linkplain #asSymbol() module}} */ Utf8Entry name(); /** - * {@return a symbolic descriptor for the module} + * {@return a symbolic descriptor for the {@linkplain #name() module name}} */ ModuleDesc asSymbol(); } diff --git a/src/java.base/share/classes/java/lang/classfile/constantpool/NameAndTypeEntry.java b/src/java.base/share/classes/java/lang/classfile/constantpool/NameAndTypeEntry.java index eff7e3456d1..38a23b0940e 100644 --- a/src/java.base/share/classes/java/lang/classfile/constantpool/NameAndTypeEntry.java +++ b/src/java.base/share/classes/java/lang/classfile/constantpool/NameAndTypeEntry.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2022, 2025, 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,36 @@ */ package java.lang.classfile.constantpool; +import java.lang.constant.ClassDesc; +import java.lang.constant.MethodTypeDesc; +import java.lang.invoke.TypeDescriptor; + import jdk.internal.classfile.impl.AbstractPoolEntry; /** - * Models a {@code CONSTANT_NameAndType_info} constant in the constant pool of a - * classfile. - * @jvms 4.4.6 The CONSTANT_NameAndType_info Structure + * Models a {@code CONSTANT_NameAndType_info} structure, representing a field or + * method, in the constant pool of a {@code class} file. + *

+ * The use of a {@code NameAndTypeEntry} is symbolically represented as a + * {@code String name}, and a {@link ConstantPoolBuilder#nameAndTypeEntry(String, + * ClassDesc) ClassDesc} or a {@link ConstantPoolBuilder#nameAndTypeEntry(String, + * MethodTypeDesc) MethodTypeDesc} {@code type}, depending on where this {@code + * NameAndTypeEntry} appears. The accessors to the symbolic descriptors for the + * {@code type} is defined on a per-use-site basis, such as {@link + * FieldRefEntry#typeSymbol()} returning a {@code ClassDesc}, and {@link + * MethodRefEntry#typeSymbol()} returning a {@code MethodTypeDesc}. + *

+ * A name and type entry is composite: + * {@snippet lang=text : + * NameAndTypeEntry( // @link substring="NameAndTypeEntry" target="ConstantPoolBuilder#nameAndTypeEntry(Utf8Entry, Utf8Entry)" + * Utf8Entry name, // @link substring="name" target="#name()" + * Utf8Entry type // @link substring="type" target="#type()" + * ) + * } + * where {@code name} is an unqualified name, and {@code type} is a field or + * method descriptor string. * + * @jvms 4.4.6 The {@code CONSTANT_NameAndType_info} Structure * @since 24 */ public sealed interface NameAndTypeEntry extends PoolEntry @@ -42,7 +65,10 @@ public sealed interface NameAndTypeEntry extends PoolEntry Utf8Entry name(); /** - * {@return the field or method descriptor} + * {@return the field or method {@linkplain TypeDescriptor descriptor} + * string} It is a method descriptor strings if it starts with {@code (}. + * Otherwise, it is a field descriptor string, and must start with one of + * the {@code BCDFIJSZL[} characters. */ Utf8Entry type(); } diff --git a/src/java.base/share/classes/java/lang/classfile/constantpool/PackageEntry.java b/src/java.base/share/classes/java/lang/classfile/constantpool/PackageEntry.java index 54ea2fc38e5..ec56d0a4870 100644 --- a/src/java.base/share/classes/java/lang/classfile/constantpool/PackageEntry.java +++ b/src/java.base/share/classes/java/lang/classfile/constantpool/PackageEntry.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2022, 2025, 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 @@ -29,21 +29,35 @@ import jdk.internal.classfile.impl.AbstractPoolEntry; /** - * Models a {@code CONSTANT_Package_info} constant in the constant pool of a - * classfile. - * @jvms 4.4.12 The CONSTANT_Package_info Structure + * Models a {@code CONSTANT_Package_info}, representing a package, in the + * constant pool of a {@code class} file. + *

+ * The use of a {@code PackageEntry} is represented by a {@link PackageDesc} + * that does not represent the unnamed package. Conversions are through + * {@link ConstantPoolBuilder#packageEntry(PackageDesc)} and + * {@link #asSymbol()}. + *

+ * A package entry is composite: + * {@snippet lang=text : + * // @link substring="PackageEntry" target="ConstantPoolBuilder#packageEntry(Utf8Entry)" : + * PackageEntry(Utf8Entry name) // @link substring="name" target="#name()" + * } + * where {@code name} is the {@linkplain ClassEntry##internalname internal form} + * of a binary package name and is not empty. * + * @jvms 4.4.12 The {@code CONSTANT_Package_info} Structure * @since 24 */ public sealed interface PackageEntry extends PoolEntry permits AbstractPoolEntry.PackageEntryImpl { /** - * {@return the package name} + * {@return the {@linkplain ClassEntry##internalname internal form} of the + * {@linkplain #asSymbol() package} name} */ Utf8Entry name(); /** - * {@return a symbolic descriptor for the package name} + * {@return a symbolic descriptor for the {@linkplain #name() package name}} */ PackageDesc asSymbol(); } diff --git a/src/java.base/share/classes/java/lang/classfile/constantpool/PoolEntry.java b/src/java.base/share/classes/java/lang/classfile/constantpool/PoolEntry.java index 5762a92a061..5d27e54e679 100644 --- a/src/java.base/share/classes/java/lang/classfile/constantpool/PoolEntry.java +++ b/src/java.base/share/classes/java/lang/classfile/constantpool/PoolEntry.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2022, 2025, 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,9 +24,28 @@ */ package java.lang.classfile.constantpool; +import java.lang.classfile.Attribute; +import java.lang.classfile.ClassFileBuilder; +import java.lang.classfile.Opcode; +import java.lang.classfile.TypeKind; + /** - * Models an entry in the constant pool of a classfile. + * Models an entry in the constant pool of a {@code class} file. Entries are + * read from {@code class} files, and can be created with a {@link + * ConstantPoolBuilder} to write to {@code class} files. + * + * @implNote + *

Unbound Constant Pool Entries

+ * Implementations may create unbound constant pool entries not belonging to + * an actual constant pool. They conveniently represent constant pool entries + * referred by unbound {@linkplain Attribute attributes} not read from a {@code + * class} file. Their {@link #index() index()} return a non-positive invalid + * value, and behaviors of their {@link #constantPool() constantPool()} are + * unspecified. They are considered alien to any {@linkplain + * ClassFileBuilder#constantPool() contextual constant pool} and will be + * converted when they are written to {@code class} files. * + * @see ConstantPoolBuilder##alien Alien Constant Pool Entries * @sealedGraph * @since 24 */ @@ -88,6 +107,14 @@ public sealed interface PoolEntry /** * {@return the constant pool this entry is from} + * + * @apiNote + * Given a {@link ConstantPoolBuilder} {@code builder} and a {@code + * PoolEntry entry}, use {@link ConstantPoolBuilder#canWriteDirect + * builder.canWriteDirect(entry.constantPool())} instead of object equality + * of the constant pool to determine if an entry belongs to the builder. + * + * @see ##unbound Unbound Constant Pool Entries */ ConstantPool constantPool(); @@ -102,11 +129,32 @@ public sealed interface PoolEntry /** * {@return the index within the constant pool corresponding to this entry} + * A valid index is always positive; if the index is non-positive, this + * entry is {@linkplain ##unbound unbound}. + * + * @see ##unbound Unbound Constant Pool Entries */ int index(); /** * {@return the number of constant pool slots this entry consumes} + *

+ * All pool entries except {@link LongEntry CONSTANT_Long} and {@link + * DoubleEntry CONSTANT_Double} have width {@code 1}. These two exceptions + * have width {@code 2}, and their subsequent indices at {@link #index() + * index() + 1} are considered unusable. + * + * @apiNote + * If this entry is {@linkplain LoadableConstantEntry loadable}, the width + * of this entry does not decide if this entry should be loaded with {@link + * Opcode#LDC ldc} or {@link Opcode#LDC2_W ldc2_w}. For example, {@link + * ConstantDynamicEntry} always has width {@code 1}, but it must be loaded + * with {@code ldc2_w} if its {@linkplain ConstantDynamicEntry#typeKind() + * type} is {@link TypeKind#LONG long} or {@link TypeKind#DOUBLE double}. + * Use {@link LoadableConstantEntry#typeKind() typeKind().slotSize()} to + * determine the loading instruction instead. + * + * @see ConstantPool##index Index in the Constant Pool */ int width(); } diff --git a/src/java.base/share/classes/java/lang/classfile/constantpool/StringEntry.java b/src/java.base/share/classes/java/lang/classfile/constantpool/StringEntry.java index 03ff7652f67..8a0bbb4b015 100644 --- a/src/java.base/share/classes/java/lang/classfile/constantpool/StringEntry.java +++ b/src/java.base/share/classes/java/lang/classfile/constantpool/StringEntry.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2022, 2025, 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 @@ -27,10 +27,20 @@ import jdk.internal.classfile.impl.AbstractPoolEntry; /** - * Models a {@code CONSTANT_String_info} constant in the constant pool of a - * classfile. - * @jvms 4.4.3 The CONSTANT_String_info Structure + * Models a {@code CONSTANT_String_info} structure, or a string constant, in the + * constant pool of a {@code class} file. + *

+ * The use of a {@code StringEntry} is represented by a {@link String}. + * Conversions are through {@link ConstantPoolBuilder#stringEntry(String)} and + * {@link #stringValue()}. + *

+ * A string entry is composite: + * {@snippet lang=text : + * // @link substring="StringEntry" target="ConstantPoolBuilder#stringEntry(Utf8Entry)" : + * StringEntry(Utf8Entry utf8) // @link substring="utf8" target="#utf8()" + * } * + * @jvms 4.4.3 The {@code CONSTANT_String_info} Structure * @since 24 */ public sealed interface StringEntry @@ -38,11 +48,15 @@ public sealed interface StringEntry permits AbstractPoolEntry.StringEntryImpl { /** * {@return the UTF constant pool entry describing the string contents} + * + * @see ConstantPoolBuilder#stringEntry(Utf8Entry) */ Utf8Entry utf8(); /** * {@return the string value for this entry} + * + * @see ConstantPoolBuilder#stringEntry(String) */ String stringValue(); } diff --git a/src/java.base/share/classes/java/lang/classfile/constantpool/Utf8Entry.java b/src/java.base/share/classes/java/lang/classfile/constantpool/Utf8Entry.java index db03bf6a403..1d885051b2b 100644 --- a/src/java.base/share/classes/java/lang/classfile/constantpool/Utf8Entry.java +++ b/src/java.base/share/classes/java/lang/classfile/constantpool/Utf8Entry.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2022, 2025, 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,40 @@ */ package java.lang.classfile.constantpool; +import java.io.DataInput; +import java.lang.classfile.AnnotationValue; +import java.lang.classfile.MethodModel; +import java.lang.constant.ClassDesc; +import java.lang.constant.MethodTypeDesc; +import java.lang.invoke.TypeDescriptor; + import jdk.internal.classfile.impl.AbstractPoolEntry; /** - * Models a {@code CONSTANT_UTF8_info} constant in the constant pool of a - * classfile. - * @jvms 4.4.7 The CONSTANT_Utf8_info Structure + * Models a {@code CONSTANT_UTF8_info} constant, representing strings, in the + * constant pool of a {@code class} file. This describes strings in the + * {@linkplain DataInput##modified-utf-8 Modified UTF-8} format. + *

+ * The use of a {@code Utf8Entry} is represented by a {@link String}. + * Conversions are through {@link ConstantPoolBuilder#utf8Entry(String)} and + * {@link #stringValue()}. + *

+ * Some uses of {@code Utf8Entry} represent field or method {@linkplain + * TypeDescriptor#descriptorString() descriptor strings}, symbolically + * represented as {@link ClassDesc} or {@link MethodTypeDesc}, depending on + * where a {@code Utf8Entry} appear. Entries representing such uses are created + * with {@link ConstantPoolBuilder#utf8Entry(ClassDesc)} and {@link + * ConstantPoolBuilder#utf8Entry(MethodTypeDesc)}, and they can be converted to + * symbolic descriptors on a per-use-site basis, such as in {@link + * AnnotationValue.OfClass#classSymbol()} and {@link MethodModel#methodTypeSymbol()}. + *

+ * Unlike most constant pool entries, a UTF-8 entry is of flexible length: it is + * represented as an array structure, with an {@code u2} for the data length in + * bytes, followed by that number of bytes of Modified UTF-8 data. It can + * represent at most 65535 bytes of data due to the physical restrictions. * + * @jvms 4.4.7 The {@code CONSTANT_Utf8_info} Structure + * @see DataInput##modified-utf-8 Modified UTF-8 * @since 24 */ public sealed interface Utf8Entry @@ -39,6 +66,15 @@ public sealed interface Utf8Entry /** * {@return the string value for this entry} + * + * @apiNote + * A {@code Utf8Entry} can be used directly as a {@link CharSequence} if + * {@code String} functionalities are not strictly desired. If only string + * equivalence is desired, {@link #equalsString(String) equalsString} should + * be used. Reduction of string processing can significantly improve {@code + * class} file reading performance. + * + * @see ConstantPoolBuilder#utf8Entry(String) */ String stringValue(); diff --git a/src/java.base/share/classes/java/lang/classfile/constantpool/package-info.java b/src/java.base/share/classes/java/lang/classfile/constantpool/package-info.java index 83039c6565c..66e72496d3a 100644 --- a/src/java.base/share/classes/java/lang/classfile/constantpool/package-info.java +++ b/src/java.base/share/classes/java/lang/classfile/constantpool/package-info.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2023, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2023, 2025, 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,11 +24,59 @@ */ /** - *

Provides interfaces describing classfile constant pool entries for the {@link java.lang.classfile} library.

+ *

Provides interfaces describing constant pool entries for the {@link java.lang.classfile} library.

* - * The {@code java.lang.classfile.constantpool} package contains interfaces describing classfile constant pool entries. + * The {@code java.lang.classfile.constantpool} package contains interfaces describing constant pool entries in the + * {@code class} file format. Constant pool entries are low-level models to faithfully represent the exact structure + * of a {@code class} file. + *

+ * Unless otherwise specified, passing {@code null} or an array or collection containing a {@code null} element as an + * argument to a constructor or method of any Class-File API class or interface will cause a {@link NullPointerException} + * to be thrown. * + *

Reading the constant pool entries

+ * When read from {@code class} files, the pool entries are lazily inflated; the contents of these entries, besides the + * bare structure, are not evaluated to speed up parsing. Entries to users interest, usually accessed from other models + * and elements, have their contents read on demand. For example, to search for methods, a user should filter first by + * access flags and then by method name, and use {@link Utf8Entry#equalsString(String)} instead of checking equality + * against {@link Utf8Entry#stringValue()}. This avoids inflation of UTF-8 entries as much as possible: + * {@snippet lang="java" class="PackageSnippets" region="isStaticWorkMethod"} + *

+ * The entries also define accessors to validated symbolic information with nominal descriptor abstractions from the + * {@link java.lang.constant} package. These symbolic information accessors perform validation against the read + * {@code class} files, and throw {@link IllegalArgumentException} when the accessed constant pool entry contains + * invalid data. The nominal descriptors represent validated data, which saves users from extra validations in future + * processing. + *

+ * Due to the lazy nature of {@code class} file parsing, {@link IllegalArgumentException} indicating malformed + * {@code class} file data can be thrown at any method invocation. For example, an exception may come from a {@link + * ClassEntry} when it is first read from the constant pool (referring to an invalid index or wrong type of entry), when + * its referred UTF-8 entry is expanded (malformed UTF-8 data), or when its symbolic information is accessed (the string + * is not valid for a class entry). + * + *

Writing the constant pool entries

+ * In general, users do not need to worry about working with the constant pool and its entries when writing {@code + * class} files. Most Class-File API models and elements have two sets of factory methods: one that accepts symbolic + * information representing the uses, and another that accepts constant pool entries. The constant pool builder + * associated with {@code class} file builders, {@link ClassFileBuilder#constantPool}, automatically creates or reuses + * pool entries from the symbolic information. Validated data in symbolic information helps {@code class} file + * generation by avoiding extraneous parsing of raw constant pool entry data. + *

+ * As always, users can use factories that accept constant pool entries if they already have them by hand, or if they + * desire fine-grained control over {@code class} file generation. + *

+ * If many models and elements are reused from another {@link ClassModel} in class building, the class building process + * can use a constant pool builder that extends from the given {@code ClassModel}, available through {@link + * ConstantPoolBuilder#of(ClassModel) ConstantPoolBuilder::of(ClassModel)}, so that byte data with constant pool + * references can be copied in batch, speeding up class building. This is especially applicable to class transformations, + * and {@link ClassFile.ConstantPoolSharingOption ConstantPoolSharingOption} exists to control this behavior. + * + * @jvms 4.4 The Constant Pool * @since 24 */ package java.lang.classfile.constantpool; +import java.lang.classfile.ClassFile; +import java.lang.classfile.ClassFileBuilder; +import java.lang.classfile.ClassModel; +import java.lang.classfile.MethodModel; diff --git a/src/java.base/share/classes/java/lang/classfile/constantpool/snippet-files/PackageSnippets.java b/src/java.base/share/classes/java/lang/classfile/constantpool/snippet-files/PackageSnippets.java new file mode 100644 index 00000000000..983aa1adb4c --- /dev/null +++ b/src/java.base/share/classes/java/lang/classfile/constantpool/snippet-files/PackageSnippets.java @@ -0,0 +1,43 @@ +/* + * Copyright (c) 2025, 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.classfile.constantpool.snippet; + +import java.lang.classfile.ClassFile; +import java.lang.classfile.MethodModel; +import java.lang.classfile.constantpool.Utf8Entry; + +class PackageSnippets { + + // @start region=isStaticWorkMethod + boolean isStaticWorkMethod(MethodModel method) { + // check static flag first to avoid unnecessary evaluation of UTF-8 entry + return (method.flags().flagsMask() & ClassFile.ACC_STATIC) != 0 + // use equalsString to avoid full conversion to String for comparison + // the Utf8Entry can also act as a basic CharSequence without full conversion + // @link substring="methodName" target="MethodModel#methodName" : + && method.methodName().equalsString("work"); // @link substring="equalsString" target="Utf8Entry#equalsString" + } + // @end +} diff --git a/test/jdk/jdk/classfile/SnippetsTest.java b/test/jdk/jdk/classfile/SnippetsTest.java index f6fa2281e14..2b84820e9b9 100644 --- a/test/jdk/jdk/classfile/SnippetsTest.java +++ b/test/jdk/jdk/classfile/SnippetsTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2023, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2023, 2025, 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 @@ -42,7 +42,9 @@ public class SnippetsTest { @ParameterizedTest @ValueSource(strings = { "src/java.base/share/classes/java/lang/classfile/snippet-files/PackageSnippets.java", - "src/java.base/share/classes/jdk/internal/classfile/components/snippet-files/PackageSnippets.java"}) + "src/java.base/share/classes/java/lang/classfile/constantpool/snippet-files/PackageSnippets.java", + "src/java.base/share/classes/jdk/internal/classfile/components/snippet-files/PackageSnippets.java" + }) void testSnippet(String source) throws Exception { var p = Paths.get(System.getProperty("test.src", ".")).toAbsolutePath(); while ((p = p.getParent()) != null) {