mirror of
https://github.com/openjdk/jdk.git
synced 2025-08-26 06:14:49 +02:00
8342465: Improve API documentation for java.lang.classfile
Reviewed-by: asotona, darcy
This commit is contained in:
parent
7d6055a786
commit
1d8ccb8920
44 changed files with 2932 additions and 1014 deletions
|
@ -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();
|
||||
}
|
||||
|
|
|
@ -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
|
||||
*/
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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
|
||||
*/
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -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")
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -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
|
||||
*/
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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));
|
||||
|
|
|
@ -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
|
||||
*/
|
||||
|
|
|
@ -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());
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
*/
|
||||
|
|
|
@ -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));
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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
|
||||
*/
|
||||
|
|
|
@ -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());
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
*/
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
*/
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue