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 964976e0fd5ad..0c4f99de29a9c 100644 --- a/src/java.base/share/classes/java/lang/classfile/BootstrapMethodEntry.java +++ b/src/java.base/share/classes/java/lang/classfile/BootstrapMethodEntry.java @@ -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; @@ -35,10 +37,27 @@ /** * 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. + *
+ * Conceptually, a bootstrap method entry is a record:
+ * {@snippet lang=text :
+ * // @link region=1 substring="BootstrapMethodEntry" target="ConstantPoolBuilder#bsmEntry(DirectMethodHandleDesc, List)"
+ * // @link substring="DirectMethodHandleDesc" target="#bootstrapMethod" :
+ * BootstrapMethodEntry(DirectMethodHandleDesc, List
+ * Physically, a bootstrap method entry is a record:
+ * {@snippet lang=text :
+ * // @link region=1 substring="BootstrapMethodEntry" target="ConstantPoolBuilder#bsmEntry(MethodHandleEntry, List)"
+ * // @link substring="MethodHandleEntry" target="#bootstrapMethod" :
+ * BootstrapMethodEntry(MethodHandleEntry, List
+ * Conceptually, a class entry is a record:
+ * {@snippet lang=text :
+ * // @link substring="ClassEntry" target="ConstantPoolBuilder#classEntry(ClassDesc)" :
+ * ClassEntry(ClassDesc) // @link substring="ClassDesc" target="#asSymbol()"
+ * }
+ * where the {@code ClassDesc} must not be primitive.
+ *
+ * Physically, a class entry is a record:
+ * {@snippet lang=text :
+ * // @link substring="ClassEntry" target="ConstantPoolBuilder#classEntry(Utf8Entry)" :
+ * ClassEntry(Utf8Entry) // @link substring="Utf8Entry" target="Utf8Entry"
+ * }
+ * where the {@code Utf8Entry} is a valid internal form of binary name or array
+ * type descriptor string.
*
+ * @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 22
*/
@PreviewFeature(feature = PreviewFeature.Feature.CLASSFILE_API)
@@ -42,23 +67,43 @@ 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 class entry} 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 ##internal-name 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
+ * ##internal-name internal form} of a binary name or an array descriptor
+ * string} The return value is equivalent to {@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 7c55a09f3f4c8..3745ce6680926 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, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2022, 2024, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -34,10 +34,37 @@
import jdk.internal.javac.PreviewFeature;
/**
- * 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.
+ *
+ * Conceptually, a constant dynamic entry is a record:
+ * {@snippet lang=text :
+ * // @link substring="ConstantDynamicEntry" target="ConstantPoolBuilder#constantDynamicEntry(DynamicConstantDesc)" :
+ * ConstantDynamicEntry(DynamicConstantDesc) // @link substring="DynamicConstantDesc" target="#asSymbol()"
+ * }
+ *
+ * Physically, a constant dynamic entry is a record:
+ * {@snippet lang=text :
+ * // @link region substring="ConstantDynamicEntry" target="ConstantPoolBuilder#constantDynamicEntry(BootstrapMethodEntry, NameAndTypeEntry)"
+ * // @link substring="BootstrapMethodEntry" target="#bootstrap()"
+ * ConstantDynamicEntry(BootstrapMethodEntry, NameAndTypeEntry) // @link substring="NameAndTypeEntry" target="#nameAndType()"
+ * // @end
+ * }
+ * where the type in the {@code NameAndTypeEntry} 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 22
*/
@PreviewFeature(feature = PreviewFeature.Feature.CLASSFILE_API)
@@ -46,19 +73,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(),
@@ -70,10 +106,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 0225f6ec77d8c..a350c660fd1b6 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
@@ -27,16 +27,24 @@
import java.lang.classfile.BootstrapMethodEntry;
import java.lang.classfile.ClassReader;
+import java.lang.classfile.attribute.BootstrapMethodsAttribute;
import java.util.Iterator;
import java.util.NoSuchElementException;
import jdk.internal.javac.PreviewFeature;
/**
- * 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.
+ *
+ *
+ * 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.
+ *
+ * Some non-constant-pool builder methods may have their outputs adjusted if
+ * they receive non-directly-writable pool entries. For example, if an {@link
+ * ConstantInstruction#ofLoad ldc_w} instruction with a non-directly-writable
+ * 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.
*
+ * @see ClassFileBuilder#constantPool() ClassFileBuilder::constantPool
* @since 22
*/
@PreviewFeature(feature = PreviewFeature.Feature.CLASSFILE_API)
@@ -57,10 +86,16 @@ 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)
+ * ClassFile::build(ClassEntry, ConstantPoolBuilder, Consumer)
+ * @see ClassFile.ConstantPoolSharingOption#SHARED_POOL
+ * ConstantPoolSharingOption.SHARED_POOL
*/
static ConstantPoolBuilder of(ClassModel classModel) {
return new SplitConstantPool((ClassReaderImpl) classModel.constantPool());
@@ -68,35 +103,42 @@ 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
+ * 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.
*
- * @param constantPool the other constant pool
+ * @param constantPool the given constant pool
+ * @see ##adoption Non-directly-writable 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}.
*
* @param desc the symbolic descriptor for the class
*/
@@ -105,10 +147,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
*/
@@ -117,25 +158,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()) {
@@ -147,196 +187,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());
@@ -349,125 +384,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);
@@ -479,13 +522,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);
@@ -502,10 +542,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
+ * Conceptually, a double entry is a record:
+ * {@snippet lang=text :
+ * // @link substring="DoubleEntry" target="ConstantPoolBuilder#doubleEntry(double)" :
+ * DoubleEntry(double) // @link substring="double" target="#doubleValue()"
+ * }
+ * where all NaN values of the {@code double} may be collapsed into a single
+ * "canonical" NaN value.
+ *
+ * Physically, a double entry stores an arbitrary 8-byte value.
+ *
+ * This constant 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 22
*/
@PreviewFeature(feature = PreviewFeature.Feature.CLASSFILE_API)
@@ -42,13 +57,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 ac7630494100c..1aaf2afd68284 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, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2022, 2024, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -29,10 +29,26 @@
import jdk.internal.javac.PreviewFeature;
/**
- * 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.
+ *
+ * Conceptually, dynamically-computed constant pool entries are not treated as
+ * a single type. The subtypes appear in distinct locations and serve distinct
+ * purposes. They resemble each other structurally and share parts of their
+ * resolution processes.
+ *
+ * Physically, a dynamically-computed constant pool entry is a record:
+ * {@snippet lang=text :
+ * // @link substring="BootstrapMethodEntry" target="#bootstrap()" :
+ * DynamicConstantPoolEntry(BootstrapMethodEntry, NameAndTypeEntry) // @link substring="NameAndTypeEntry" 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 22
*/
@@ -42,28 +58,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 ab122f410b699..0d94331127044 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, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2022, 2024, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -31,10 +31,34 @@
import jdk.internal.javac.PreviewFeature;
/**
- * 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.
+ *
+ * Conceptually, a field reference entry is a record:
+ * {@snippet lang=text :
+ * // @link region=1 substring="FieldRefEntry" target="ConstantPoolBuilder#fieldRefEntry(ClassDesc, String, ClassDesc)"
+ * // @link region=2 substring="ClassDesc owner" target="#owner()"
+ * // @link substring="String name" target="#name()" :
+ * FieldRefEntry(ClassDesc owner, String name, ClassDesc type) // @link substring="ClassDesc type" target="#typeSymbol()"
+ * // @end region=1
+ * // @end region=2
+ * }
+ * where the {@code ClassDesc owner} represents a class or interface.
+ *
+ * Physically, a field reference entry is a record:
+ * {@snippet lang=text :
+ * // @link region=1 substring="FieldRefEntry" target="ConstantPoolBuilder#fieldRefEntry(ClassEntry, NameAndTypeEntry)"
+ * // @link substring="ClassEntry owner" target="#owner()" :
+ * FieldRefEntry(ClassEntry owner, NameAndTypeEntry) // @link substring="NameAndTypeEntry" target="#nameAndType()"
+ * // @end region=1
+ * }
+ * where the type in the {@code NameAndTypeEntry} is 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 22
*/
@PreviewFeature(feature = PreviewFeature.Feature.CLASSFILE_API)
@@ -42,7 +66,7 @@ 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 7a91dd111530f..c21655ca1c853 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
@@ -30,10 +30,22 @@
import jdk.internal.javac.PreviewFeature;
/**
- * 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.
+ *
+ * Conceptually, a float entry is a record:
+ * {@snippet lang=text :
+ * // @link substring="FloatEntry" target="ConstantPoolBuilder#floatEntry(float)" :
+ * FloatEntry(float) // @link substring="float" target="#floatValue()"
+ * }
+ * where all NaN values of the {@code float} may be collapsed into a single
+ * "canonical" NaN value.
+ *
+ * Physically, a float entry stores an arbitrary 4-byte value.
*
+ * @see ConstantPoolBuilder#floatEntry ConstantPoolBuilder::floatEntry
+ * @jvms 4.4.4 The {@code CONSTANT_Integer_info} and {@code CONSTANT_Float_info}
+ * Structures
* @since 22
*/
@PreviewFeature(feature = PreviewFeature.Feature.CLASSFILE_API)
@@ -42,14 +54,13 @@ public sealed interface FloatEntry
permits AbstractPoolEntry.FloatEntryImpl {
/**
- * {@return the float value}
+ * {@return the {@code float} value}
+ *
+ * @see ConstantPoolBuilder#floatEntry(float)
+ * 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 7cd21e37db824..b67e9aa550204 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
@@ -30,10 +30,20 @@
import jdk.internal.javac.PreviewFeature;
/**
- * 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.
+ *
+ * Conceptually, an integer entry is a record:
+ * {@snippet lang=text :
+ * // @link substring="IntegerEntry" target="ConstantPoolBuilder#intEntry(int)" :
+ * IntegerEntry(int) // @link substring="int" target="#intValue()"
+ * }
+ *
+ * Physically, an integer entry stores an arbitrary 4-byte value.
*
+ * @see ConstantPoolBuilder#intEntry ConstantPoolBuilder::intEntry
+ * @jvms 4.4.4 The {@code CONSTANT_Integer_info} and {@code CONSTANT_Float_info}
+ * Structures
* @since 22
*/
@PreviewFeature(feature = PreviewFeature.Feature.CLASSFILE_API)
@@ -42,13 +52,12 @@ public sealed interface IntegerEntry
permits AbstractPoolEntry.IntegerEntryImpl {
/**
- * {@return the integer value}
+ * {@return the {@code int} value}
+ *
+ * @see ConstantPoolBuilder#intEntry(int) 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 8f15053e5b705..49f74be525127 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, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2022, 2024, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -31,10 +31,36 @@
import jdk.internal.javac.PreviewFeature;
/**
- * 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.
+ *
+ * Conceptually, an interface method reference entry is a record:
+ * {@snippet lang=text :
+ * // @link region=1 substring="InterfaceMethodRefEntry" target="ConstantPoolBuilder#interfaceMethodRefEntry(ClassDesc, String, MethodTypeDesc)"
+ * // @link region=2 substring="ClassDesc owner" target="#owner()"
+ * // @link substring="String name" target="#name()" :
+ * InterfaceMethodRefEntry(ClassDesc owner, String name, MethodTypeDesc type) // @link substring="MethodTypeDesc type" target="#typeSymbol()"
+ * // @end region=1
+ * // @end region=2
+ * }
+ * where the {@code ClassDesc owner} represents an interface.
+ *
+ * Physically, an interface method reference entry is a record:
+ * {@snippet lang=text :
+ * // @link region=1 substring="InterfaceMethodRefEntry" target="ConstantPoolBuilder#interfaceMethodRefEntry(ClassEntry, NameAndTypeEntry)"
+ * // @link substring="ClassEntry owner" target="#owner()" :
+ * InterfaceMethodRefEntry(ClassEntry owner, NameAndTypeEntry) // @link substring="NameAndTypeEntry" target="#nameAndType()"
+ * // @end region=1
+ * }
+ * where the type in the {@code NameAndTypeEntry} 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 22
*/
@PreviewFeature(feature = PreviewFeature.Feature.CLASSFILE_API)
@@ -43,7 +69,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 f06c3d4c7828c..cdea5a4100729 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, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2022, 2024, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -33,9 +33,35 @@
import jdk.internal.javac.PreviewFeature;
/**
- * 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.
+ *
+ * Conceptually, an invoke dynamic entry is a record:
+ * {@snippet lang=text :
+ * // @link substring="InvokeDynamicEntry" target="ConstantPoolBuilder#constantDynamicEntry(DynamicConstantDesc)" :
+ * InvokeDynamicEntry(DynamicCallSiteDesc) // @link substring="DynamicCallSiteDesc" target="#asSymbol()"
+ * }
+ *
+ * Physically, an invoke dynamic entry is a record:
+ * {@snippet lang=text :
+ * // @link region substring="InvokeDynamicEntry" target="ConstantPoolBuilder#constantDynamicEntry(BootstrapMethodEntry, NameAndTypeEntry)"
+ * // @link substring="BootstrapMethodEntry" target="#bootstrap()"
+ * InvokeDynamicEntry(BootstrapMethodEntry, NameAndTypeEntry) // @link substring="NameAndTypeEntry" target="#nameAndType()"
+ * // @end
+ * }
+ * where the type in the {@code NameAndTypeEntry} 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
+ * @jvms 4.4.10 The {@code CONSTANT_Dynamic_info} and {@code
+ * CONSTANT_InvokeDynamic_info} Structures
* @since 22
*/
@PreviewFeature(feature = PreviewFeature.Feature.CLASSFILE_API)
@@ -44,14 +70,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 c963e2425eac4..50ede47676323 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
@@ -24,15 +24,23 @@
*/
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;
import jdk.internal.javac.PreviewFeature;
/**
* Marker interface for constant pool entries suitable for loading via the
- * {@code LDC} instructions.
+ * {@link ConstantInstruction.LoadConstantInstruction ldc} instructions.
*
+ * @see CodeBuilder#ldc(LoadableConstantEntry)
+ * CodeBuilder::ldc(LoadableConstantEntry)
+ * @see ConstantPoolBuilder#loadableConstantEntry
+ * ConstantPoolBuilder::loadableConstantEntry
+ * @jvms 4.4 The Constant Pool
* @sealedGraph
* @since 22
*/
@@ -41,14 +49,36 @@ 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)
+ * 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;
}
+
+ /**
+ * {@inheritDoc}
+ *
+ * @apiNote
+ * 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 #typeKind()
+ * type} is {@link TypeKind#LONG long} or {@link TypeKind#DOUBLE double}.
+ * Use {@link #typeKind() typeKind().slotSize()} for this purpose instead.
+ */
+ @Override
+ int width();
}
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 75e02b1944192..aec5ee7d60e1a 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
@@ -30,10 +30,23 @@
import jdk.internal.javac.PreviewFeature;
/**
- * 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.
+ *
+ * Conceptually, a long entry is a record:
+ * {@snippet lang=text :
+ * // @link substring="LongEntry" target="ConstantPoolBuilder#longEntry(long)" :
+ * LongEntry(long) // @link substring="long" target="#longValue()"
+ * }
+ *
+ * Physically, a long entry stores an arbitrary 8-byte value.
+ *
+ * This constant 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 22
*/
@PreviewFeature(feature = PreviewFeature.Feature.CLASSFILE_API)
@@ -42,7 +55,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 7c9292c8f0459..5d686f6041893 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, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2022, 2024, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -28,9 +28,24 @@
import jdk.internal.javac.PreviewFeature;
/**
- * 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}.
+ *
+ * Conceptually, member reference entries are not treated as a single type. The
+ * subtypes appear in distinct locations and serve distinct purposes. They
+ * resemble each other structurally and share parts of the resolution processes.
+ *
+ * Physically, a member reference entry is a record:
+ * {@snippet lang=text :
+ * // @link substring="ClassEntry owner" target="#owner()" :
+ * MemberRefEntry(ClassEntry owner, NameAndTypeEntry) // @link substring="NameAndTypeEntry" target="#nameAndType()"
+ * }
*
+ * @jvms 4.4.2 The {@code CONSTANT_Fieldref_info}, {@code
+ * CONSTANT_Methodref_info}, and {@code
+ * CONSTANT_InterfaceMethodref_info} Structures
* @sealedGraph
* @since 22
*/
@@ -38,24 +53,39 @@
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}
+ *
+ * @apiNote
+ * A symbolic descriptor for the owner is available through {@link
+ * ClassEntry#asSymbol() owner().asSymbol()}.
*/
ClassEntry owner();
/**
- * {@return the name and type of the member}
+ * {@return the name and descriptor string of the member}
*/
NameAndTypeEntry nameAndType();
/**
* {@return the name of the member}
+ *
+ * @apiNote
+ * A string value for the name is available through {@link
+ * Utf8Entry#stringValue() name().stringValue()}.
*/
default Utf8Entry name() {
return nameAndType().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 37ec30648ab6f..7897faeb24504 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
@@ -26,14 +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;
import jdk.internal.javac.PreviewFeature;
/**
- * 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.
+ *
+ * Conceptually, a method handle entry is a record:
+ * {@snippet lang=text :
+ * // @link substring="MethodHandleEntry" target="ConstantPoolBuilder#methodHandleEntry(DirectMethodHandleDesc)" :
+ * MethodHandleEntry(DirectMethodHandleDesc) // @link substring="DirectMethodHandleDesc" target="#typeSymbol()"
+ * }
+ *
+ * Physically, a method handle entry is a record:
+ * {@snippet lang=text :
+ * // @link region=1 substring="MethodHandleEntry" target="ConstantPoolBuilder#methodHandleEntry(int, MemberRefEntry)"
+ * // @link substring="int refKind" target="#kind()" :
+ * MethodHandleEntry(int refKind, MemberRefEntry) // @link substring="MemberRefEntry" target="#reference()"
+ * // @end region=1
+ * }
+ * where the {@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 22
*/
@@ -42,6 +63,11 @@ public sealed interface MethodHandleEntry
extends LoadableConstantEntry
permits AbstractPoolEntry.MethodHandleEntryImpl {
+ /**
+ * {@inheritDoc}
+ *
+ * This is equivalent to {@link #asSymbol() asSymbol()}.
+ */
@Override
default ConstantDesc constantValue() {
return asSymbol();
@@ -49,17 +75,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 ff3f5e5220ccd..61231bd9e5283 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, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2022, 2024, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -31,10 +31,34 @@
import jdk.internal.javac.PreviewFeature;
/**
- * 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.
+ *
+ * Conceptually, a class method reference entry is a record:
+ * {@snippet lang=text :
+ * // @link region=1 substring="MethodRefEntry" target="ConstantPoolBuilder#methodRefEntry(ClassDesc, String, MethodTypeDesc)"
+ * // @link region=2 substring="ClassDesc owner" target="#owner()"
+ * // @link substring="String name" target="#name()" :
+ * MethodRefEntry(ClassDesc owner, String name, MethodTypeDesc type) // @link substring="MethodTypeDesc type" target="#typeSymbol()"
+ * // @end region=1
+ * // @end region=2
+ * }
+ * where the {@code ClassDesc owner} represents a class.
+ *
+ * Physically, a class method reference entry is a record:
+ * {@snippet lang=text :
+ * // @link region=1 substring="MethodRefEntry" target="ConstantPoolBuilder#methodRefEntry(ClassEntry, NameAndTypeEntry)"
+ * // @link substring="ClassEntry owner" target="#owner()" :
+ * MethodRefEntry(ClassEntry owner, NameAndTypeEntry) // @link substring="NameAndTypeEntry" target="#nameAndType()"
+ * // @end region=1
+ * }
+ * 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 22
*/
@PreviewFeature(feature = PreviewFeature.Feature.CLASSFILE_API)
@@ -42,7 +66,7 @@ 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 d626aeb4900ba..a1c86b34c5a79 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, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2022, 2024, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -31,10 +31,24 @@
import jdk.internal.javac.PreviewFeature;
/**
- * 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.
+ *
+ * Conceptually, a method type entry is a record:
+ * {@snippet lang=text :
+ * // @link substring="MethodTypeEntry" target="ConstantPoolBuilder#methodTypeEntry(MethodTypeDesc)" :
+ * MethodTypeEntry(MethodTypeDesc) // @link substring="MethodTypeDesc" target="#asSymbol()"
+ * }
+ *
+ * Physically, a method type entry is a record:
+ * {@snippet lang=text :
+ * // @link substring="MethodTypeEntry" target="ConstantPoolBuilder#methodTypeEntry(Utf8Entry)" :
+ * MethodTypeEntry(Utf8Entry) // @link substring="Utf8Entry" target="#descriptor()"
+ * }
+ * where the {@code Utf8Entry} is a {@linkplain #asSymbol() method descriptor}
+ * string.
*
+ * @jvms 4.4.9 The {@code CONSTANT_MethodType_info} Structure
* @since 22
*/
@PreviewFeature(feature = PreviewFeature.Feature.CLASSFILE_API)
@@ -42,18 +56,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 db7aa1f76fe1a..5e5d53393c99d 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, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2022, 2024, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -30,22 +30,35 @@
import jdk.internal.javac.PreviewFeature;
/**
- * 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.
+ *
+ * Conceptually, a module entry is a record:
+ * {@snippet lang=text :
+ * // @link substring="ModuleEntry" target="ConstantPoolBuilder#moduleEntry(ModuleDesc)" :
+ * ModuleEntry(ModuleDesc) // @link substring="ModuleDesc" target="#asSymbol()"
+ * }
+ *
+ * Physically, a module entry is a record:
+ * {@snippet lang=text :
+ * // @link substring="ModuleEntry" target="ConstantPoolBuilder#moduleEntry(Utf8Entry)" :
+ * ModuleEntry(Utf8Entry) // @link substring="Utf8Entry" target="#name()"
+ * }
+ * where the {@code Utf8Entry} is a {@linkplain #asSymbol() module name}.
*
+ * @jvms 4.4.11 The {@code CONSTANT_Module_info} Structure
* @since 22
*/
@PreviewFeature(feature = PreviewFeature.Feature.CLASSFILE_API)
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 d4beff2aff77f..aaef3c1e88d20 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, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2022, 2024, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -24,14 +24,39 @@
*/
package java.lang.classfile.constantpool;
+import java.lang.invoke.TypeDescriptor;
+
import jdk.internal.classfile.impl.AbstractPoolEntry;
import jdk.internal.javac.PreviewFeature;
/**
- * 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.
+ *
+ * Conceptually, a name and type entry may be one of the following records:
+ * {@snippet lang=text :
+ * // @link region substring="NameAndTypeEntry" target="ConstantPoolBuilder#nameAndTypeEntry(String, ClassDesc)"
+ * // @link substring="String" target="#name()" :
+ * NameAndTypeEntry(String, ClassDesc) // @link substring="ClassDesc" target="#type()"
+ * // @end
+ * // @link region substring="NameAndTypeEntry" target="ConstantPoolBuilder#nameAndTypeEntry(String, MethodTypeDesc)"
+ * // @link substring="String" target="#name()" :
+ * NameAndTypeEntry(String, MethodTypeDesc) // @link substring="MethodTypeDesc" target="#type()"
+ * // @end
+ * }
+ * where {@code String} is an unqualified name.
+ *
+ * Physically, a name and type entry is a record:
+ * {@snippet lang=text :
+ * // @link region substring="NameAndTypeEntry" target="ConstantPoolBuilder#nameAndTypeEntry(Utf8Entry, Utf8Entry)"
+ * // @link substring="Utf8Entry name" target="#name()" :
+ * NameAndTypeEntry(Utf8Entry name, Utf8Entry type) // @link substring="Utf8Entry type" target="#type()"
+ * // @end
+ * }
+ * where {@code Utf8Entry name} is an unqualified name, and {@code Utf8Entry
+ * type} is a field or method descriptor string.
*
+ * @jvms 4.4.6 The {@code CONSTANT_NameAndType_info} Structure
* @since 22
*/
@PreviewFeature(feature = PreviewFeature.Feature.CLASSFILE_API)
@@ -40,11 +65,18 @@ public sealed interface NameAndTypeEntry extends PoolEntry
/**
* {@return the field or method name}
+ *
+ * @apiNote
+ * A string value for the name is available through {@link
+ * Utf8Entry#stringValue() name().stringValue()}.
*/
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 5725d411028c1..9d9981734bf1d 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, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2022, 2024, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -30,22 +30,38 @@
import jdk.internal.javac.PreviewFeature;
/**
- * 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.
+ *
+ * Conceptually, a package entry is a record:
+ * {@snippet lang=text :
+ * // @link substring="PackageEntry" target="ConstantPoolBuilder#packageEntry(PackageDesc)" :
+ * PackageEntry(PackageDesc) // @link substring="PackageDesc" target="#asSymbol()"
+ * }
+ * where the {@code PackageDesc} must not be the unnamed package.
+ *
+ * Physically, a package entry is a record:
+ * {@snippet lang=text :
+ * // @link substring="PackageEntry" target="ConstantPoolBuilder#packageEntry(Utf8Entry)" :
+ * PackageEntry(Utf8Entry) // @link substring="Utf8Entry" target="#name()"
+ * }
+ * where the {@code Utf8Entry} is the {@linkplain ClassEntry##internal-name
+ * internal form} of a binary package name and is not empty.
*
+ * @jvms 4.4.12 The {@code CONSTANT_Package_info} Structure
* @since 22
*/
@PreviewFeature(feature = PreviewFeature.Feature.CLASSFILE_API)
public sealed interface PackageEntry extends PoolEntry
permits AbstractPoolEntry.PackageEntryImpl {
/**
- * {@return the package name}
+ * {@return the {@linkplain ClassEntry##internal-name 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 d2af4c7c11ae5..d6dec01793267 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
@@ -24,11 +24,26 @@
*/
package java.lang.classfile.constantpool;
+import java.lang.classfile.Attribute;
+import java.lang.classfile.ClassFileBuilder;
+
import jdk.internal.javac.PreviewFeature;
/**
- * Models an entry in the constant pool of a classfile.
+ * Models an entry in the constant pool of a {@code class} file.
+ *
+ * @implNote
+ *
+ * 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.
+ *
+ * @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 65f75a6a062b3..1a1760930a594 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, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2022, 2024, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -28,10 +28,22 @@
import jdk.internal.javac.PreviewFeature;
/**
- * 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.
+ *
+ * Conceptually, a string entry is a record:
+ * {@snippet lang=text :
+ * // @link substring="StringEntry" target="ConstantPoolBuilder#stringEntry(String)" :
+ * StringEntry(String) // @link regex="String(?=[)])" target="#stringValue()"
+ * }
+ *
+ * Physically, a string entry is a record:
+ * {@snippet lang=text :
+ * // @link substring="StringEntry" target="ConstantPoolBuilder#stringEntry(Utf8Entry)" :
+ * StringEntry(Utf8Entry) // @link substring="Utf8Entry" target="#utf8()"
+ * }
*
+ * @jvms 4.4.3 The {@code CONSTANT_String_info} Structure
* @since 22
*/
@PreviewFeature(feature = PreviewFeature.Feature.CLASSFILE_API)
@@ -40,11 +52,17 @@ public sealed interface StringEntry
permits AbstractPoolEntry.StringEntryImpl {
/**
* {@return the UTF constant pool entry describing the string contents}
+ *
+ * @see ConstantPoolBuilder#stringEntry(Utf8Entry)
+ * ConstantPoolBuilder::stringEntry(Utf8Entry)
*/
Utf8Entry utf8();
/**
* {@return the string value for this entry}
+ *
+ * @see ConstantPoolBuilder#stringEntry(String)
+ * 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 b379854cfcbe4..c3b7f52a88d62 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, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2022, 2024, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -24,14 +24,30 @@
*/
package java.lang.classfile.constantpool;
+import java.io.DataInput;
+
import jdk.internal.classfile.impl.AbstractPoolEntry;
import jdk.internal.javac.PreviewFeature;
/**
- * 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.
+ *
+ * Conceptually, a UTF8 entry is a record:
+ * {@snippet lang=text :
+ * // @link substring="Utf8Entry" target="ConstantPoolBuilder#utf8Entry(String)" :
+ * Utf8Entry(String) // @link substring="String" target="#stringValue()"
+ * }
+ * where the encoded data length must be no more than 65535 bytes.
+ *
+ * Physically, a UTF8 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 22
*/
@PreviewFeature(feature = PreviewFeature.Feature.CLASSFILE_API)
@@ -41,6 +57,8 @@ public sealed interface Utf8Entry
/**
* {@return the string value for this entry}
+ *
+ * @see ConstantPoolBuilder#utf8Entry(String) ConstantPoolBuilder::utf8Entry
*/
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 1ba2b63b6a1fb..5c6a04a54b897 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, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2023, 2024, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -24,13 +24,55 @@
*/
/**
- *
+ * Unless otherwise noted, passing a {@code null} argument to a constructor or method of any Class-File API class or
+ * interface will cause a {@link NullPointerException} to be thrown. Additionally, invoking a method with an array or
+ * collection containing a {@code null} element will cause a {@code NullPointerException}, unless otherwise specified.
+ *
+ *
+ * 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.
+ *
+ *
+ * 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.
*
* @since 22
*/
@PreviewFeature(feature = PreviewFeature.Feature.CLASSFILE_API)
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;
+
import jdk.internal.javac.PreviewFeature;
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 0000000000000..87bdfe981cd40
--- /dev/null
+++ b/src/java.base/share/classes/java/lang/classfile/constantpool/snippet-files/PackageSnippets.java
@@ -0,0 +1,43 @@
+/*
+ * Copyright (c) 2024, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * 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 6999ef2a0aef1..207093389b5b4 100644
--- a/test/jdk/jdk/classfile/SnippetsTest.java
+++ b/test/jdk/jdk/classfile/SnippetsTest.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2023, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2023, 2024, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -41,7 +41,9 @@ public class SnippetsTest {
@ParameterizedTest
@ValueSource(strings = {
"src/java.base/share/classes/java/lang/classfile/snippet-files/PackageSnippets.java",
- "src/java.base/share/classes/java/lang/classfile/components/snippet-files/PackageSnippets.java"})
+ "src/java.base/share/classes/java/lang/classfile/components/snippet-files/PackageSnippets.java",
+ "src/java.base/share/classes/java/lang/classfile/constantpool/snippet-files/PackageSnippets.java",
+ })
void testSnippet(String source) throws Exception {
var p = Paths.get(System.getProperty("test.src", ".")).toAbsolutePath();
while ((p = p.getParent()) != null) {
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 22
*/
@@ -58,7 +66,11 @@ public sealed interface ConstantPool extends IterableNon-directly-writable constant pool entries
+ * In {@code class} file building and constant pool building, some constant pool
+ * entries supplied will not be {@linkplain #canWriteDirect(ConstantPool)
+ * directly writable} to this constant pool. For example, {@link #classEntry(Utf8Entry)
+ * classEntry(Utf8Entry)} may be called with an UTF8 entry not directly writable.
+ * Such entries will be first converted to a pool entry in this builder, reusing
+ * suitable entries or adding new entries if there is none suitable. As a
+ * result, all pool entries returned by writing methods in this builder is
+ * directly writable to this constant pool.
+ * Unbound constant pool entries
+ * Implementations may create unbound constant pool entries not belonging to
+ * an actual constant pool. They are convenient to represent constant pool
+ * entries referred by unbound {@linkplain Attribute attributes}. Their
+ * {@link #constantPool() constantPool()} returns a dummy constant pool that
+ * throws {@link UnsupportedOperationException} upon queries, their {@link
+ * #index() index()} return a non-positive invalid value, and they will always
+ * be converted by the {@linkplain ClassFileBuilder#constantPool() contextual
+ * constant pool} when they are written to {@code class} files.
*
+ * @see ConstantPoolBuilder##adoption Non-directly-writable constant pool entries
* @sealedGraph
* @since 22
*/
@@ -91,6 +106,14 @@ public sealed interface PoolEntry
/**
* {@return the constant pool this entry is from}
+ *
+ * @apiNote
+ * Given a {@link ConstantPoolBuilder} {@code builder} and a {@code
+ * PoolEntry} {@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.
+ *
+ * @see ##unbound Unbound constant pool entries
*/
ConstantPool constantPool();
@@ -105,11 +128,22 @@ 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}
+ * 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.
+ * 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) Utf8Entry::equalsString} instead
+ * of checking equality with the string value. This avoids inflation of UTF-8 entries as much as possible:
+ * {@snippet lang="java" class="PackageSnippets" region="isStaticWorkMethod"}
+ * 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, and another that accepts physical constant pool entries. The constant pool builder associated with
+ * {@code class} file builders, {@link ClassFileBuilder#constantPool 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.
+ *