8342465: Improve API documentation for java.lang.classfile

Reviewed-by: asotona, darcy
This commit is contained in:
Chen Liang 2025-01-27 14:03:35 +00:00
parent 7d6055a786
commit 1d8ccb8920
44 changed files with 2932 additions and 1014 deletions

View file

@ -1,5 +1,5 @@
/*
* Copyright (c) 2022, 2024, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2022, 2025, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -30,10 +30,33 @@ import java.util.Set;
import jdk.internal.classfile.impl.AccessFlagsImpl;
/**
* Models the access flags for a class, method, or field. Delivered as a
* {@link ClassElement}, {@link FieldElement}, or {@link MethodElement}
* when traversing the corresponding model type.
* Models the access flags for a class, method, or field. The access flags
* appears exactly once in each class, method, or field; a {@link
* ClassBuilder} and a {@link FieldBuilder} chooses an unspecified default value
* if access flags are not provided, and a {@link MethodBuilder} is always
* created with access flags.
* <p>
* {@code AccessFlags} cannot be created via a factory method directly; it can
* be created with {@code withFlags} methods on the respective builders.
* <p>
* A {@link MethodBuilder} throws an {@link IllegalArgumentException} if it is
* supplied an {@code AccessFlags} object that changes the preexisting
* {@link ClassFile#ACC_STATIC ACC_STATIC} flag of the builder, because the
* access flag change may invalidate previously supplied data to the builder.
*
* @apiNote
* The access flags of classes, methods, and fields are modeled as a standalone
* object to support streaming as elements for {@link ClassFileTransform}.
* Other access flags are not elements of a {@link CompoundElement} and thus not
* modeled by {@code AccessFlags}; they provide their own {@code flagsMask},
* {@code flags}, and {@code has} methods.
*
* @see ClassModel#flags()
* @see FieldModel#flags()
* @see MethodModel#flags()
* @see ClassBuilder#withFlags
* @see FieldBuilder#withFlags
* @see MethodBuilder#withFlags
* @since 24
*/
public sealed interface AccessFlags
@ -41,26 +64,36 @@ public sealed interface AccessFlags
permits AccessFlagsImpl {
/**
* {@return the access flags, as a bit mask}
* {@return the access flags, as a bit mask} It is in the range of unsigned
* short, {@code [0, 0xFFFF]}.
*/
int flagsMask();
/**
* {@return the access flags}
* {@return the access flags, as a set of flag enums}
*
* @throws IllegalArgumentException if the flags mask has any undefined bit set
* @see #location()
*/
Set<AccessFlag> flags();
/**
* {@return whether the specified flag is present} The specified flag
* should be a valid flag for the classfile location associated with this
* element otherwise false is returned.
* {@return whether the specified flag is set} If the specified flag
* is not available to this {@linkplain #location() location}, returns
* {@code false}.
*
* @param flag the flag to test
* @see #location()
*/
boolean has(AccessFlag flag);
/**
* {@return the classfile location for this element, which is either class,
* method, or field}
* {@return the {@code class} file location for this element, which is
* either class, method, or field}
*
* @see AccessFlag.Location#CLASS
* @see AccessFlag.Location#FIELD
* @see AccessFlag.Location#METHOD
*/
AccessFlag.Location location();
}

View file

@ -54,7 +54,7 @@ public sealed interface AnnotationValue {
/**
* Models an annotation value of an element-value pair.
* The {@linkplain #tag tag} of this value is {@value TAG_ANNOTATION}.
* The {@linkplain #tag tag} of this value is {@value %c TAG_ANNOTATION}.
*
* @since 24
*/
@ -66,7 +66,7 @@ public sealed interface AnnotationValue {
/**
* Models an array value of an element-value pair.
* The {@linkplain #tag tag} of this value is {@value TAG_ARRAY}.
* The {@linkplain #tag tag} of this value is {@value %c TAG_ARRAY}.
*
* @since 24
*/
@ -122,7 +122,7 @@ public sealed interface AnnotationValue {
/**
* Models a string value of an element-value pair.
* The {@linkplain #tag tag} of this value is {@value TAG_STRING}.
* The {@linkplain #tag tag} of this value is {@value %c TAG_STRING}.
*
* @since 24
*/
@ -149,7 +149,7 @@ public sealed interface AnnotationValue {
/**
* Models a double value of an element-value pair.
* The {@linkplain #tag tag} of this value is {@value TAG_DOUBLE}.
* The {@linkplain #tag tag} of this value is {@value %c TAG_DOUBLE}.
*
* @since 24
*/
@ -176,7 +176,7 @@ public sealed interface AnnotationValue {
/**
* Models a float value of an element-value pair.
* The {@linkplain #tag tag} of this value is {@value TAG_FLOAT}.
* The {@linkplain #tag tag} of this value is {@value %c TAG_FLOAT}.
*
* @since 24
*/
@ -203,7 +203,7 @@ public sealed interface AnnotationValue {
/**
* Models a long value of an element-value pair.
* The {@linkplain #tag tag} of this value is {@value TAG_LONG}.
* The {@linkplain #tag tag} of this value is {@value %c TAG_LONG}.
*
* @since 24
*/
@ -230,7 +230,7 @@ public sealed interface AnnotationValue {
/**
* Models an int value of an element-value pair.
* The {@linkplain #tag tag} of this value is {@value TAG_INT}.
* The {@linkplain #tag tag} of this value is {@value %c TAG_INT}.
*
* @since 24
*/
@ -257,7 +257,7 @@ public sealed interface AnnotationValue {
/**
* Models a short value of an element-value pair.
* The {@linkplain #tag tag} of this value is {@value TAG_SHORT}.
* The {@linkplain #tag tag} of this value is {@value %c TAG_SHORT}.
*
* @since 24
*/
@ -287,7 +287,7 @@ public sealed interface AnnotationValue {
/**
* Models a char value of an element-value pair.
* The {@linkplain #tag tag} of this value is {@value TAG_CHAR}.
* The {@linkplain #tag tag} of this value is {@value %c TAG_CHAR}.
*
* @since 24
*/
@ -317,7 +317,7 @@ public sealed interface AnnotationValue {
/**
* Models a byte value of an element-value pair.
* The {@linkplain #tag tag} of this value is {@value TAG_BYTE}.
* The {@linkplain #tag tag} of this value is {@value %c TAG_BYTE}.
*
* @since 24
*/
@ -347,7 +347,7 @@ public sealed interface AnnotationValue {
/**
* Models a boolean value of an element-value pair.
* The {@linkplain #tag tag} of this value is {@value TAG_BOOLEAN}.
* The {@linkplain #tag tag} of this value is {@value %c TAG_BOOLEAN}.
*
* @since 24
*/
@ -377,7 +377,7 @@ public sealed interface AnnotationValue {
/**
* Models a class value of an element-value pair.
* The {@linkplain #tag tag} of this value is {@value TAG_CLASS}.
* The {@linkplain #tag tag} of this value is {@value %c TAG_CLASS}.
*
* @since 24
*/
@ -394,7 +394,7 @@ public sealed interface AnnotationValue {
/**
* Models an enum value of an element-value pair.
* The {@linkplain #tag tag} of this value is {@value TAG_ENUM}.
* The {@linkplain #tag tag} of this value is {@value %c TAG_ENUM}.
*
* @since 24
*/

View file

@ -39,7 +39,14 @@ import static java.util.Objects.requireNonNull;
* A {@link ClassFileElement} describing a {@code class} file structure that has
* attributes, such as a {@code class} file, a field, a method, a {@link
* CodeAttribute Code} attribute, or a record component.
* <p>
* Unless otherwise specified, most attributes that can be discovered in a
* {@link CompoundElement} implements the corresponding {@linkplain
* ClassFileElement##membership membership subinterface} of {@code
* ClassFileElement}, and can be sent to a {@link ClassFileBuilder} to be
* integrated into the built structure.
*
* @see java.lang.classfile.attribute
* @jvms 4.7 Attributes
* @sealedGraph
* @since 24

View file

@ -1,5 +1,5 @@
/*
* Copyright (c) 2022, 2024, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2022, 2025, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -25,8 +25,8 @@
package java.lang.classfile;
import java.lang.classfile.attribute.CodeAttribute;
import java.lang.classfile.constantpool.ClassEntry;
import java.lang.classfile.constantpool.ConstantPoolBuilder;
import java.lang.classfile.constantpool.Utf8Entry;
import java.lang.constant.ClassDesc;
import java.lang.constant.MethodTypeDesc;
@ -41,14 +41,19 @@ import jdk.internal.classfile.impl.DirectClassBuilder;
import jdk.internal.classfile.impl.Util;
/**
* A builder for classfiles. Builders are not created directly; they are passed
* to handlers by methods such as {@link ClassFile#build(ClassDesc, Consumer)}
* or to class transforms. The elements of a classfile can be specified
* abstractly (by passing a {@link ClassElement} to {@link #with(ClassFileElement)})
* or concretely by calling the various {@code withXxx} methods.
* A builder for a {@code class} file. {@link ClassFile} provides different
* {@code build} methods that accept handlers to configure such a builder;
* {@link ClassFile#build(ClassDesc, Consumer)} suffices for basic usage, while
* {@link ClassFile#build(ClassEntry, ConstantPoolBuilder, Consumer)} allows
* fine-grained control over {@linkplain ClassFileBuilder#constantPool() the
* constant pool}.
* <p>
* Refer to {@link ClassFileBuilder} for general guidance and caution around
* the use of builders for structures in the {@code class} file format.
*
* @see ClassFile#build(ClassEntry, ConstantPoolBuilder, Consumer)
* @see ClassModel
* @see ClassTransform
*
* @since 24
*/
public sealed interface ClassBuilder
@ -56,28 +61,38 @@ public sealed interface ClassBuilder
permits ChainedClassBuilder, DirectClassBuilder {
/**
* Sets the classfile version.
* Sets the version of this class.
*
* @param major the major version number
* @param minor the minor version number
* @return this builder
* @see ClassFileVersion
*/
default ClassBuilder withVersion(int major, int minor) {
return with(ClassFileVersion.of(major, minor));
}
/**
* Sets the classfile access flags.
* Sets the access flags of this class.
*
* @param flags the access flags, as a bit mask
* @return this builder
* @see AccessFlags
* @see AccessFlag.Location#CLASS
*/
default ClassBuilder withFlags(int flags) {
return with(new AccessFlagsImpl(AccessFlag.Location.CLASS, flags));
}
/**
* Sets the classfile access flags.
* @param flags the access flags
* Sets the access flags of this class.
*
* @param flags the access flags, as flag enums
* @return this builder
* @throws IllegalArgumentException if any flag cannot be applied to the
* {@link AccessFlag.Location#CLASS} location
* @see AccessFlags
* @see AccessFlag.Location#CLASS
*/
default ClassBuilder withFlags(AccessFlag... flags) {
return with(new AccessFlagsImpl(AccessFlag.Location.CLASS, flags));
@ -85,8 +100,10 @@ public sealed interface ClassBuilder
/**
* Sets the superclass of this class.
*
* @param superclassEntry the superclass
* @return this builder
* @see Superclass
*/
default ClassBuilder withSuperclass(ClassEntry superclassEntry) {
return with(Superclass.of(superclassEntry));
@ -94,9 +111,11 @@ public sealed interface ClassBuilder
/**
* Sets the superclass of this class.
*
* @param desc the superclass
* @return this builder
* @throws IllegalArgumentException if {@code desc} represents a primitive type
* @see Superclass
*/
default ClassBuilder withSuperclass(ClassDesc desc) {
return withSuperclass(constantPool().classEntry(desc));
@ -104,8 +123,10 @@ public sealed interface ClassBuilder
/**
* Sets the interfaces of this class.
*
* @param interfaces the interfaces
* @return this builder
* @see Interfaces
*/
default ClassBuilder withInterfaces(List<ClassEntry> interfaces) {
return with(Interfaces.of(interfaces));
@ -113,8 +134,10 @@ public sealed interface ClassBuilder
/**
* Sets the interfaces of this class.
*
* @param interfaces the interfaces
* @return this builder
* @see Interfaces
*/
default ClassBuilder withInterfaces(ClassEntry... interfaces) {
return withInterfaces(List.of(interfaces));
@ -122,8 +145,11 @@ public sealed interface ClassBuilder
/**
* Sets the interfaces of this class.
*
* @param interfaces the interfaces
* @return this builder
* @throws IllegalArgumentException if any element of {@code interfaces} is primitive
* @see Interfaces
*/
default ClassBuilder withInterfaceSymbols(List<ClassDesc> interfaces) {
return withInterfaces(Util.entryList(interfaces));
@ -131,32 +157,39 @@ public sealed interface ClassBuilder
/**
* Sets the interfaces of this class.
*
* @param interfaces the interfaces
* @return this builder
* @throws IllegalArgumentException if any element of {@code interfaces} is primitive
* @see Interfaces
*/
default ClassBuilder withInterfaceSymbols(ClassDesc... interfaces) {
// List view, since ref to interfaces is temporary
// list version does defensive copy
return withInterfaceSymbols(Arrays.asList(interfaces));
}
/**
* Adds a field.
* @param name the name of the field
* @param descriptor the field descriptor
* @param handler handler which receives a {@link FieldBuilder} which can
* further define the contents of the field
*
* @param name the field name
* @param descriptor the field descriptor string
* @param handler handler to supply the contents of the field
* @return this builder
* @see FieldModel
*/
ClassBuilder withField(Utf8Entry name,
Utf8Entry descriptor,
Consumer<? super FieldBuilder> handler);
/**
* Adds a field.
* @param name the name of the field
* @param descriptor the field descriptor
* @param flags the access flags for this field
* Adds a field, with only access flags.
*
* @param name the field name
* @param descriptor the field descriptor string
* @param flags the access flags for this field, as a bit mask
* @return this builder
* @see FieldModel
* @see FieldBuilder#withFlags(int)
*/
default ClassBuilder withField(Utf8Entry name,
Utf8Entry descriptor,
@ -166,11 +199,12 @@ public sealed interface ClassBuilder
/**
* Adds a field.
* @param name the name of the field
* @param descriptor the field descriptor
* @param handler handler which receives a {@link FieldBuilder} which can
* further define the contents of the field
*
* @param name the field name
* @param descriptor the symbolic field descriptor
* @param handler handler to supply the contents of the field
* @return this builder
* @see FieldModel
*/
default ClassBuilder withField(String name,
ClassDesc descriptor,
@ -181,11 +215,14 @@ public sealed interface ClassBuilder
}
/**
* Adds a field.
* @param name the name of the field
* @param descriptor the field descriptor
* @param flags the access flags for this field
* Adds a field, with only access flags.
*
* @param name the field name
* @param descriptor the symbolic field descriptor
* @param flags the access flags for this field, as a bit mask
* @return this builder
* @see FieldModel
* @see FieldBuilder#withFlags(int)
*/
default ClassBuilder withField(String name,
ClassDesc descriptor,
@ -197,28 +234,33 @@ public sealed interface ClassBuilder
/**
* Adds a field by transforming a field from another class.
*
* @implNote
* <p>This method behaves as if:
* <p>
* This method behaves as if:
* {@snippet lang=java :
* withField(field.fieldName(), field.fieldType(),
* b -> b.transformField(field, transform));
* // @link substring=withField target="#withField(Utf8Entry, Utf8Entry, Consumer)" :
* withField(field.fieldName(), field.fieldType(),
* fb -> fb.transform(field, transform)) // @link regex="transform(?=\()" target="FieldBuilder#transform"
* }
*
* @param field the field to be transformed
* @param transform the transform to apply to the field
* @return this builder
* @see FieldTransform
*/
ClassBuilder transformField(FieldModel field, FieldTransform transform);
/**
* Adds a method.
* @param name the name of the method
* Adds a method. The bit for {@link ClassFile#ACC_STATIC ACC_STATIC} flag
* cannot be modified by the {@code handler} later, and must be set through
* {@code methodFlags}.
*
* @param name the method name
* @param descriptor the method descriptor
* @param methodFlags the access flags
* @param handler handler which receives a {@link MethodBuilder} which can
* further define the contents of the method
* @param methodFlags the access flags as a bit mask, with the {@code
* ACC_STATIC} bit definitely set
* @param handler handler to supply the contents of the method
* @return this builder
* @see MethodModel
*/
ClassBuilder withMethod(Utf8Entry name,
Utf8Entry descriptor,
@ -226,14 +268,23 @@ public sealed interface ClassBuilder
Consumer<? super MethodBuilder> handler);
/**
* Adds a method, with only a {@code Code} attribute.
* Adds a method, with only access flags and a {@link CodeModel}. The bit
* for {@link ClassFile#ACC_STATIC ACC_STATIC} flag cannot be modified by
* the {@code handler} later, and must be set through {@code methodFlags}.
* <p>
* This method behaves as if:
* {@snippet lang=java :
* // @link substring=withMethod target="#withMethod(Utf8Entry, Utf8Entry, int, Consumer)" :
* withMethod(name, descriptor, methodFlags, mb -> mb.withCode(handler)) // @link substring=withCode target="MethodBuilder#withCode"
* }
*
* @param name the name of the method
* @param name the method name
* @param descriptor the method descriptor
* @param methodFlags the access flags
* @param handler handler which receives a {@link CodeBuilder} which can
* define the contents of the method body
* @param methodFlags the access flags as a bit mask, with the {@code
* ACC_STATIC} bit definitely set
* @param handler handler to supply the contents of the method body
* @return this builder
* @see MethodModel
*/
default ClassBuilder withMethodBody(Utf8Entry name,
Utf8Entry descriptor,
@ -243,13 +294,17 @@ public sealed interface ClassBuilder
}
/**
* Adds a method.
* @param name the name of the method
* Adds a method. The bit for {@link ClassFile#ACC_STATIC ACC_STATIC} flag
* cannot be modified by the {@code handler}, and must be set through
* {@code methodFlags}.
*
* @param name the method name
* @param descriptor the method descriptor
* @param methodFlags the access flags
* @param handler handler which receives a {@link MethodBuilder} which can
* further define the contents of the method
* @param methodFlags the access flags as a bit mask, with the {@code
* ACC_STATIC} bit definitely set
* @param handler handler to supply the contents of the method
* @return this builder
* @see MethodModel
*/
default ClassBuilder withMethod(String name,
MethodTypeDesc descriptor,
@ -262,13 +317,23 @@ public sealed interface ClassBuilder
}
/**
* Adds a method, with only a {@link CodeAttribute}.
* @param name the name of the method
* Adds a method, with only access flags and a {@link CodeModel}. The bit
* for {@link ClassFile#ACC_STATIC ACC_STATIC} flag cannot be modified by
* the {@code handler}, and must be set through {@code methodFlags}.
* <p>
* This method behaves as if:
* {@snippet lang=java :
* // @link substring=withMethod target="#withMethod(String, MethodTypeDesc, int, Consumer)" :
* withMethod(name, descriptor, methodFlags, mb -> mb.withCode(handler)) // @link substring=withCode target="MethodBuilder#withCode"
* }
*
* @param name the method name
* @param descriptor the method descriptor
* @param methodFlags the access flags
* @param handler handler which receives a {@link CodeBuilder} which can
* define the contents of the method body
* @param methodFlags the access flags as a bit mask, with the {@code
* ACC_STATIC} bit definitely set
* @param handler handler to supply the contents of the method body
* @return this builder
* @see MethodModel
*/
default ClassBuilder withMethodBody(String name,
MethodTypeDesc descriptor,
@ -278,17 +343,21 @@ public sealed interface ClassBuilder
}
/**
* Adds a method by transforming a method from another class.
*
* @implNote
* <p>This method behaves as if:
* Adds a method by transforming a method from another class. The transform
* cannot modify the {@link ClassFile#ACC_STATIC ACC_STATIC} flag of the
* original method.
* <p>
* This method behaves as if:
* {@snippet lang=java :
* withMethod(method.methodName(), method.methodType(),
* b -> b.transformMethod(method, transform));
* // @link substring=withMethod target="#withMethod(Utf8Entry, Utf8Entry, int, Consumer)" :
* withMethod(method.methodName(), method.methodType(), method.flags().flagMask(),
* mb -> mb.transform(method, transform)) // @link regex="transform(?=\()" target="MethodBuilder#transform"
* }
*
* @param method the method to be transformed
* @param transform the transform to apply to the method
* @return this builder
* @see MethodTransform
*/
ClassBuilder transformMethod(MethodModel method, MethodTransform transform);
}

View file

@ -1,5 +1,5 @@
/*
* Copyright (c) 2022, 2024, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2022, 2025, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -27,9 +27,21 @@ package java.lang.classfile;
import java.lang.classfile.attribute.*;
/**
* A marker interface for elements that can appear when traversing
* a {@link ClassModel} or be presented to a {@link ClassBuilder}.
* Marker interface for a member element of a {@link ClassModel}. Such an
* element can appear when traversing a {@link ClassModel} unless otherwise
* specified, be supplied to a {@link ClassBuilder}, and be processed by a
* {@link ClassTransform}.
* <p>
* {@link AccessFlags}, and {@link ClassFileVersion} are member elements of a
* class that appear exactly once during the traversal of a {@link ClassModel}.
* {@link Superclass} and {@link Interfaces} may be absent or appear at most
* once. A {@link ClassBuilder} may provide an alternative superclass if it is
* not defined but required.
*
* @see ClassFileElement##membership Membership Elements
* @see MethodElement
* @see FieldElement
* @see CodeElement
* @sealedGraph
* @since 24
*/

View file

@ -1,5 +1,5 @@
/*
* Copyright (c) 2022, 2024, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2022, 2025, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -31,17 +31,36 @@ import java.util.function.Consumer;
import jdk.internal.classfile.impl.TransformImpl;
/**
* A builder for a classfile or portion of a classfile. Builders are rarely
* created directly; they are passed to handlers by methods such as
* {@link ClassFile#build(ClassDesc, Consumer)} or to transforms.
* Elements of the newly built entity can be specified
* abstractly (by passing a {@link ClassFileElement} to {@link #with(ClassFileElement)}
* or concretely by calling the various {@code withXxx} methods.
* A builder for a {@link CompoundElement}, which accepts the member elements
* to be integrated into the built structure. Builders are usually passed as
* an argument to {@link Consumer} handlers, such as in {@link
* ClassFile#build(ClassDesc, Consumer)}. The handlers should deliver elements
* to a builder similar to how a {@link CompoundElement} traverses its member
* elements.
* <p>
* The basic way a builder accepts elements is through {@link #with}, which
* supports call chaining. Concrete subtypes of builders usually define extra
* methods to define elements directly to the builder, such as {@link
* ClassBuilder#withFlags(int)} or {@link CodeBuilder#aload(int)}.
* <p>
* Whether a member element can appear multiple times in a compound structure
* affects the behavior of the element in {@code ClassFileBuilder}s. If an
* element can appear at most once but multiple instances are supplied to a
* {@code ClassFileBuilder}, the last supplied instance appears on the built
* structure. If an element appears exactly once but no instance is supplied,
* an unspecified default value element may be used in that structure.
* <p>
* Due to restrictions of the {@code class} file format, certain member elements
* that can be modeled by the API cannot be represented in the built structure
* under specific circumstances. Passing such elements to the builder causes
* {@link IllegalArgumentException}. Some {@link ClassFile.Option}s control
* whether such elements should be altered or dropped to produce valid {@code
* class} files.
*
* @param <E> the element type
* @param <B> the builder type
* @param <E> the member element type
* @param <B> the self type of this builder
* @see CompoundElement
* @see ClassFileTransform
*
* @sealedGraph
* @since 24
*/
@ -49,8 +68,15 @@ public sealed interface ClassFileBuilder<E extends ClassFileElement, B extends C
extends Consumer<E> permits ClassBuilder, FieldBuilder, MethodBuilder, CodeBuilder {
/**
* Integrate the {@link ClassFileElement} into the entity being built.
* @param e the element
* Integrates the member element into the structure being built.
*
* @apiNote
* This method exists to implement {@link Consumer}; users can use {@link
* #with} for call chaining.
*
* @param e the member element
* @throws IllegalArgumentException if the member element cannot be
* represented in the {@code class} file format
*/
@Override
default void accept(E e) {
@ -58,9 +84,12 @@ public sealed interface ClassFileBuilder<E extends ClassFileElement, B extends C
}
/**
* Integrate the {@link ClassFileElement} into the entity being built.
* @param e the element
* Integrates the member element into the structure being built.
*
* @param e the member element
* @return this builder
* @throws IllegalArgumentException if the member element cannot be
* represented in the {@code class} file format
*/
B with(E e);
@ -70,10 +99,29 @@ public sealed interface ClassFileBuilder<E extends ClassFileElement, B extends C
ConstantPoolBuilder constantPool();
/**
* Apply a transform to a model, directing results to this builder.
* @param model the model to transform
* Applies a transform to a compound structure, directing results to this
* builder.
* <p>
* The transform will receive each element of the compound structure, as
* well as this builder for building the structure. The transform is free
* to preserve, remove, or replace elements as it sees fit.
* <p>
* A builder can run multiple transforms against different compound
* structures, integrating member elements of different origins.
*
* @apiNote
* Many subinterfaces have methods like {@link ClassBuilder#transformMethod}
* or {@link MethodBuilder#transformCode}. However, calling them is
* fundamentally different from calling this method: those methods call the
* {@code transform} on the child builders instead of on itself. For
* example, {@code classBuilder.transformMethod} calls {@code
* methodBuilder.transform} with a new method builder instead of calling
* {@code classBuilder.transform} on itself.
*
* @param model the structure to transform
* @param transform the transform to apply
* @return this builder
* @see ClassFileTransform
*/
default B transform(CompoundElement<E> model, ClassFileTransform<?, E, B> transform) {
@SuppressWarnings("unchecked")

View file

@ -1,5 +1,5 @@
/*
* Copyright (c) 2022, 2024, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2022, 2025, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -25,12 +25,34 @@
package java.lang.classfile;
/**
* Immutable model for a portion of (or the entirety of) a classfile. Elements
* that model parts of the classfile that have attributes will implement {@link
* AttributedElement}; elements that model complex parts of the classfile that
* themselves contain their own child elements will implement {@link
* CompoundElement}. Elements specific to various locations in the classfile
* will implement {@link ClassElement}, {@link MethodElement}, etc.
* Marker interface for structures with special capabilities in the {@code
* class} file format. {@link AttributedElement} indicates a structure has
* {@link Attribute}s. {@link CompoundElement} indicates a structure can be
* viewed as a composition of member structures, whose memberships are marked by
* {@link ClassElement}, {@link MethodElement}, {@link FieldElement}, or {@link
* CodeElement}.
*
* <h2 id="membership">Membership Elements</h2>
* {@link ClassModel}, {@link MethodModel}, {@link FieldModel}, and {@link
* CodeModel} each has a dedicated interface marking its member structures:
* {@link ClassElement}, {@link MethodElement}, {@link FieldElement}, and
* {@link CodeElement}. They can be supplied to a {@link ClassBuilder}, a
* {@link MethodBuilder}, a {@link FieldBuilder}, or a {@link CodeBuilder} to be
* included as members of the built model. Unless otherwise specified, these
* structures are delivered during the {@linkplain CompoundElement traversal} of
* the corresponding models. Some of these elements may appear at most once or
* exactly once in the traversal of the models; such elements have special
* treatment by {@link ClassFileBuilder} and are specified in their modeling
* interfaces. If such elements appear multiple times during traversal, the
* last occurrence should be used and all previous instances should be
* discarded.
* <p>
* These membership element marker interfaces are sealed; future versions of the
* Java SE Platform may define new elements to the sealed hierarchy when the
* {@code class} file format for the Java Platform evolves. Using an exhaustive
* pattern matching switch over these hierarchies indicates the user only wish
* the processing code to run on a specific version of Java Platform, and will
* fail if unknown new elements are encountered.
*
* @sealedGraph
* @since 24

View file

@ -1,5 +1,5 @@
/*
* Copyright (c) 2022, 2024, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2022, 2025, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -25,44 +25,74 @@
package java.lang.classfile;
import java.lang.classfile.attribute.RuntimeVisibleAnnotationsAttribute;
import java.util.function.Predicate;
import java.util.function.Supplier;
/**
* A transformation on streams of elements. Transforms are used during
* transformation of classfile entities; a transform is provided to a method like
* {@link ClassFile#transformClass(ClassModel, ClassTransform)}, and the elements of the class,
* along with a builder, are presented to the transform.
*
* <p>The subtypes of {@linkplain
* ClassFileTransform} (e.g., {@link ClassTransform}) are functional interfaces
* that accept an element and a corresponding builder. Since any element can be
* reproduced on the builder via {@link ClassBuilder#with(ClassFileElement)}, a
* transform can easily leave elements in place, remove them, replace them, or
* augment them with other elements. This enables localized transforms to be
* represented concisely.
*
* <p>Transforms also have an {@link #atEnd(ClassFileBuilder)} method, for
* which the default implementation does nothing, so that a transform can
* perform additional building after the stream of elements is exhausted.
*
* <p>Transforms can be chained together via the {@link
* #andThen(ClassFileTransform)} method, so that the output of one becomes the
* input to another. This allows smaller units of transformation to be captured
* and reused.
*
* <p>Some transforms are stateful; for example, a transform that injects an
* annotation on a class may watch for the {@link RuntimeVisibleAnnotationsAttribute}
* element and transform it if found, but if it is not found, will generate a
* {@linkplain RuntimeVisibleAnnotationsAttribute} element containing the
* injected annotation from the {@linkplain #atEnd(ClassFileBuilder)} handler.
* To do this, the transform must accumulate some state during the traversal so
* that the end handler knows what to do. If such a transform is to be reused,
* its state must be reset for each traversal; this will happen automatically if
* the transform is created with {@link ClassTransform#ofStateful(Supplier)} (or
* corresponding methods for other classfile locations.)
* A transformation on a {@link CompoundElement} by processing its individual
* member elements and sending the results to a {@link ClassFileBuilder},
* through {@link ClassFileBuilder#transform}. A subtype of {@code
* ClassFileTransform} is defined for each subtype of {@link CompoundElement}
* and {@link ClassFileBuilder}, as shown in the sealed class hierarchy below.
* <p>
* For example, this is a basic transformation of a {@link CodeModel} that
* redirects all calls to static methods in the {@code Foo} class to the {@code
* Bar} class, preserving all other elements:
* {@snippet file="PackageSnippets.java" region=fooToBarTransform}
* Note that if no transformation of a member element is desired, the element
* should be presented to {@link ClassFileBuilder#with builder::with}. If no
* action is taken, that member element is dropped.
* <p>
* More advanced usages of transforms include {@linkplain ##start-end start or
* end handling}, {@linkplain ##stateful stateful transformation} that makes a
* decision based on previously encountered member elements, and {@linkplain
* ##composition composition} of transforms, where one transform processes the
* results of a previous transform on the input compound structure. All these
* capabilities are supported by this interface and accessible to user transform
* implementations.
* <p id="start-end">
* Users can define custom start and end handling for a transform by overriding
* {@link #atStart} and {@link #atEnd}. The start handler is called before any
* member element is processed, and the end handler is called after all member
* elements are processed. For example, the start handler can be used to inject
* extra code elements to the beginning of a code array, and the end handler,
* combined with stateful transformation, can perform cleanup actions, such as
* determining if an attribute has been merged, or if a new attribute should be
* defined. Each subtype of {@code ClassFileTransform} defines a utility method
* {@code endHandler} that returns a transform that only has end handling.
* <p id="stateful">
* Transforms can have states that persist across processing of individual
* member elements. For example, if a transform injects an annotation, the
* transform may keep track if it has encountered and presented an updated
* {@link RuntimeVisibleAnnotationsAttribute} to the builder; if it has not yet,
* it can present a new attribute containing only the injected annotation in its
* end handler. If such a transform is to be shared or reused, each returned
* transform should have its own state. Each subtype of {@code ClassFileTransform}
* defines a utility method {@code ofStateful} where a supplier creates the
* transform at its initial state each time the transform is reused.
* <p id="composition">
* Transforms can be composed via {@link #andThen}. When this transform is
* composed with another transform, it means the output member elements received
* by the {@link ClassFileBuilder} become the input elements to that other
* transform. Composition avoids building intermediate structures for multiple
* transforms to run on. Each subtype of {@code ClassFileTransform} implements
* {@link #andThen}, which generally should not be implemented by users.
* <p>
* Transforms that run on smaller structures can be lifted to its enclosing
* structures to selectively run on all enclosed smaller structures of the same
* kind. For example, a {@link CodeTransform} can be lifted via {@link
* ClassTransform#transformingMethodBodies(Predicate, CodeTransform)} to
* transform the method body of select methods in the class it runs on. This
* allows users to write small transforms and apply to larger scales.
* <p>
* Besides {@link ClassFileBuilder#transform}, there are other methods that
* accepts a transform conveniently, such as {@link ClassFile#transformClass},
* {@link ClassBuilder#transformField}, {@link ClassBuilder#transformMethod}, or
* {@link MethodBuilder#transformCode}. They are convenience methods that suit
* the majority of transformation scenarios.
*
* @param <C> the transform type
* @param <E> the element type
* @param <E> the member element type
* @param <B> the builder type
*
* @sealedGraph
@ -79,6 +109,9 @@ public sealed interface ClassFileTransform<
* body.) If no transformation is desired, the element can be presented to
* {@link B#with(ClassFileElement)}. If the element is to be dropped, no
* action is required.
* <p>
* This method is called by the Class-File API. Users should never call
* this method.
*
* @param builder the builder for the new entity
* @param element the element
@ -89,6 +122,9 @@ public sealed interface ClassFileTransform<
* Take any final action during transformation of a classfile entity. Called
* after all elements of the class are presented to {@link
* #accept(ClassFileBuilder, ClassFileElement)}.
* <p>
* This method is called by the Class-File API. Users should never call
* this method.
*
* @param builder the builder for the new entity
* @implSpec The default implementation does nothing.
@ -100,6 +136,9 @@ public sealed interface ClassFileTransform<
* Take any preliminary action during transformation of a classfile entity.
* Called before any elements of the class are presented to {@link
* #accept(ClassFileBuilder, ClassFileElement)}.
* <p>
* This method is called by the Class-File API. Users should never call
* this method.
*
* @param builder the builder for the new entity
* @implSpec The default implementation does nothing.
@ -110,6 +149,10 @@ public sealed interface ClassFileTransform<
/**
* Chain this transform with another; elements presented to the builder of
* this transform will become the input to the next transform.
* <p>
* This method is implemented by the Class-File API. Users usually don't
* have sufficient access to Class-File API functionalities to override this
* method correctly for generic downstream transforms.
*
* @param next the downstream transform
* @return the chained transform

View file

@ -1,5 +1,5 @@
/*
* Copyright (c) 2022, 2024, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2022, 2025, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -24,32 +24,62 @@
*/
package java.lang.classfile;
import java.lang.reflect.ClassFileFormatVersion;
import jdk.internal.classfile.impl.ClassFileVersionImpl;
/**
* Models the classfile version information for a class. Delivered as a {@link
* java.lang.classfile.ClassElement} when traversing the elements of a {@link
* ClassModel}.
* Models the minor and major version numbers of a {@code class} file (JVMS
* {@jvms 4.1}). The {@code class} file version appears exactly once in each
* class, and is set to an unspecified default value if not explicitly provided.
* <p>
* The major versions of {@code class} file format begins at {@value
* ClassFile#JAVA_1_VERSION} for Java Platform version 1.0.2, and is continuous
* up to {@link ClassFile#latestMajorVersion()}. In general, each major version
* defines a new supported {@code class} file format, modeled by {@link
* ClassFileFormatVersion}, and supports all previous formats.
* <p>
* For major versions up to {@value ClassFile#JAVA_11_VERSION} for Java SE
* Platform 11, the minor version of any value is supported. For major versions
* {@value ClassFile#JAVA_12_VERSION} for Java SE Platform version 12 and above,
* the minor version must be {@code 0} or {@value ClassFile#PREVIEW_MINOR_VERSION}.
* The minor version {@code 0} is always supported, and represents the format
* modeled by {@link ClassFileFormatVersion}. The minor version {@code 65535}
* indicates the {@code class} file uses preview features of the Java SE
* Platform release represented by the major version. A Java Virtual Machine
* can only load such a {@code class} file if it has the same Java SE Platform
* version and the JVM has preview features enabled.
*
* @see ClassModel#majorVersion()
* @see ClassModel#minorVersion()
* @see ClassFileFormatVersion
* @jvms 4.1 The {@code ClassFile} Structure
* @since 24
*/
public sealed interface ClassFileVersion
extends ClassElement
permits ClassFileVersionImpl {
/**
* {@return the major classfile version}
* {@return the major version} It is in the range of unsigned short, {@code
* [0, 65535]}.
*
* @apiNote
* Constants in {@link ClassFile} named {@code Java_#_VERSION}, where # is
* a release number, such as {@link ClassFile#JAVA_21_VERSION}, describe the
* class major versions of the Java Platform SE.
*/
int majorVersion();
/**
* {@return the minor classfile version}
* {@return the minor version} It is in the range of unsigned short, {@code
* [0, 65535]}.
*/
int minorVersion();
/**
* {@return a {@link ClassFileVersion} element}
* @param majorVersion the major classfile version
* @param minorVersion the minor classfile version
* @param majorVersion the major version
* @param minorVersion the minor version
*/
static ClassFileVersion of(int majorVersion, int minorVersion) {
return new ClassFileVersionImpl(majorVersion, minorVersion);

View file

@ -1,5 +1,5 @@
/*
* Copyright (c) 2022, 2024, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2022, 2025, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -24,7 +24,11 @@
*/
package java.lang.classfile;
import java.io.IOException;
import java.io.InputStream;
import java.io.UncheckedIOException;
import java.lang.classfile.ClassFile.StackMapsOption;
import java.lang.classfile.attribute.StackMapTableAttribute;
import java.lang.constant.ClassDesc;
import java.lang.invoke.MethodHandles;
import java.util.Collection;
@ -42,27 +46,42 @@ import static java.lang.constant.ConstantDescs.CD_Object;
import static java.util.Objects.requireNonNull;
/**
* Provides class hierarchy information for generating correct stack maps
* during code building.
* Provides class hierarchy information for {@linkplain StackMapsOption stack
* maps generation} and {@linkplain ClassFile#verify(byte[]) verification}.
* A class hierarchy resolver must be able to process all classes and interfaces
* encountered during these workloads.
*
* @see ClassFile.ClassHierarchyResolverOption
* @see StackMapTableAttribute
* @jvms 4.10.1.2 Verification Type System
* @since 24
*/
@FunctionalInterface
public interface ClassHierarchyResolver {
/**
* {@return the default instance of {@linkplain ClassHierarchyResolver} that
* {@return the default instance of {@code ClassHierarchyResolver} that
* gets {@link ClassHierarchyInfo} from system class loader with reflection}
* This default instance cannot load classes from other class loaders, such
* as the caller's class loader; it also loads the system classes if they
* are not yet loaded, which makes it unsuitable for instrumentation.
*/
static ClassHierarchyResolver defaultResolver() {
return ClassHierarchyImpl.DEFAULT_RESOLVER;
}
/**
* {@return the {@link ClassHierarchyInfo} for a given class name, or null
* if the name is unknown to the resolver}
* {@return the {@code ClassHierarchyInfo} for a given class name, or {@code
* null} if the name is unknown to the resolver}
* <p>
* This method is called by the Class-File API to obtain the hierarchy
* information of a class or interface; users should not call this method.
* The symbolic descriptor passed by the Class-File API always represents
* a class or interface.
*
* @param classDesc descriptor of the class
* @throws IllegalArgumentException if a class shouldn't be queried for hierarchy
* @throws IllegalArgumentException if a class shouldn't be queried for
* hierarchy, such as when it is inaccessible
*/
ClassHierarchyInfo getClassInfo(ClassDesc classDesc);
@ -78,6 +97,7 @@ public interface ClassHierarchyResolver {
*
* @param superClass descriptor of the super class, may be {@code null}
* @return the info indicating the super class
* @see Superclass
*/
static ClassHierarchyInfo ofClass(ClassDesc superClass) {
return new ClassHierarchyImpl.ClassHierarchyInfoImpl(superClass, false);
@ -94,14 +114,15 @@ public interface ClassHierarchyResolver {
}
/**
* Chains this {@linkplain ClassHierarchyResolver} with another to be
* consulted if this resolver does not know about the specified class.
* Chains this {@code ClassHierarchyResolver} with another to be consulted
* if this resolver does not know about the specified class.
*
* @implSpec
* The default implementation returns resolver implemented to query {@code
* other} resolver in case this resolver returns {@code null}.
*
* @param other the other resolver
* @return the chained resolver
*
* @implSpec The default implementation returns resolver implemented to ask
* other resolver in cases where this resolver returns {@code null}.
*/
default ClassHierarchyResolver orElse(ClassHierarchyResolver other) {
requireNonNull(other);
@ -117,32 +138,32 @@ public interface ClassHierarchyResolver {
}
/**
* Returns a ClassHierarchyResolver that caches class hierarchy information from this
* resolver. The returned resolver will not update if delegate resolver returns differently.
* The thread safety of the returned resolver depends on the thread safety of the map
* {@return a {@code ClassHierarchyResolver} that caches class hierarchy
* information from this resolver} The returned resolver will not update if
* the query results from this resolver changed over time. The thread
* safety of the returned resolver depends on the thread safety of the map
* returned by the {@code cacheFactory}.
*
* @param cacheFactory the factory for the cache
* @return the ClassHierarchyResolver with caching
* @implSpec
* The default implementation returns a resolver holding an instance of the
* cache map provided by the {@code cacheFactory}. It looks up in the cache
* map, or if a class name has not yet been queried, queries this resolver
* and caches the result, including a {@code null} that indicates unknown
* class names. The cache map may refuse {@code null} keys and values.
*
* @implSpec The default implementation returns resolver holding an instance
* of the cache map provided by the {@code cacheFactory}. It asks
* the cache map always first and fills the cache map with all
* resolved and also unresolved class info. The cache map may refuse
* {@code null} keys and values.
* @param cacheFactory the factory for the cache
*/
default ClassHierarchyResolver cached(Supplier<Map<ClassDesc, ClassHierarchyInfo>> cacheFactory) {
return new ClassHierarchyImpl.CachedClassHierarchyResolver(this, cacheFactory.get());
}
/**
* Returns a ClassHierarchyResolver that caches class hierarchy information from this
* resolver. The returned resolver will not update if delegate resolver returns differently.
* The returned resolver is not thread-safe.
* {@return a {@code ClassHierarchyResolver} that caches class hierarchy
* information from this resolver} The returned resolver will not update if
* the query results from this resolver changed over time. The returned
* resolver is not thread-safe.
* {@snippet file="PackageSnippets.java" region="lookup-class-hierarchy-resolver"}
*
* @return the ClassHierarchyResolver
*
* @implSpec The default implementation calls {@link #cached(Supplier)} with
* {@link HashMap} supplier as {@code cacheFactory}.
*/
@ -160,24 +181,24 @@ public interface ClassHierarchyResolver {
}
/**
* Returns a {@linkplain ClassHierarchyResolver} that extracts class hierarchy
* information from classfiles located by a mapping function. The mapping function
* should return null if it cannot provide a mapping for a classfile. Any IOException
* from the provided input stream is rethrown as an UncheckedIOException.
* {@return a {@code ClassHierarchyResolver} that extracts class hierarchy
* information from {@code class} files returned by a mapping function} The
* mapping function should return {@code null} if it cannot provide a
* {@code class} file for a class name. Any {@link IOException} from the
* provided input stream is rethrown as an {@link UncheckedIOException}
* in {@link #getClassInfo(ClassDesc)}.
*
* @param classStreamResolver maps class descriptors to classfile input streams
* @return the {@linkplain ClassHierarchyResolver}
* @param classStreamResolver maps class descriptors to {@code class} file input streams
*/
static ClassHierarchyResolver ofResourceParsing(Function<ClassDesc, InputStream> classStreamResolver) {
return new ClassHierarchyImpl.ResourceParsingClassHierarchyResolver(requireNonNull(classStreamResolver));
}
/**
* Returns a {@linkplain ClassHierarchyResolver} that extracts class hierarchy
* information from classfiles located by a class loader.
* {@return a {@code ClassHierarchyResolver} that extracts class hierarchy
* information from {@code class} files located by a class loader}
*
* @param loader the class loader, to find class files
* @return the {@linkplain ClassHierarchyResolver}
*/
static ClassHierarchyResolver ofResourceParsing(ClassLoader loader) {
requireNonNull(loader);
@ -190,24 +211,22 @@ public interface ClassHierarchyResolver {
}
/**
* Returns a {@linkplain ClassHierarchyResolver} that extracts class hierarchy
* information from collections of class hierarchy metadata
* {@return a {@code ClassHierarchyResolver} that extracts class hierarchy
* information from collections of class hierarchy metadata}
*
* @param interfaces a collection of classes known to be interfaces
* @param classToSuperClass a map from classes to their super classes
* @return the {@linkplain ClassHierarchyResolver}
*/
static ClassHierarchyResolver of(Collection<ClassDesc> interfaces,
Map<ClassDesc, ClassDesc> classToSuperClass) {
Map<ClassDesc, ClassDesc> classToSuperClass) {
return new StaticClassHierarchyResolver(interfaces, classToSuperClass);
}
/**
* Returns a ClassHierarchyResolver that extracts class hierarchy information via
* the Reflection API with a {@linkplain ClassLoader}.
* {@return a {@code ClassHierarchyResolver} that extracts class hierarchy
* information via classes loaded by a class loader with reflection}
*
* @param loader the class loader
* @return the class hierarchy resolver
*/
static ClassHierarchyResolver ofClassLoading(ClassLoader loader) {
requireNonNull(loader);
@ -224,13 +243,13 @@ public interface ClassHierarchyResolver {
}
/**
* Returns a ClassHierarchyResolver that extracts class hierarchy information via
* the Reflection API with a {@linkplain MethodHandles.Lookup Lookup}. If the class
* resolved is inaccessible to the given lookup, it throws {@link
* {@return a {@code ClassHierarchyResolver} that extracts class hierarchy
* information via classes accessible to a {@link MethodHandles.Lookup}
* with reflection} If the class resolved is inaccessible to the given
* lookup, {@link #getClassInfo(ClassDesc)} throws {@link
* IllegalArgumentException} instead of returning {@code null}.
*
* @param lookup the lookup, must be able to access classes to resolve
* @return the class hierarchy resolver
*/
static ClassHierarchyResolver ofClassLoading(MethodHandles.Lookup lookup) {
requireNonNull(lookup);

View file

@ -1,5 +1,5 @@
/*
* Copyright (c) 2022, 2024, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2022, 2025, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -25,18 +25,41 @@
package java.lang.classfile;
import java.lang.classfile.attribute.BootstrapMethodsAttribute;
import java.lang.classfile.attribute.ModuleAttribute;
import java.lang.classfile.constantpool.ClassEntry;
import java.lang.classfile.constantpool.ConstantPool;
import java.lang.classfile.constantpool.ConstantPoolBuilder;
import java.lang.constant.ClassDesc;
import java.lang.reflect.AccessFlag;
import java.util.List;
import java.util.Optional;
import java.util.function.Consumer;
import jdk.internal.classfile.impl.ClassImpl;
/**
* Models a classfile. The contents of the classfile can be traversed via
* a streaming view, or via random access (e.g.,
* {@link #flags()}), or by freely mixing the two.
* Models a {@code class} file. A {@code class} file can be viewed as a
* {@linkplain CompoundElement composition} of {@link ClassElement}s, or by
* random access via accessor methods if only specific parts of the {@code
* class} file is needed.
* <p>
* Use {@link ClassFile#parse(byte[])}, which parses the binary data of a {@code
* class} file into a model, to obtain a {@code ClassModel}.
* <p>
* To construct a {@code class} file, use {@link ClassFile#build(ClassDesc,
* Consumer)}. {@link ClassFile#transformClass(ClassModel, ClassTransform)}
* allows creating a new class by selectively processing the original class
* elements and directing the results to a class builder.
* <p>
* A class holds attributes, most of which are accessible as member elements.
* {@link BootstrapMethodsAttribute} can only be accessed via {@linkplain
* AttributedElement explicit attribute reading}, as it is modeled as part of
* the {@linkplain #constantPool() constant pool}.
*
* @see ClassFile#parse(byte[])
* @see ClassTransform
* @jvms 4.1 The {@code ClassFile} Structure
* @since 24
*/
public sealed interface ClassModel
@ -45,19 +68,35 @@ public sealed interface ClassModel
/**
* {@return the constant pool for this class}
*
* @see ConstantPoolBuilder#of(ClassModel)
*/
ConstantPool constantPool();
/** {@return the access flags} */
/**
* {@return the access flags}
*
* @see AccessFlag.Location#CLASS
*/
AccessFlags flags();
/** {@return the constant pool entry describing the name of this class} */
ClassEntry thisClass();
/** {@return the major classfile version} */
/**
* {@return the major version of this class} It is in the range of unsigned
* short, {@code [0, 65535]}.
*
* @see ClassFileVersion
*/
int majorVersion();
/** {@return the minor classfile version} */
/**
* {@return the minor version of this class} It is in the range of unsigned
* short, {@code [0, 65535]}.
*
* @see ClassFileVersion
*/
int minorVersion();
/** {@return the fields of this class} */
@ -66,12 +105,28 @@ public sealed interface ClassModel
/** {@return the methods of this class} */
List<MethodModel> methods();
/** {@return the superclass of this class, if there is one} */
/**
* {@return the superclass of this class, if there is one}
* This {@code class} file may have no superclass if this represents a
* {@linkplain #isModuleInfo() module descriptor} or the {@link Object}
* class; otherwise, it must have a superclass. If this is an interface,
* the superclass must be {@link Object}.
*
* @see Superclass
*/
Optional<ClassEntry> superclass();
/** {@return the interfaces implemented by this class} */
/**
* {@return the interfaces implemented by this class}
*
* @see Interfaces
*/
List<ClassEntry> interfaces();
/** {@return whether this class is a module descriptor} */
/**
* {@return whether this {@code class} file is a module descriptor}
*
* @see ClassFile#buildModule(ModuleAttribute, Consumer)
*/
boolean isModuleInfo();
}

View file

@ -1,5 +1,5 @@
/*
* Copyright (c) 2022, 2024, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2022, 2025, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -35,9 +35,12 @@ import static java.util.Objects.requireNonNull;
/**
* A transformation on streams of {@link ClassElement}.
* <p>
* Refer to {@link ClassFileTransform} for general guidance and caution around
* the use of transforms for structures in the {@code class} file format.
*
* @see ClassFileTransform
*
* @see ClassModel
* @see ClassFile#transformClass(ClassModel, ClassTransform)
* @since 24
*/
@FunctionalInterface
@ -45,7 +48,7 @@ public non-sealed interface ClassTransform
extends ClassFileTransform<ClassTransform, ClassElement, ClassBuilder> {
/**
* A class transform that sends all elements to the builder.
* A class transform that passes all elements to the builder.
*/
static final ClassTransform ACCEPT_ALL = new ClassTransform() {
@Override
@ -55,7 +58,7 @@ public non-sealed interface ClassTransform
};
/**
* Create a stateful class transform from a {@link Supplier}. The supplier
* Creates a stateful class transform from a {@link Supplier}. The supplier
* will be invoked for each transformation.
*
* @param supplier a {@link Supplier} that produces a fresh transform object
@ -67,7 +70,7 @@ public non-sealed interface ClassTransform
}
/**
* Create a class transform that passes each element through to the builder,
* Creates a class transform that passes each element through to the builder,
* and calls the specified function when transformation is complete.
*
* @param finisher the function to call when transformation is complete
@ -89,8 +92,8 @@ public non-sealed interface ClassTransform
}
/**
* Create a class transform that passes each element through to the builder,
* except for those that the supplied {@link Predicate} is true for.
* Creates a class transform that passes each element through to the builder,
* except for those that the supplied {@link Predicate} returns true for.
*
* @param filter the predicate that determines which elements to drop
* @return the class transform
@ -104,8 +107,10 @@ public non-sealed interface ClassTransform
}
/**
* Create a class transform that transforms {@link MethodModel} elements
* with the supplied method transform.
* Creates a class transform that transforms {@link MethodModel} elements
* with the supplied method transform for methods that the supplied {@link
* Predicate} returns true for, passing other elements through to the
* builder.
*
* @param filter a predicate that determines which methods to transform
* @param xform the method transform
@ -117,8 +122,9 @@ public non-sealed interface ClassTransform
}
/**
* Create a class transform that transforms {@link MethodModel} elements
* with the supplied method transform.
* Creates a class transform that transforms {@link MethodModel} elements
* with the supplied method transform, passing other elements through to the
* builder.
*
* @param xform the method transform
* @return the class transform
@ -128,8 +134,10 @@ public non-sealed interface ClassTransform
}
/**
* Create a class transform that transforms the {@link CodeAttribute} (method body)
* of {@link MethodModel} elements with the supplied code transform.
* Creates a class transform that transforms the {@link CodeAttribute} (method body)
* of {@link MethodModel} elements with the supplied code transform for
* methods that the supplied {@link Predicate} returns true for, passing
* other elements through to the builder.
*
* @param filter a predicate that determines which methods to transform
* @param xform the code transform
@ -141,8 +149,9 @@ public non-sealed interface ClassTransform
}
/**
* Create a class transform that transforms the {@link CodeAttribute} (method body)
* of {@link MethodModel} elements with the supplied code transform.
* Creates a class transform that transforms the {@link CodeAttribute} (method body)
* of {@link MethodModel} elements with the supplied code transform, passing
* other elements through to the builder.
*
* @param xform the code transform
* @return the class transform
@ -152,8 +161,9 @@ public non-sealed interface ClassTransform
}
/**
* Create a class transform that transforms {@link FieldModel} elements
* with the supplied field transform.
* Creates a class transform that transforms {@link FieldModel} elements
* with the supplied field transform, passing other elements through to the
* builder.
*
* @param xform the field transform
* @return the class transform

View file

@ -1,5 +1,5 @@
/*
* Copyright (c) 2022, 2024, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2022, 2025, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -29,13 +29,20 @@ import java.lang.classfile.attribute.RuntimeVisibleTypeAnnotationsAttribute;
import java.lang.classfile.attribute.StackMapTableAttribute;
/**
* A marker interface for elements that can appear when traversing
* a {@link CodeModel} or be presented to a {@link CodeBuilder}. Code elements
* are either an {@link Instruction}, which models an instruction in the body
* of a method, or a {@link PseudoInstruction}, which models metadata from
* the code attribute, such as line number metadata, local variable metadata,
* exception metadata, label target metadata, etc.
* Marker interface for a member element of a {@link CodeModel}. Such an
* element can appear when traversing a {@link CodeModel} unless otherwise
* specified, be supplied to a {@link CodeBuilder}, and be processed by a
* {@link CodeTransform}.
* <p>
* Code elements can be categorized into {@link Instruction}, {@link
* PseudoInstruction}, and {@link Attribute}. Unlike in other {@link
* CompoundElement}, the order of elements for all {@link Instruction}s and some
* {@link PseudoInstruction}s is significant.
*
* @see ClassFileElement##membership Membership Elements
* @see ClassElement
* @see MethodElement
* @see FieldElement
* @sealedGraph
* @since 24
*/

View file

@ -1,5 +1,5 @@
/*
* Copyright (c) 2022, 2024, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2022, 2025, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -25,17 +25,44 @@
package java.lang.classfile;
import java.lang.classfile.ClassFile.DeadLabelsOption;
import java.lang.classfile.ClassFile.DebugElementsOption;
import java.lang.classfile.ClassFile.LineNumbersOption;
import java.lang.classfile.attribute.BootstrapMethodsAttribute;
import java.lang.classfile.attribute.CodeAttribute;
import java.lang.classfile.attribute.StackMapTableAttribute;
import java.lang.classfile.instruction.ExceptionCatch;
import java.util.List;
import java.util.Optional;
import java.util.function.Consumer;
import jdk.internal.classfile.impl.BufferedCodeBuilder;
/**
* Models the body of a method (the {@code Code} attribute). The instructions
* of the method body are accessed via a streaming view.
* Models the body of a method (the {@code Code} attribute). A {@code Code}
* attribute is viewed as a {@linkplain CompoundElement composition} of {@link
* CodeElement}s, which is the only way to access {@link Instruction}s; the
* order of elements of a code model is significant.
* <p>
* A {@code CodeModel} is obtained from {@link MethodModel#code()}, or in the
* traversal of the member elements of a method.
* <p>
* {@link MethodBuilder#withCode} is the main way to build code models. {@link
* MethodBuilder#transformCode} and {@link CodeBuilder#transforming} allow
* creating new {@code Code} attributes by selectively processing the original
* code elements and directing the results to a code builder.
* <p>
* A {@code Code} attribute holds attributes, but they are usually not member
* elements, but are decomposed to {@link PseudoInstruction}, accessible
* according to {@link DeadLabelsOption}, {@link DebugElementsOption}, and
* {@link LineNumbersOption}. {@link StackMapTableAttribute} can only be
* accessed via {@linkplain AttributedElement explicit attribute reading}, as it
* is considered a derived property from the code body.
*
* @see MethodModel#code()
* @see CodeTransform
* @see CodeAttribute
* @jvms 4.7.3 The {@code Code} Attribute
* @since 24
*/
public sealed interface CodeModel

View file

@ -1,5 +1,5 @@
/*
* Copyright (c) 2022, 2024, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2022, 2025, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -32,10 +32,22 @@ import jdk.internal.classfile.impl.TransformImpl;
import static java.util.Objects.requireNonNull;
/**
* A transformation on streams of {@link CodeElement}.
*
* @see ClassFileTransform
* A transformation on streams of {@link CodeElement}. The stream can come
* from a {@link CodeModel}, or a handler to a {@link CodeBuilder} as in
* {@link CodeBuilder#transforming}.
* <p>
* Refer to {@link ClassFileTransform} for general guidance and caution around
* the use of transforms for structures in the {@code class} file format.
* <p>
* A code transform can be lifted to a method or a class transform via {@link
* MethodTransform#transformingCode(CodeTransform)} and {@link
* ClassTransform#transformingMethodBodies(CodeTransform)}, transforming only
* the {@link CodeModel} within those structures and passing all other elements
* to the builders.
*
* @see CodeModel
* @see MethodBuilder#transformCode
* @see CodeBuilder#transforming
* @since 24
*/
@FunctionalInterface
@ -43,7 +55,7 @@ public non-sealed interface CodeTransform
extends ClassFileTransform<CodeTransform, CodeElement, CodeBuilder> {
/**
* A code transform that sends all elements to the builder.
* A code transform that passes all elements to the builder.
*/
CodeTransform ACCEPT_ALL = new CodeTransform() {
@Override
@ -53,7 +65,7 @@ public non-sealed interface CodeTransform
};
/**
* Create a stateful code transform from a {@link Supplier}. The supplier
* Creates a stateful code transform from a {@link Supplier}. The supplier
* will be invoked for each transformation.
*
* @param supplier a {@link Supplier} that produces a fresh transform object
@ -65,7 +77,7 @@ public non-sealed interface CodeTransform
}
/**
* Create a code transform that passes each element through to the builder,
* Creates a code transform that passes each element through to the builder,
* and calls the specified function when transformation is complete.
*
* @param finisher the function to call when transformation is complete

View file

@ -1,5 +1,5 @@
/*
* Copyright (c) 2022, 2024, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2022, 2025, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -37,14 +37,26 @@ import java.util.stream.StreamSupport;
import jdk.internal.classfile.components.ClassPrinter;
/**
* A {@link ClassFileElement} that has complex structure defined in terms of
* other classfile elements, such as a method, field, method body, or entire
* class. When encountering a {@linkplain CompoundElement}, clients have the
* option to treat the element as a single entity (e.g., an entire method)
* or to traverse the contents of that element with the methods in this class
* (e.g., {@link #forEach(Consumer)}, etc.)
* @param <E> the element type
* A {@code class} file structure that can be viewed as a composition of its
* member structures. {@code CompoundElement} allows users to traverse these
* member elements with {@link #forEach(Consumer)} or {@link #elementStream()},
* or buffer the elements obtained from the traversal through {@link
* #iterator()} or {@link #elementList()}.
* <p>
* Unless otherwise specified, all member elements of compatible type will be
* presented during the traversal if they exist in this element. Some member
* elements specify that they may appear at most once in this element; if such
* elements are presented multiple times, the latest occurrence is authentic and
* all previous occurrences should be ignored.
* <p>
* {@code CompoundElement}s can be constructed by {@link ClassFileBuilder}s.
* {@link ClassFileBuilder#transform(CompoundElement, ClassFileTransform)}
* provides an easy way to create a new structure by selectively processing
* the original member structures and directing the results to the builder.
*
* @param <E> the member element type
* @see ClassFileElement##membership Membership Elements
* @see ClassFileBuilder
* @sealedGraph
* @since 24
*/
@ -52,15 +64,16 @@ public sealed interface CompoundElement<E extends ClassFileElement>
extends ClassFileElement, Iterable<E>
permits ClassModel, CodeModel, FieldModel, MethodModel, jdk.internal.classfile.impl.AbstractUnboundModel {
/**
* Invoke the provided handler with each element contained in this
* compound element
* Invokes the provided handler with each member element in this compound
* element.
*
* @param consumer the handler
*/
@Override
void forEach(Consumer<? super E> consumer);
/**
* {@return an {@link Iterator} describing all the elements contained in this
* {@return an {@link Iterator} describing all member elements in this
* compound element}
*/
@Override
@ -69,8 +82,8 @@ public sealed interface CompoundElement<E extends ClassFileElement>
}
/**
* {@return a {@link Stream} containing all the elements contained in this
* compound element}
* {@return a {@link Stream} containing all member elements in this compound
* element}
*/
default Stream<E> elementStream() {
return StreamSupport.stream(Spliterators.spliteratorUnknownSize(
@ -80,8 +93,8 @@ public sealed interface CompoundElement<E extends ClassFileElement>
}
/**
* {@return an {@link List} containing all the elements contained in this
* compound element}
* {@return a {@link List} containing all member elements in this compound
* element}
*/
default List<E> elementList() {
List<E> list = new ArrayList<>();
@ -95,9 +108,11 @@ public sealed interface CompoundElement<E extends ClassFileElement>
}
/**
* {@return a text representation of the compound element and its contents for debugging purposes}
* {@return a text representation of the compound element and its contents
* for debugging purposes}
*
* The format, structure and exact contents of the returned string are not specified and may change at any time in the future.
* The format, structure and exact contents of the returned string are not
* specified and may change at any time in the future.
*/
default String toDebugString() {
StringBuilder text = new StringBuilder();

View file

@ -1,5 +1,5 @@
/*
* Copyright (c) 2022, 2024, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2022, 2025, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -25,7 +25,7 @@
package java.lang.classfile;
import java.lang.classfile.constantpool.Utf8Entry;
import java.lang.constant.ClassDesc;
import java.lang.reflect.AccessFlag;
import java.util.function.Consumer;
@ -34,14 +34,17 @@ import jdk.internal.classfile.impl.ChainedFieldBuilder;
import jdk.internal.classfile.impl.TerminalFieldBuilder;
/**
* A builder for fields. Builders are not created directly; they are passed
* to handlers by methods such as {@link ClassBuilder#withField(Utf8Entry, Utf8Entry, Consumer)}
* or to field transforms. The elements of a field can be specified
* abstractly (by passing a {@link FieldElement} to {@link #with(ClassFileElement)}
* or concretely by calling the various {@code withXxx} methods.
* A builder for fields. The main way to obtain a field builder is via {@link
* ClassBuilder#withField(String, ClassDesc, Consumer)}. The {@linkplain
* ClassBuilder#withField(String, ClassDesc, int) access flag overload} is
* useful if no attribute needs to be configured, skipping the handler.
* <p>
* Refer to {@link ClassFileBuilder} for general guidance and caution around
* the use of builders for structures in the {@code class} file format.
*
* @see ClassBuilder#withField(String, ClassDesc, Consumer)
* @see FieldModel
* @see FieldTransform
*
* @since 24
*/
public sealed interface FieldBuilder
@ -50,8 +53,12 @@ public sealed interface FieldBuilder
/**
* Sets the field access flags.
*
* @param flags the access flags, as a bit mask
* @return this builder
* @see AccessFlags
* @see AccessFlag.Location#FIELD
* @see ClassBuilder#withField(String, ClassDesc, int)
*/
default FieldBuilder withFlags(int flags) {
return with(new AccessFlagsImpl(AccessFlag.Location.FIELD, flags));
@ -59,8 +66,12 @@ public sealed interface FieldBuilder
/**
* Sets the field access flags.
*
* @param flags the access flags, as a bit mask
* @return this builder
* @see AccessFlags
* @see AccessFlag.Location#FIELD
* @see ClassBuilder#withField(String, ClassDesc, int)
*/
default FieldBuilder withFlags(AccessFlag... flags) {
return with(new AccessFlagsImpl(AccessFlag.Location.FIELD, flags));

View file

@ -1,5 +1,5 @@
/*
* Copyright (c) 2022, 2024, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2022, 2025, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -27,9 +27,18 @@ package java.lang.classfile;
import java.lang.classfile.attribute.*;
/**
* A marker interface for elements that can appear when traversing
* a {@link FieldModel} or be presented to a {@link FieldBuilder}.
* Marker interface for a member element of a {@link FieldModel}. Such an
* element can appear when traversing a {@link FieldModel} unless otherwise
* specified, be supplied to a {@link FieldBuilder}, and be processed by a
* {@link FieldTransform}.
* <p>
* {@link AccessFlags} is the only member element of a field that appear exactly
* once during the traversal of a {@link FieldModel}.
*
* @see ClassFileElement##membership Membership Elements
* @see ClassElement
* @see MethodElement
* @see CodeElement
* @sealedGraph
* @since 24
*/

View file

@ -1,5 +1,5 @@
/*
* Copyright (c) 2022, 2024, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2022, 2025, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -27,24 +27,43 @@ package java.lang.classfile;
import java.lang.classfile.constantpool.Utf8Entry;
import java.lang.constant.ClassDesc;
import java.lang.reflect.AccessFlag;
import java.util.Optional;
import java.util.function.Consumer;
import jdk.internal.classfile.impl.BufferedFieldBuilder;
import jdk.internal.classfile.impl.FieldImpl;
import jdk.internal.classfile.impl.Util;
/**
* Models a field. The contents of the field can be traversed via
* a streaming view, or via random access (e.g.,
* {@link #flags()}), or by freely mixing the two.
* Models a field. A field can be viewed as a {@linkplain CompoundElement
* composition} of {@link FieldElement}s, or by random access via accessor
* methods if only specific parts of the field is needed.
* <p>
* Fields can be obtained from {@link ClassModel#fields()}, or in the traversal
* of member elements of a class.
* <p>
* {@link ClassBuilder#withField(String, ClassDesc, Consumer)} is the main way
* to construct fields. {@link ClassBuilder#transformField} allows creating a
* new field by selectively processing the original field elements and directing
* the results to a field builder.
* <p>
* All field attributes are accessible as member elements.
*
* @see ClassModel#fields()
* @see FieldTransform
* @jvms 4.5 Fields
* @since 24
*/
public sealed interface FieldModel
extends CompoundElement<FieldElement>, AttributedElement, ClassElement
permits BufferedFieldBuilder.Model, FieldImpl {
/** {@return the access flags} */
/**
* {@return the access flags}
*
* @see AccessFlag.Location#FIELD
*/
AccessFlags flags();
/** {@return the class model this field is a member of, if known} */
@ -53,10 +72,10 @@ public sealed interface FieldModel
/** {@return the name of this field} */
Utf8Entry fieldName();
/** {@return the field descriptor of this field} */
/** {@return the field descriptor string of this field} */
Utf8Entry fieldType();
/** {@return the field descriptor of this field, as a symbolic descriptor} */
/** {@return the field type, as a symbolic descriptor} */
default ClassDesc fieldTypeSymbol() {
return Util.fieldTypeSymbol(fieldType());
}

View file

@ -1,5 +1,5 @@
/*
* Copyright (c) 2022, 2024, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2022, 2025, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -34,9 +34,17 @@ import static java.util.Objects.requireNonNull;
/**
* A transformation on streams of {@link FieldElement}.
* <p>
* Refer to {@link ClassFileTransform} for general guidance and caution around
* the use of transforms for structures in the {@code class} file format.
* <p>
* A field transform can be lifted to a class transform via {@link
* ClassTransform#transformingFields(FieldTransform)}, transforming only
* the {@link FieldModel} among the class members and passing all other elements
* to the builders.
*
* @see ClassFileTransform
*
* @see FieldModel
* @see ClassBuilder#transformField
* @since 24
*/
@FunctionalInterface
@ -44,7 +52,7 @@ public non-sealed interface FieldTransform
extends ClassFileTransform<FieldTransform, FieldElement, FieldBuilder> {
/**
* A field transform that sends all elements to the builder.
* A field transform that passes all elements to the builder.
*/
FieldTransform ACCEPT_ALL = new FieldTransform() {
@Override
@ -54,7 +62,7 @@ public non-sealed interface FieldTransform
};
/**
* Create a stateful field transform from a {@link Supplier}. The supplier
* Creates a stateful field transform from a {@link Supplier}. The supplier
* will be invoked for each transformation.
*
* @param supplier a {@link Supplier} that produces a fresh transform object
@ -66,7 +74,7 @@ public non-sealed interface FieldTransform
}
/**
* Create a field transform that passes each element through to the builder,
* Creates a field transform that passes each element through to the builder,
* and calls the specified function when transformation is complete.
*
* @param finisher the function to call when transformation is complete
@ -88,7 +96,7 @@ public non-sealed interface FieldTransform
}
/**
* Create a field transform that passes each element through to the builder,
* Creates a field transform that passes each element through to the builder,
* except for those that the supplied {@link Predicate} is true for.
*
* @param filter the predicate that determines which elements to drop

View file

@ -1,5 +1,5 @@
/*
* Copyright (c) 2022, 2024, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2022, 2025, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -32,12 +32,15 @@ import jdk.internal.classfile.impl.AbstractInstruction;
/**
* Models an executable instruction in the {@code code} array of the {@link
* CodeAttribute Code} attribute of a method.
* CodeAttribute Code} attribute of a method. The order of instructions in
* a {@link CodeModel} is significant.
* <p>
* The {@link #opcode() opcode} identifies the operation of an instruction.
* Each {@linkplain Opcode#kind() kind} of opcode has its own modeling interface
* for instructions.
*
* @see Opcode
* @jvms 6.5 Instructions
* @sealedGraph
* @since 24
*/

View file

@ -1,5 +1,5 @@
/*
* Copyright (c) 2022, 2024, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2022, 2025, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -33,16 +33,22 @@ import jdk.internal.classfile.impl.InterfacesImpl;
import jdk.internal.classfile.impl.Util;
/**
* Models the interfaces of a class. Delivered as a {@link
* java.lang.classfile.ClassElement} when traversing a {@link ClassModel}.
* Models the interfaces (JVMS {@jvms 4.1}) of a class. An {@code Interfaces}
* appears at most once in a {@link ClassModel}: if it does not appear, the
* class has no interfaces, which is equivalent to an {@code Interfaces} whose
* {@link #interfaces()} returns an empty list. A {@link ClassBuilder} sets
* the interfaces to an empty list if the interfaces is not supplied.
*
* @see ClassModel#interfaces()
* @see ClassBuilder#withInterfaces
* @jvms 4.1 The {@code ClassFile} Structure
* @since 24
*/
public sealed interface Interfaces
extends ClassElement
permits InterfacesImpl {
/** {@return the interfaces of this class} */
/** {@return the interfaces of this class, may be empty} */
List<ClassEntry> interfaces();
/**
@ -64,6 +70,7 @@ public sealed interface Interfaces
/**
* {@return an {@linkplain Interfaces} element}
* @param interfaces the interfaces
* @throws IllegalArgumentException if any of {@code interfaces} is primitive
*/
static Interfaces ofSymbols(List<ClassDesc> interfaces) {
return of(Util.entryList(interfaces));
@ -72,6 +79,7 @@ public sealed interface Interfaces
/**
* {@return an {@linkplain Interfaces} element}
* @param interfaces the interfaces
* @throws IllegalArgumentException if any of {@code interfaces} is primitive
*/
static Interfaces ofSymbols(ClassDesc... interfaces) {
return ofSymbols(Arrays.asList(interfaces));

View file

@ -1,5 +1,5 @@
/*
* Copyright (c) 2022, 2024, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2022, 2025, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -25,7 +25,7 @@
package java.lang.classfile;
import java.lang.classfile.constantpool.Utf8Entry;
import java.lang.constant.MethodTypeDesc;
import java.lang.reflect.AccessFlag;
import java.util.function.Consumer;
@ -34,14 +34,18 @@ import jdk.internal.classfile.impl.ChainedMethodBuilder;
import jdk.internal.classfile.impl.TerminalMethodBuilder;
/**
* A builder for methods. Builders are not created directly; they are passed
* to handlers by methods such as {@link ClassBuilder#withMethod(Utf8Entry, Utf8Entry, int, Consumer)}
* or to method transforms. The elements of a method can be specified
* abstractly (by passing a {@link MethodElement} to {@link #with(ClassFileElement)}
* or concretely by calling the various {@code withXxx} methods.
* A builder for methods. The main way to obtain a method builder is via {@link
* ClassBuilder#withMethod(String, MethodTypeDesc, int, Consumer)}. {@link
* ClassBuilder#withMethodBody(String, MethodTypeDesc, int, Consumer)} is
* useful if no attribute on the method except {@link CodeModel Code} needs to
* be configured, skipping the method handler.
* <p>
* Refer to {@link ClassFileBuilder} for general guidance and caution around
* the use of builders for structures in the {@code class} file format.
*
* @see MethodModel
* @see MethodTransform
*
* @jvms 4.6 Methods
* @since 24
*/
public sealed interface MethodBuilder
@ -49,18 +53,30 @@ public sealed interface MethodBuilder
permits ChainedMethodBuilder, TerminalMethodBuilder {
/**
* Sets the method access flags.
* Sets the method access flags. The {@link AccessFlag#STATIC} flag cannot
* be modified after the builder is created.
*
* @param flags the access flags, as a bit mask
* @return this builder
* @throws IllegalArgumentException if the {@link ClassFile#ACC_STATIC
* ACC_STATIC} flag is modified
* @see AccessFlags
* @see AccessFlag.Location#METHOD
*/
default MethodBuilder withFlags(int flags) {
return with(new AccessFlagsImpl(AccessFlag.Location.METHOD, flags));
}
/**
* Sets the method access flags.
* Sets the method access flags. The {@link AccessFlag#STATIC} flag cannot
* be modified after the builder is created.
*
* @param flags the access flags, as a bit mask
* @return this builder
* @throws IllegalArgumentException if the {@link ClassFile#ACC_STATIC
* ACC_STATIC} flag is modified
* @see AccessFlags
* @see AccessFlag.Location#METHOD
*/
default MethodBuilder withFlags(AccessFlag... flags) {
return with(new AccessFlagsImpl(AccessFlag.Location.METHOD, flags));
@ -68,24 +84,26 @@ public sealed interface MethodBuilder
/**
* Build the method body for this method.
*
* @param code a handler receiving a {@link CodeBuilder}
* @return this builder
* @see CodeModel
*/
MethodBuilder withCode(Consumer<? super CodeBuilder> code);
/**
* Build the method body for this method by transforming the body of another
* method.
*
* @implNote
* <p>This method behaves as if:
* <p>
* This method behaves as if:
* {@snippet lang=java :
* withCode(b -> b.transformCode(code, transform));
* withCode(cob -> cob.transform(code, transform));
* }
*
* @param code the method body to be transformed
* @param transform the transform to apply to the method body
* @return this builder
* @see CodeTransform
*/
MethodBuilder transformCode(CodeModel code, CodeTransform transform);
}

View file

@ -1,5 +1,5 @@
/*
* Copyright (c) 2022, 2024, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2022, 2025, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -27,9 +27,18 @@ package java.lang.classfile;
import java.lang.classfile.attribute.*;
/**
* A marker interface for elements that can appear when traversing
* a {@link MethodModel} or be presented to a {@link MethodBuilder}.
* Marker interface for a member element of a {@link MethodModel}. Such an
* element can appear when traversing a {@link MethodModel} unless otherwise
* specified, be supplied to a {@link MethodBuilder}, and be processed by a
* {@link MethodTransform}.
* <p>
* {@link AccessFlags} is the only member element of a method that appear
* exactly once during the traversal of a {@link MethodModel}.
*
* @see ClassFileElement##membership Membership Elements
* @see ClassElement
* @see FieldElement
* @see CodeElement
* @sealedGraph
* @since 24
*/

View file

@ -1,5 +1,5 @@
/*
* Copyright (c) 2022, 2024, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2022, 2025, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -27,24 +27,43 @@ package java.lang.classfile;
import java.lang.classfile.constantpool.Utf8Entry;
import java.lang.constant.MethodTypeDesc;
import java.lang.reflect.AccessFlag;
import java.util.Optional;
import java.util.function.Consumer;
import jdk.internal.classfile.impl.BufferedMethodBuilder;
import jdk.internal.classfile.impl.MethodImpl;
import jdk.internal.classfile.impl.Util;
/**
* Models a method. The contents of the method can be traversed via
* a streaming view, or via random access (e.g.,
* {@link #flags()}), or by freely mixing the two.
* Models a method. A method can be viewed as a {@linkplain CompoundElement
* composition} of {@link MethodElement}s, or by random access via accessor
* methods if only specific parts of the method is needed.
* <p>
* Methods can be obtained from {@link ClassModel#methods()}, or in the
* traversal of member elements of a class.
* <p>
* {@link ClassBuilder#withMethod(String, MethodTypeDesc, int, Consumer)} is the
* main way to construct methods. {@link ClassBuilder#transformMethod} allows
* creating a new method by selectively processing the original method elements
* and directing the results to a method builder.
* <p>
* All method attributes are accessible as member elements.
*
* @see ClassModel#methods()
* @see MethodTransform
* @jvms 4.6 Methods
* @since 24
*/
public sealed interface MethodModel
extends CompoundElement<MethodElement>, AttributedElement, ClassElement
permits BufferedMethodBuilder.Model, MethodImpl {
/** {@return the access flags} */
/**
* {@return the access flags}
*
* @see AccessFlag.Location#METHOD
*/
AccessFlags flags();
/** {@return the class model this method is a member of, if known} */
@ -53,10 +72,10 @@ public sealed interface MethodModel
/** {@return the name of this method} */
Utf8Entry methodName();
/** {@return the method descriptor of this method} */
/** {@return the method descriptor string of this method} */
Utf8Entry methodType();
/** {@return the method descriptor of this method, as a symbolic descriptor} */
/** {@return the method type, as a symbolic descriptor} */
default MethodTypeDesc methodTypeSymbol() {
return Util.methodTypeSymbol(methodType());
}

View file

@ -1,5 +1,5 @@
/*
* Copyright (c) 2022, 2024, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2022, 2025, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -34,9 +34,17 @@ import static java.util.Objects.requireNonNull;
/**
* A transformation on streams of {@link MethodElement}.
* <p>
* Refer to {@link ClassFileTransform} for general guidance and caution around
* the use of transforms for structures in the {@code class} file format.
* <p>
* A method transform can be lifted to a class transform via {@link
* ClassTransform#transformingMethods(MethodTransform)}, transforming only
* the {@link MethodModel} among the class members and passing all other
* elements to the builders.
*
* @see ClassFileTransform
*
* @see MethodModel
* @see ClassBuilder#transformMethod
* @since 24
*/
@FunctionalInterface
@ -44,7 +52,7 @@ public non-sealed interface MethodTransform
extends ClassFileTransform<MethodTransform, MethodElement, MethodBuilder> {
/**
* A method transform that sends all elements to the builder.
* A method transform that passes all elements to the builder.
*/
MethodTransform ACCEPT_ALL = new MethodTransform() {
@Override
@ -54,7 +62,7 @@ public non-sealed interface MethodTransform
};
/**
* Create a stateful method transform from a {@link Supplier}. The supplier
* Creates a stateful method transform from a {@link Supplier}. The supplier
* will be invoked for each transformation.
*
* @param supplier a {@link Supplier} that produces a fresh transform object
@ -67,7 +75,7 @@ public non-sealed interface MethodTransform
}
/**
* Create a method transform that passes each element through to the builder,
* Creates a method transform that passes each element through to the builder,
* and calls the specified function when transformation is complete.
*
* @param finisher the function to call when transformation is complete
@ -89,7 +97,7 @@ public non-sealed interface MethodTransform
}
/**
* Create a method transform that passes each element through to the builder,
* Creates a method transform that passes each element through to the builder,
* except for those that the supplied {@link Predicate} is true for.
*
* @param filter the predicate that determines which elements to drop
@ -104,8 +112,9 @@ public non-sealed interface MethodTransform
}
/**
* Create a method transform that transforms {@link CodeModel} elements
* with the supplied code transform.
* Creates a method transform that transforms {@link CodeModel} elements
* with the supplied code transform, passing every other element through to
* the builder.
*
* @param xform the method transform
* @return the class transform

View file

@ -1,5 +1,5 @@
/*
* Copyright (c) 2022, 2024, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2022, 2025, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -42,7 +42,7 @@ import jdk.internal.classfile.impl.RawBytecodeHelper;
* instead of wide pseudo-opcodes.
*
* @see Instruction
*
* @jvms 6.5 Instructions
* @since 24
*/
public enum Opcode {
@ -1143,7 +1143,7 @@ public enum Opcode {
LXOR(RawBytecodeHelper.LXOR, 1, Kind.OPERATOR),
/**
* Increment local variable by constant.
* Increment {@link TypeKind#INT int} local variable by constant.
*
* @jvms 6.5.iinc <em>iinc</em>
* @see Kind#INCREMENT

View file

@ -1,5 +1,5 @@
/*
* Copyright (c) 2022, 2024, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2022, 2025, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -35,13 +35,16 @@ import java.lang.classfile.instruction.LocalVariableType;
import jdk.internal.classfile.impl.AbstractPseudoInstruction;
/**
* Models metadata about a {@link CodeAttribute}, such as entries in the
* exception table, line number table, local variable table, or the mapping
* between instructions and labels. Pseudo-instructions are delivered as part
* of the element stream of a {@link CodeModel}. Delivery of some
* pseudo-instructions can be disabled by modifying the value of classfile
* options (e.g., {@link ClassFile.DebugElementsOption}).
* Models metadata about a {@link CodeModel}, derived from the {@link
* CodeAttribute Code} attribute itself or its attributes.
* <p>
* Order is significant for some pseudo-instructions relative to {@link
* Instruction}s, such as {@link LabelTarget} or {@link LineNumber}. Some
* pseudo-instructions can be omitted in reading and writing according to
* certain {@link ClassFile.Option}s. These are specified in the corresponding
* modeling interfaces.
*
* @sealedGraph
* @since 24
*/
public sealed interface PseudoInstruction

View file

@ -1,5 +1,5 @@
/*
* Copyright (c) 2022, 2024, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2022, 2025, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -25,13 +25,24 @@
package java.lang.classfile;
import java.lang.classfile.constantpool.ClassEntry;
import java.lang.constant.ClassDesc;
import jdk.internal.classfile.impl.SuperclassImpl;
/**
* Models the superclass of a class. Delivered as a {@link
* java.lang.classfile.ClassElement} when traversing a {@link ClassModel}.
* Models the superclass (JVMS {@jvms 4.1}) of a class. A {@code Superclass}
* appears at most once in a {@link ClassModel}: it must be absent for
* {@linkplain ClassModel#isModuleInfo() module descriptors} or the {@link
* Object} class, and must be present otherwise. A {@link ClassBuilder} sets
* the {@link Object} class as the superclass if the superclass is not supplied
* and the class to build is required to have a superclass.
* <p>
* All {@linkplain ClassFile#ACC_INTERFACE interfaces} have {@link Object} as
* their superclass.
*
* @see ClassModel#superclass()
* @see ClassBuilder#withSuperclass
* @jvms 4.1 The {@code ClassFile} Structure
* @since 24
*/
public sealed interface Superclass
@ -43,6 +54,7 @@ public sealed interface Superclass
/**
* {@return a {@linkplain Superclass} element}
*
* @param superclassEntry the superclass
*/
static Superclass of(ClassEntry superclassEntry) {

View file

@ -1,5 +1,5 @@
/*
* Copyright (c) 2022, 2024, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2022, 2025, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -108,11 +108,16 @@ public enum TypeKind {
*/
LONG(2, 11),
/**
* The primitive type {@code float}.
* The primitive type {@code float}. All NaN values of {@code float} may or
* may not be collapsed into a single {@linkplain Float#NaN "canonical" NaN
* value} in loading and storing.
*/
FLOAT(1, 6),
/**
* The primitive type {@code double}. It is of {@linkplain #slotSize() category} 2.
* The primitive type {@code double}. It is of {@linkplain #slotSize()
* category} 2. All NaN values of {@code double} may or may not be
* collapsed into a single {@linkplain Double#NaN "canonical" NaN value}
* in loading and storing.
*/
DOUBLE(2, 7),
// End primitive types

View file

@ -49,6 +49,7 @@ import jdk.internal.classfile.impl.BoundAttribute;
* being built.
*
* @see Attributes#code()
* @see CodeModel
* @jvms 4.7.3 The {@code Code} Attribute
* @since 24
*/

View file

@ -68,7 +68,8 @@ public sealed interface InnerClassInfo
/**
* {@return a bit mask of flags denoting access permissions and properties
* of the inner class}
* of the inner class} It is in the range of unsigned short, {@code [0,
* 0xFFFF]}.
*
* @see Class#getModifiers()
* @see AccessFlag.Location#INNER_CLASS

View file

@ -53,7 +53,8 @@ public sealed interface MethodParameterInfo
Optional<Utf8Entry> name();
/**
* {@return the access flags, as a bit mask}
* {@return the access flags, as a bit mask} It is in the range of unsigned
* short, {@code [0, 0xFFFF]}.
*
* @see Parameter#getModifiers()
* @see AccessFlag.Location#METHOD_PARAMETER

View file

@ -81,7 +81,8 @@ public sealed interface ModuleAttribute
ModuleEntry moduleName();
/**
* {@return the module flags of the module, as a bit mask}
* {@return the module flags of the module, as a bit mask} It is in the
* range of unsigned short, {@code [0, 0xFFFF]}.
*
* @see ModuleDescriptor#modifiers()
* @see AccessFlag.Location#MODULE

View file

@ -58,6 +58,7 @@ public sealed interface ModuleExportInfo
/**
* {@return the flags associated with this export declaration, as a bit mask}
* It is in the range of unsigned short, {@code [0, 0xFFFF]}.
*
* @see ModuleDescriptor.Exports#modifiers()
* @see AccessFlag.Location#MODULE_EXPORTS

View file

@ -64,6 +64,7 @@ public sealed interface ModuleOpenInfo
/**
* {@return the flags associated with this open declaration, as a bit mask}
* It is in the range of unsigned short, {@code [0, 0xFFFF]}.
*
* @see ModuleDescriptor.Opens#modifiers()
* @see AccessFlag.Location#MODULE_OPENS

View file

@ -55,6 +55,7 @@ public sealed interface ModuleRequireInfo
/**
* {@return the flags associated with this require declaration, as a bit mask}
* It is in the range of unsigned short, {@code [0, 0xFFFF]}.
*
* @see ModuleDescriptor.Requires#modifiers()
* @see AccessFlag.Location#MODULE_REQUIRES

View file

@ -78,7 +78,8 @@ public sealed interface ModuleResolutionAttribute
permits BoundAttribute.BoundModuleResolutionAttribute, UnboundAttribute.UnboundModuleResolutionAttribute {
/**
* {@return the module resolution flags}
* {@return the module resolution flags} It is in the range of unsigned
* short, {@code [0, 0xFFFF]}.
* <p>
* The value of the resolution_flags item is a mask of flags used to denote
* properties of module resolution. The flags are as follows:

View file

@ -467,6 +467,9 @@ public sealed interface ConstantPoolBuilder
/**
* {@return a {@link FloatEntry} describing the provided value}
* <p>
* All NaN values of the {@code float} may or may not be collapsed into a
* single {@linkplain Float#NaN "canonical" NaN value}.
*
* @param value the value
* @see FloatEntry#floatValue() FloatEntry::floatValue
@ -483,6 +486,9 @@ public sealed interface ConstantPoolBuilder
/**
* {@return a {@link DoubleEntry} describing the provided value}
* <p>
* All NaN values of the {@code double} may or may not be collapsed into a
* single {@linkplain Double#NaN "canonical" NaN value}.
*
* @param value the value
* @see DoubleEntry#doubleValue() DoubleEntry::doubleValue

View file

@ -1,5 +1,5 @@
/*
* Copyright (c) 2022, 2024, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2022, 2025, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -54,6 +54,7 @@ import jdk.internal.classfile.impl.AbstractPseudoInstruction;
* }
*
* @see CodeBuilder#exceptionCatch CodeBuilder::exceptionCatch
* @see CodeAttribute#exceptionHandlers()
* @jvms 4.7.3 The {@code Code} Attribute
* @since 24
*/

View file

@ -1,5 +1,5 @@
/*
* Copyright (c) 2022, 2024, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2022, 2025, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -25,14 +25,16 @@
/**
* <h2>Provides classfile parsing, generation, and transformation library.</h2>
* The {@code java.lang.classfile} package contains classes for reading, writing, and
* modifying Java class files, as specified in Chapter {@jvms 4} of the
* <cite>Java Virtual Machine Specification</cite>.
* The {@code java.lang.classfile} package contains API models for reading,
* writing, and modifying Java class files, as specified in Chapter {@jvms 4} of
* the <cite>Java Virtual Machine Specification</cite>. This package, {@link
* java.lang.classfile.attribute}, {@link java.lang.classfile.constantpool},
* and {@link java.lang.classfile.instruction} form the Class-File API.
*
* <h2>Reading classfiles</h2>
* The main class for reading classfiles is {@link java.lang.classfile.ClassModel}; we
* convert bytes into a {@link java.lang.classfile.ClassModel} with {@link
* java.lang.classfile.ClassFile#parse(byte[])}:
* The main class for reading classfiles is {@link ClassModel}; we
* convert bytes into a {@link ClassModel} with {@link
* ClassFile#parse(byte[])}:
*
* {@snippet lang=java :
* ClassModel cm = ClassFile.of().parse(bytes);
@ -41,29 +43,32 @@
* There are several additional overloads of {@code parse} that let you specify
* various processing options.
* <p>
* A {@link java.lang.classfile.ClassModel} is an immutable description of a class
* A {@link ClassModel} is an immutable description of a class
* file. It provides accessor methods to get at class metadata (e.g., {@link
* java.lang.classfile.ClassModel#thisClass()}, {@link java.lang.classfile.ClassModel#flags()}),
* as well as subordinate classfile entities ({@link java.lang.classfile.ClassModel#fields()},
* {@link java.lang.classfile.ClassModel#attributes()}). A {@link
* java.lang.classfile.ClassModel} is inflated lazily; most parts of the classfile are
* not parsed until they are actually needed.
* ClassModel#thisClass()}, {@link ClassModel#flags()}),
* as well as subordinate classfile entities ({@link ClassModel#fields()},
* {@link ClassModel#attributes()}). A {@link
* ClassModel} is inflated lazily; most parts of the classfile are
* not parsed until they are actually needed. Due to the laziness, these models
* may not be thread safe. Additionally, invocations to accessor methods on
* models may lead to {@link IllegalArgumentException} due to malformed {@code
* class} file format, as parsing happens lazily.
* <p>
* We can enumerate the names of the fields and methods in a class by:
* {@snippet lang="java" class="PackageSnippets" region="enumerateFieldsMethods1"}
* <p>
* When we enumerate the methods, we get a {@link java.lang.classfile.MethodModel} for each method; like a
* When we enumerate the methods, we get a {@link MethodModel} for each method; like a
* {@code ClassModel}, it gives us access to method metadata and
* the ability to descend into subordinate entities such as the bytecodes of the
* method body. In this way, a {@code ClassModel} is the root of a
* tree, with children for fields, methods, and attributes, and {@code MethodModel} in
* turn has its own children (attributes, {@code CodeModel}, etc.)
* <p>
* Methods like {@link java.lang.classfile.ClassModel#methods} allows us to traverse the class structure
* Methods like {@link ClassModel#methods} allows us to traverse the class structure
* explicitly, going straight to the parts we are interested in. This is useful
* for certain kinds of analysis, but if we wanted to process the whole
* classfile, we may want something more organized. A {@link
* java.lang.classfile.ClassModel} also provides us with a view of the classfile as a
* ClassModel} also provides us with a view of the classfile as a
* series of class <em>elements</em>, which may include methods, fields, attributes,
* and more, and which can be distinguished with pattern matching. We could
* rewrite the above example as:
@ -87,24 +92,24 @@
* <em>models</em> and <em>elements</em>. Models represent complex structures,
* such as classes, methods, fields, record elements, or the code body of a
* method. Models can be explored either via random-access navigation (such as
* the {@link java.lang.classfile.ClassModel#methods()} accessor) or as a linear
* the {@link ClassModel#methods()} accessor) or as a linear
* sequence of <em>elements</em>. (Elements can in turn also be models; a {@link
* java.lang.classfile.FieldModel} is also an element of a class.) For each model type
* (e.g., {@link java.lang.classfile.MethodModel}), there is a corresponding element
* type ({@link java.lang.classfile.MethodElement}). Models and elements are immutable
* FieldModel} is also an element of a class.) For each model type
* (e.g., {@link MethodModel}), there is a corresponding element
* type ({@link MethodElement}). Models and elements are immutable
* and are inflated lazily so creating a model does not necessarily require
* processing its entire content.
*
* <h3>The constant pool</h3>
* Much of the interesting content in a classfile lives in the <em>constant
* pool</em>. {@link java.lang.classfile.ClassModel} provides a lazily-inflated,
* read-only view of the constant pool via {@link java.lang.classfile.ClassModel#constantPool()}.
* pool</em>. {@link ClassModel} provides a lazily-inflated,
* read-only view of the constant pool via {@link ClassModel#constantPool()}.
* Descriptions of classfile content is often exposed in the form of various
* subtypes of {@link java.lang.classfile.constantpool.PoolEntry}, such as {@link
* java.lang.classfile.constantpool.ClassEntry} or {@link java.lang.classfile.constantpool.Utf8Entry}.
* subtypes of {@link PoolEntry}, such as {@link
* ClassEntry} or {@link Utf8Entry}.
* <p>
* Constant pool entries are also exposed through models and elements; in the
* above traversal example, the {@link java.lang.classfile.instruction.InvokeInstruction}
* above traversal example, the {@link InvokeInstruction}
* element exposed a method for {@code owner} that corresponds to a {@code
* Constant_Class_info} entry in the constant pool.
*
@ -112,9 +117,9 @@
* Much of the contents of a classfile is stored in attributes; attributes are
* found on classes, methods, fields, record components, and on the {@code Code}
* attribute. Most attributes are surfaced as elements; for example, {@link
* java.lang.classfile.attribute.SignatureAttribute} is a {@link
* java.lang.classfile.ClassElement}, {@link java.lang.classfile.MethodElement}, and {@link
* java.lang.classfile.FieldElement} since it can appear in all of those places, and is
* SignatureAttribute} is a {@link
* ClassElement}, {@link MethodElement}, and {@link
* FieldElement} since it can appear in all of those places, and is
* included when iterating the elements of the corresponding model.
* <p>
* Some attributes are not surfaced as elements; these are attributes that are
@ -125,77 +130,84 @@
* treated as part of the structure they are coupled to (the entries of the
* {@code BootstrapMethods} attribute are treated as part of the constant pool;
* line numbers and local variable metadata are modeled as elements of {@link
* java.lang.classfile.CodeModel}.)
* CodeModel}.)
* <p>
* The {@code Code} attribute, in addition to being modeled as a {@link
* java.lang.classfile.MethodElement}, is also a model in its own right ({@link
* java.lang.classfile.CodeModel}) due to its complex structure.
* MethodElement}, is also a model in its own right ({@link
* CodeModel}) due to its complex structure.
* <p>
* Each standard attribute has an interface (in {@code java.lang.classfile.attribute})
* which exposes the contents of the attribute and provides factories to
* construct the attribute. For example, the {@code Signature} attribute is
* defined by the {@link java.lang.classfile.attribute.SignatureAttribute} class, and
* provides accessors for {@link java.lang.classfile.attribute.SignatureAttribute#signature()}
* as well as factories taking {@link java.lang.classfile.constantpool.Utf8Entry} or
* {@link java.lang.String}.
* defined by the {@link SignatureAttribute} class, and
* provides accessors for {@link SignatureAttribute#signature()}
* as well as factories taking {@link Utf8Entry} or
* {@link String}.
*
* <h3>Custom attributes</h3>
* Attributes are converted between their classfile form and their corresponding
* object form via an {@link java.lang.classfile.AttributeMapper}. An {@code
* object form via an {@link AttributeMapper}. An {@code
* AttributeMapper} provides the
* {@link java.lang.classfile.AttributeMapper#readAttribute(AttributedElement,
* {@link AttributeMapper#readAttribute(AttributedElement,
* ClassReader, int)} method for mapping from the classfile format
* to an attribute instance, and the
* {@link java.lang.classfile.AttributeMapper#writeAttribute(java.lang.classfile.BufWriter,
* java.lang.classfile.Attribute)} method for mapping back to the classfile format. It also
* {@link AttributeMapper#writeAttribute(BufWriter,
* Attribute)} method for mapping back to the classfile format. It also
* contains metadata including the attribute name, the set of classfile entities
* where the attribute is applicable, and whether multiple attributes of the
* same kind are allowed on a single entity.
* <p>
* There are built-in attribute mappers (in {@link java.lang.classfile.Attributes}) for
* There are built-in attribute mappers (in {@link Attributes}) for
* each of the attribute types defined in section {@jvms 4.7} of <cite>The Java Virtual
* Machine Specification</cite>, as well as several common nonstandard attributes used by the
* JDK such as {@code CharacterRangeTable}.
* <p>
* Unrecognized attributes are delivered as elements of type {@link
* java.lang.classfile.attribute.UnknownAttribute}, which provide access only to the
* UnknownAttribute}, which provide access only to the
* {@code byte[]} contents of the attribute.
* <p>
* For nonstandard attributes, user-provided attribute mappers can be specified
* through the use of the {@link
* java.lang.classfile.ClassFile.AttributeMapperOption#of(java.util.function.Function)}}
* ClassFile.AttributeMapperOption#of(Function)}}
* classfile option. Implementations of custom attributes should extend {@link
* java.lang.classfile.CustomAttribute}.
* CustomAttribute}.
*
* <h3>Options</h3>
* <h3 id="options">Options</h3>
* <p>
* {@link java.lang.classfile.ClassFile#of(java.lang.classfile.ClassFile.Option[])}
* accepts a list of options. {@link java.lang.classfile.ClassFile.Option} is a base interface
* {@link ClassFile#of(ClassFile.Option[])}
* accepts a list of options. {@link ClassFile.Option} is a base interface
* for some statically enumerated options, as well as factories for more complex options,
* including:
* <ul>
* <li>{@link java.lang.classfile.ClassFile.AttributeMapperOption#of(java.util.function.Function)}
* <li>{@link ClassFile.AttributeMapperOption#of(Function)}
* -- specify format of custom attributes</li>
* <li>{@link java.lang.classfile.ClassFile.AttributesProcessingOption}
* <li>{@link ClassFile.AttributesProcessingOption}
* -- unrecognized or problematic original attributes (default is {@code PASS_ALL_ATTRIBUTES})</li>
* <li>{@link java.lang.classfile.ClassFile.ClassHierarchyResolverOption#of(java.lang.classfile.ClassHierarchyResolver)}
* <li>{@link ClassFile.ClassHierarchyResolverOption#of(ClassHierarchyResolver)}
* -- specify a custom class hierarchy resolver used by stack map generation</li>
* <li>{@link java.lang.classfile.ClassFile.ConstantPoolSharingOption}}
* <li>{@link ClassFile.ConstantPoolSharingOption}}
* -- share constant pool when transforming (default is {@code SHARED_POOL})</li>
* <li>{@link java.lang.classfile.ClassFile.DeadCodeOption}}
* <li>{@link ClassFile.DeadCodeOption}}
* -- patch out unreachable code (default is {@code PATCH_DEAD_CODE})</li>
* <li>{@link java.lang.classfile.ClassFile.DeadLabelsOption}}
* <li>{@link ClassFile.DeadLabelsOption}}
* -- filter unresolved labels (default is {@code FAIL_ON_DEAD_LABELS})</li>
* <li>{@link java.lang.classfile.ClassFile.DebugElementsOption}
* <li>{@link ClassFile.DebugElementsOption}
* -- processing of debug information, such as local variable metadata (default is {@code PASS_DEBUG}) </li>
* <li>{@link java.lang.classfile.ClassFile.LineNumbersOption}
* <li>{@link ClassFile.LineNumbersOption}
* -- processing of line numbers (default is {@code PASS_LINE_NUMBERS}) </li>
* <li>{@link java.lang.classfile.ClassFile.ShortJumpsOption}
* <li>{@link ClassFile.ShortJumpsOption}
* -- automatically rewrite short jumps to long when necessary (default is {@code FIX_SHORT_JUMPS})</li>
* <li>{@link java.lang.classfile.ClassFile.StackMapsOption}
* <li>{@link ClassFile.StackMapsOption}
* -- generate stackmaps (default is {@code STACK_MAPS_WHEN_REQUIRED})</li>
* </ul>
* <p>
* {@link ClassFile.AttributeMapperOption} and {@link ClassFile.ClassHierarchyResolverOption}
* are critical to the correctness of {@code class} file parsing and generation.
* The attribute mapper is required to parse custom attributes. A correct
* resolver is required to generate {@code class} files that refer to classes
* not available to the system class loader in its bytecode, or in corner cases,
* when generation wishes to avoid loading system classes, such as in agents.
* <p>
* Most options allow you to request that certain parts of the classfile be
* skipped during traversal, such as debug information or unrecognized
* attributes. Some options allow you to suppress generation of portions of the
@ -207,8 +219,8 @@
* <h2>Writing classfiles</h2>
* ClassFile generation is accomplished through <em>builders</em>. For each
* entity type that has a model, there is also a corresponding builder type;
* classes are built through {@link java.lang.classfile.ClassBuilder}, methods through
* {@link java.lang.classfile.MethodBuilder}, etc.
* classes are built through {@link ClassBuilder}, methods through
* {@link MethodBuilder}, etc.
* <p>
* Rather than creating builders directly, builders are provided as an argument
* to a user-provided lambda. To generate the familiar "hello world" program,
@ -226,34 +238,34 @@
* Builders often support multiple ways of expressing the same entity at
* different levels of abstraction. For example, the {@code invokevirtual}
* instruction invoking {@code println} could have been generated with {@link
* java.lang.classfile.CodeBuilder#invokevirtual(java.lang.constant.ClassDesc,
* java.lang.String, java.lang.constant.MethodTypeDesc) CodeBuilder.invokevirtual}, {@link
* java.lang.classfile.CodeBuilder#invoke(java.lang.classfile.Opcode,
* java.lang.constant.ClassDesc, java.lang.String, java.lang.constant.MethodTypeDesc,
* boolean) CodeBuilder.invokeInstruction}, or {@link
* java.lang.classfile.CodeBuilder#with(java.lang.classfile.ClassFileElement)
* CodeBuilder#invokevirtual(ClassDesc,
* String, MethodTypeDesc) CodeBuilder.invokevirtual}, {@link
* CodeBuilder#invoke(Opcode,
* ClassDesc, String, MethodTypeDesc,
* boolean) CodeBuilder.invoke}, or {@link
* CodeBuilder#with(ClassFileElement)
* CodeBuilder.with}.
* <p>
* The convenience method {@code CodeBuilder.invokevirtual} behaves as if it calls
* the convenience method {@code CodeBuilder.invokeInstruction}, which in turn behaves
* the convenience method {@code CodeBuilder.invoke}, which in turn behaves
* as if it calls method {@code CodeBuilder.with}. This composing of method calls on the
* builder enables the composing of transforms (as described later).
* <p>
* 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
* java.lang.NullPointerException NullPointerException} to be thrown. Additionally,
* 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. </p>
*
* <h3>Symbolic information</h3>
* To describe symbolic information for classes and types, the API uses the
* nominal descriptor abstractions from {@code java.lang.constant} such as {@link
* java.lang.constant.ClassDesc} and {@link java.lang.constant.MethodTypeDesc},
* nominal descriptor abstractions from {@link java.lang.constant} such as {@link
* ClassDesc} and {@link MethodTypeDesc},
* which is less error-prone than using raw strings.
* <p>
* If a constant pool entry has a nominal representation then it provides a
* method returning the corresponding nominal descriptor type e.g.
* method {@link java.lang.classfile.constantpool.ClassEntry#asSymbol} returns
* method {@link ClassEntry#asSymbol} returns
* {@code ClassDesc}.
* <p>
* Where appropriate builders provide two methods for building an element with
@ -266,13 +278,14 @@
* methods accepts the provided information without implicit validation.
* However, fatal inconsistencies (like for example invalid code sequence or
* unresolved labels) affects internal tools and may cause exceptions later in
* the classfile building process.
* the classfile building process. These fatal exceptions are thrown as
* {@link IllegalArgumentException}.
* <p>
* Using nominal descriptors assures the right serial form is applied by the
* ClassFile API library based on the actual context. Also these nominal
* descriptors are validated during their construction, so it is not possible to
* create them with invalid content by mistake. Following example pass class
* name to the {@link java.lang.constant.ClassDesc#of} method for validation
* name to the {@link ClassDesc#of} method for validation
* and the library performs automatic conversion to the right internal form of
* the class name when serialized in the constant pool as a class entry.
* {@snippet lang=java :
@ -290,7 +303,7 @@
* }
* <p>
* More complex verification of a classfile can be achieved by invocation of
* {@link java.lang.classfile.ClassFile#verify}.
* {@link ClassFile#verify}.
*
* <h2>Transforming classfiles</h2>
* ClassFile Processing APIs are most frequently used to combine reading and
@ -301,9 +314,9 @@
* to the builder.
* <p>
* If we wanted to strip out methods whose names starts with "debug", we could
* get an existing {@link java.lang.classfile.ClassModel}, build a new classfile that
* provides a {@link java.lang.classfile.ClassBuilder}, iterate the elements of the
* original {@link java.lang.classfile.ClassModel}, and pass through all of them to
* get an existing {@link ClassModel}, build a new classfile that
* provides a {@link ClassBuilder}, iterate the elements of the
* original {@link ClassModel}, and pass through all of them to
* the builder except the methods we want to drop:
* {@snippet lang="java" class="PackageSnippets" region="stripDebugMethods1"}
* <p>
@ -335,7 +348,7 @@
* operations can be more easily combined. Suppose we want to redirect
* invocations of static methods on {@code Foo} to the corresponding method on
* {@code Bar} instead. We could express this as a transformation on {@link
* java.lang.classfile.CodeElement}:
* CodeElement}:
* {@snippet lang="java" class="PackageSnippets" region="fooToBarTransform"}
* <p>
* We can then <em>lift</em> this transformation on code elements into a
@ -376,7 +389,7 @@
* {@snippet lang="java" class="PackageSnippets" region="instrumentCallsTransform"}
* <p>
* Then we can compose {@code fooToBar} and {@code instrumentCalls} with {@link
* java.lang.classfile.CodeTransform#andThen(java.lang.classfile.CodeTransform)}:
* CodeTransform#andThen(CodeTransform)}:
*
* {@snippet lang=java :
* var cc = ClassFile.of();
@ -399,7 +412,7 @@
* attributes that are not transformed can be processed by bulk-copying their
* bytes, rather than parsing them and regenerating their contents.) If
* constant pool sharing is not desired it can be suppressed
* with the {@link java.lang.classfile.ClassFile.ConstantPoolSharingOption} option.
* with the {@link ClassFile.ConstantPoolSharingOption} option.
* Such suppression may be beneficial when transformation removes many elements,
* resulting in many unreferenced constant pool entries.
*
@ -429,14 +442,14 @@
* corresponding interface to describe that element, and factory methods to
* create that element. Some element kinds also have convenience methods on the
* corresponding builder (e.g., {@link
* java.lang.classfile.CodeBuilder#invokevirtual(java.lang.constant.ClassDesc,
* java.lang.String, java.lang.constant.MethodTypeDesc)}).
* CodeBuilder#invokevirtual(ClassDesc,
* String, MethodTypeDesc)}).
* <p>
* Most symbolic information in elements is represented by constant pool entries
* (for example, the owner of a field is represented by a {@link
* java.lang.classfile.constantpool.ClassEntry}.) Factories and builders also
* accept nominal descriptors from {@code java.lang.constant} (e.g., {@link
* java.lang.constant.ClassDesc}.)
* ClassEntry}.) Factories and builders also
* accept nominal descriptors from {@link java.lang.constant} (e.g., {@link
* ClassDesc}.)
*
* <h2><a id="data_model"></a>Data model</h2>
* We define each kind of element by its name, an optional arity indicator (zero
@ -485,7 +498,7 @@
*
* Fields and methods are models with their own elements. The elements of fields
* and methods are fairly simple; most of the complexity of methods lives in the
* {@link java.lang.classfile.CodeModel} (which models the {@code Code} attribute
* {@link CodeModel} (which models the {@code Code} attribute
* along with the code-related attributes: stack map table, local variable table,
* line number table, etc.)
*
@ -502,7 +515,7 @@
* | ExceptionsAttribute?(List<ClassEntry> exceptions)
* }
*
* {@link java.lang.classfile.CodeModel} is unique in that its elements are <em>ordered</em>.
* {@link CodeModel} is unique in that its elements are <em>ordered</em>.
* Elements of {@code Code} include ordinary bytecodes, as well as a number of pseudo-instructions
* representing branch targets, line number metadata, local variable metadata, and
* catch blocks.
@ -549,3 +562,13 @@
* @since 24
*/
package java.lang.classfile;
import java.lang.classfile.attribute.SignatureAttribute;
import java.lang.classfile.attribute.UnknownAttribute;
import java.lang.classfile.constantpool.ClassEntry;
import java.lang.classfile.constantpool.PoolEntry;
import java.lang.classfile.constantpool.Utf8Entry;
import java.lang.classfile.instruction.InvokeInstruction;
import java.lang.constant.ClassDesc;
import java.lang.constant.MethodTypeDesc;
import java.util.function.Function;

View file

@ -1,5 +1,5 @@
/*
* Copyright (c) 2022, 2024, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2022, 2025, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -25,6 +25,7 @@
package java.lang.classfile.snippets;
import java.lang.classfile.*;
import java.lang.classfile.attribute.CodeAttribute;
import java.lang.classfile.instruction.*;
import java.lang.constant.ClassDesc;
import java.lang.constant.ConstantDescs;
@ -185,10 +186,14 @@ class PackageSnippets {
// @start region="fooToBarTransform"
CodeTransform fooToBar = (b, e) -> {
if (e instanceof InvokeInstruction i
&& i.owner().asInternalName().equals("Foo")
&& i.opcode() == Opcode.INVOKESTATIC)
b.invoke(i.opcode(), CD_Bar, i.name().stringValue(), i.typeSymbol(), i.isInterface());
else b.with(e);
&& i.owner().name().equalsString("Foo")
&& i.opcode() == Opcode.INVOKESTATIC) {
// remove the old element i by doing nothing to the builder
// add a new invokestatic instruction to the builder
b.invokestatic(CD_Bar, i.name().stringValue(), i.typeSymbol(), i.isInterface());
} else {
b.with(e); // leaves the element in place
}
};
// @end
}
@ -324,4 +329,12 @@ class PackageSnippets {
ClassHierarchyResolver resolver = ClassHierarchyResolver.ofClassLoading(lookup).cached();
// @end
}
void manualReuseStackMaps(CodeBuilder cob, MethodModel method) {
// @start region="manual-reuse-stack-maps"
CodeAttribute code = method.findAttribute(Attributes.code()).orElseThrow();
// Note that StackMapTable may be absent, representing code with no branching
code.findAttribute(Attributes.stackMapTable()).ifPresent(cob);
// @end
}
}