8312491: Update Classfile API snippets and examples

Reviewed-by: jlahoda
This commit is contained in:
Adam Sotona 2023-09-05 08:48:39 +00:00
parent 69c9ec92d0
commit 744b3970f9
62 changed files with 3384 additions and 83 deletions

View File

@ -72,6 +72,7 @@ import jdk.internal.classfile.impl.UnboundAttribute;
* corresponding model type. Additionally, all attributes are accessible
* directly from the corresponding model type through {@link
* AttributedElement#findAttribute(AttributeMapper)}.
* @param <A> the attribute type
*/
public sealed interface Attribute<A extends Attribute<A>>
extends WritableElement<A>

View File

@ -33,6 +33,7 @@ package jdk.internal.classfile;
* attributes, clients can define their own {@linkplain AttributeMapper}.
* Classes that model nonstandard attributes should extend {@link
* CustomAttribute}.
* @param <A> the attribute type
*/
public interface AttributeMapper<A> {

View File

@ -91,41 +91,113 @@ import jdk.internal.classfile.impl.StackMapDecoder;
* @see AttributeMapper
*/
public class Attributes {
/** AnnotationDefault */
public static final String NAME_ANNOTATION_DEFAULT = "AnnotationDefault";
/** BootstrapMethods */
public static final String NAME_BOOTSTRAP_METHODS = "BootstrapMethods";
/** CharacterRangeTable */
public static final String NAME_CHARACTER_RANGE_TABLE = "CharacterRangeTable";
/** Code */
public static final String NAME_CODE = "Code";
/** CompilationID */
public static final String NAME_COMPILATION_ID = "CompilationID";
/** ConstantValue */
public static final String NAME_CONSTANT_VALUE = "ConstantValue";
/** Deprecated */
public static final String NAME_DEPRECATED = "Deprecated";
/** EnclosingMethod */
public static final String NAME_ENCLOSING_METHOD = "EnclosingMethod";
/** Exceptions */
public static final String NAME_EXCEPTIONS = "Exceptions";
/** InnerClasses */
public static final String NAME_INNER_CLASSES = "InnerClasses";
/** LineNumberTable */
public static final String NAME_LINE_NUMBER_TABLE = "LineNumberTable";
/** LocalVariableTable */
public static final String NAME_LOCAL_VARIABLE_TABLE = "LocalVariableTable";
/** LocalVariableTypeTable */
public static final String NAME_LOCAL_VARIABLE_TYPE_TABLE = "LocalVariableTypeTable";
/** MethodParameters */
public static final String NAME_METHOD_PARAMETERS = "MethodParameters";
/** Module */
public static final String NAME_MODULE = "Module";
/** ModuleHashes */
public static final String NAME_MODULE_HASHES = "ModuleHashes";
/** ModuleMainClass */
public static final String NAME_MODULE_MAIN_CLASS = "ModuleMainClass";
/** ModulePackages */
public static final String NAME_MODULE_PACKAGES = "ModulePackages";
/** ModuleResolution */
public static final String NAME_MODULE_RESOLUTION = "ModuleResolution";
/** ModuleTarget */
public static final String NAME_MODULE_TARGET = "ModuleTarget";
/** NestHost */
public static final String NAME_NEST_HOST = "NestHost";
/** NestMembers */
public static final String NAME_NEST_MEMBERS = "NestMembers";
/** PermittedSubclasses */
public static final String NAME_PERMITTED_SUBCLASSES = "PermittedSubclasses";
/** Record */
public static final String NAME_RECORD = "Record";
/** RuntimeInvisibleAnnotations */
public static final String NAME_RUNTIME_INVISIBLE_ANNOTATIONS = "RuntimeInvisibleAnnotations";
/** RuntimeInvisibleTypeAnnotations */
public static final String NAME_RUNTIME_INVISIBLE_PARAMETER_ANNOTATIONS = "RuntimeInvisibleParameterAnnotations";
/** */
public static final String NAME_RUNTIME_INVISIBLE_TYPE_ANNOTATIONS = "RuntimeInvisibleTypeAnnotations";
/** RuntimeVisibleAnnotations */
public static final String NAME_RUNTIME_VISIBLE_ANNOTATIONS = "RuntimeVisibleAnnotations";
/** RuntimeVisibleParameterAnnotations */
public static final String NAME_RUNTIME_VISIBLE_PARAMETER_ANNOTATIONS = "RuntimeVisibleParameterAnnotations";
/** RuntimeVisibleTypeAnnotations */
public static final String NAME_RUNTIME_VISIBLE_TYPE_ANNOTATIONS = "RuntimeVisibleTypeAnnotations";
/** Signature */
public static final String NAME_SIGNATURE = "Signature";
/** SourceDebugExtension */
public static final String NAME_SOURCE_DEBUG_EXTENSION = "SourceDebugExtension";
/** SourceFile */
public static final String NAME_SOURCE_FILE = "SourceFile";
/** SourceID */
public static final String NAME_SOURCE_ID = "SourceID";
/** StackMapTable */
public static final String NAME_STACK_MAP_TABLE = "StackMapTable";
/** Synthetic */
public static final String NAME_SYNTHETIC = "Synthetic";
private Attributes() {
@ -712,7 +784,7 @@ public class Attributes {
/** Attribute mapper for the {@code Synthetic} attribute */
public static final AttributeMapper<SyntheticAttribute>
SYNTHETIC = new AbstractAttributeMapper<>(NAME_SYNTHETIC) {
SYNTHETIC = new AbstractAttributeMapper<>(NAME_SYNTHETIC, true) {
@Override
public SyntheticAttribute readAttribute(AttributedElement e, ClassReader cf, int p) {
return new BoundAttribute.BoundSyntheticAttribute(cf, this, p);

View File

@ -48,8 +48,8 @@ import static java.lang.constant.ConstantDescs.CD_Object;
public interface ClassHierarchyResolver {
/**
* Returns a default instance of {@linkplain ClassHierarchyResolver} that
* gets {@link ClassHierarchyInfo} from system class loader with reflection.
* {@return the default instance of {@linkplain ClassHierarchyResolver} that
* gets {@link ClassHierarchyInfo} from system class loader with reflection}
*/
static ClassHierarchyResolver defaultResolver() {
return ClassHierarchyImpl.DEFAULT_RESOLVER;

View File

@ -38,6 +38,8 @@ import jdk.internal.classfile.constantpool.ConstantPoolBuilder;
* abstractly (by passing a {@link ClassfileElement} to {@link #with(ClassfileElement)}
* or concretely by calling the various {@code withXxx} methods.
*
* @param <E> the element type
* @param <B> the builder type
* @see ClassfileTransform
*/
public sealed interface ClassfileBuilder<E extends ClassfileElement, B extends ClassfileBuilder<E, B>>

View File

@ -68,6 +68,9 @@ import jdk.internal.classfile.attribute.RuntimeVisibleAnnotationsAttribute;
* <p>
* Complex class instrumentation sample chaining multiple transformations:
* {@snippet lang="java" class="PackageSnippets" region="classInstrumentation"}
* @param <C> the transform type
* @param <E> the element type
* @param <B> the builder type
*/
public sealed interface ClassfileTransform<
C extends ClassfileTransform<C, E, B>,

View File

@ -40,6 +40,7 @@ import java.util.stream.StreamSupport;
* 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 #elements()}, {@link #forEachElement(Consumer)}, etc.)
* @param <E> the element type
*/
public sealed interface CompoundElement<E extends ClassfileElement>
extends ClassfileElement, Iterable<E>

View File

@ -31,6 +31,7 @@ import jdk.internal.classfile.impl.UnboundAttribute;
* this class to provide an implementation class for non-standard attributes,
* and provide an {@link AttributeMapper} to mediate between the classfile
* format and the {@linkplain CustomAttribute} representation.
* @param <T> the custom attribute type
*/
@SuppressWarnings("exports")
public abstract non-sealed class CustomAttribute<T extends CustomAttribute<T>>

View File

@ -176,7 +176,26 @@ public sealed interface Signature {
* an upper bound, or a lower bound
*/
public enum WildcardIndicator {
DEFAULT, UNBOUNDED, EXTENDS, SUPER;
/**
* default bound wildcard (empty)
*/
DEFAULT,
/**
* unbounded indicator {@code *}
*/
UNBOUNDED,
/**
* upper-bounded indicator {@code +}
*/
EXTENDS,
/**
* lower-bounded indicator {@code -}
*/
SUPER;
}
/** {@return the wildcard indicator} */

View File

@ -59,7 +59,7 @@ import static jdk.internal.classfile.Classfile.TAT_THROWS;
import jdk.internal.classfile.impl.TemporaryConstantPool;
/**
* Models an annotation on a type use.
* Models an annotation on a type use, as defined in {@jvms 4.7.19} and {@jvms 4.7.20}.
*
* @see RuntimeVisibleTypeAnnotationsAttribute
* @see RuntimeInvisibleTypeAnnotationsAttribute
@ -69,7 +69,7 @@ public sealed interface TypeAnnotation
permits UnboundAttribute.UnboundTypeAnnotation {
/**
* The kind of target on which the annotation appears.
* The kind of target on which the annotation appears, as defined in {@jvms 4.7.20.1}.
*/
public enum TargetType {
/** For annotations on a class type parameter declaration. */
@ -146,10 +146,16 @@ public sealed interface TypeAnnotation
this.sizeIfFixed = sizeIfFixed;
}
/**
* {@return the target type value}
*/
public int targetTypeValue() {
return targetTypeValue;
}
/**
* {@return the size of the target type if fixed or -1 if variable}
*/
public int sizeIfFixed() {
return sizeIfFixed;
}
@ -225,120 +231,269 @@ public sealed interface TypeAnnotation
*/
sealed interface TargetInfo {
/**
* {@return the type of the target}
*/
TargetType targetType();
/**
* {@return the size of the target info}
*/
default int size() {
return targetType().sizeIfFixed;
}
/**
* {@return a target for annotations on a class or method type parameter declaration}
* @param targetType {@link TargetType#CLASS_TYPE_PARAMETER} or {@link TargetType#METHOD_TYPE_PARAMETER}
* @param typeParameterIndex specifies which type parameter declaration is annotated
*/
static TypeParameterTarget ofTypeParameter(TargetType targetType, int typeParameterIndex) {
return new TargetInfoImpl.TypeParameterTargetImpl(targetType, typeParameterIndex);
}
/**
* {@return a target for annotations on a class type parameter declaration}
* @param typeParameterIndex specifies which type parameter declaration is annotated
*/
static TypeParameterTarget ofClassTypeParameter(int typeParameterIndex) {
return ofTypeParameter(TargetType.CLASS_TYPE_PARAMETER, typeParameterIndex);
}
/**
* {@return a target for annotations on a method type parameter declaration}
* @param typeParameterIndex specifies which type parameter declaration is annotated
*/
static TypeParameterTarget ofMethodTypeParameter(int typeParameterIndex) {
return ofTypeParameter(TargetType.METHOD_TYPE_PARAMETER, typeParameterIndex);
}
/**
* {@return a target for annotations on the type of an "extends" or "implements" clause}
* @param supertypeIndex the index into the interfaces array or 65535 to indicate it is the superclass
*/
static SupertypeTarget ofClassExtends(int supertypeIndex) {
return new TargetInfoImpl.SupertypeTargetImpl(supertypeIndex);
}
/**
* {@return a target for annotations on the i'th bound of the j'th type parameter declaration of
* a generic class, interface, method, or constructor}
* @param targetType {@link TargetType#CLASS_TYPE_PARAMETER_BOUND} or {@link TargetType#METHOD_TYPE_PARAMETER_BOUND}
* @param typeParameterIndex specifies which type parameter declaration is annotated
* @param boundIndex specifies which bound of the type parameter declaration is annotated
*/
static TypeParameterBoundTarget ofTypeParameterBound(TargetType targetType, int typeParameterIndex, int boundIndex) {
return new TargetInfoImpl.TypeParameterBoundTargetImpl(targetType, typeParameterIndex, boundIndex);
}
/**
* {@return a target for annotations on the i'th bound of the j'th type parameter declaration of
* a generic class, or interface}
* @param typeParameterIndex specifies which type parameter declaration is annotated
* @param boundIndex specifies which bound of the type parameter declaration is annotated
*/
static TypeParameterBoundTarget ofClassTypeParameterBound(int typeParameterIndex, int boundIndex) {
return ofTypeParameterBound(TargetType.CLASS_TYPE_PARAMETER_BOUND, typeParameterIndex, boundIndex);
}
/**
* {@return a target for annotations on the i'th bound of the j'th type parameter declaration of
* a generic method, or constructor}
* @param typeParameterIndex specifies which type parameter declaration is annotated
* @param boundIndex specifies which bound of the type parameter declaration is annotated
*/
static TypeParameterBoundTarget ofMethodTypeParameterBound(int typeParameterIndex, int boundIndex) {
return ofTypeParameterBound(TargetType.METHOD_TYPE_PARAMETER_BOUND, typeParameterIndex, boundIndex);
}
/**
* {@return a target for annotations}
* @param targetType {@link TargetType#FIELD}, {@link TargetType#METHOD_RETURN} or {@link TargetType#METHOD_RECEIVER}
*/
static EmptyTarget of(TargetType targetType) {
return new TargetInfoImpl.EmptyTargetImpl(targetType);
}
/**
* {@return a target for annotations on the type in a field or record declaration}
*/
static EmptyTarget ofField() {
return of(TargetType.FIELD);
}
/**
* {@return a target for annotations on the return type of a method or a newly constructed object}
*/
static EmptyTarget ofMethodReturn() {
return of(TargetType.METHOD_RETURN);
}
/**
* {@return a target for annotations on the receiver type of a method or constructor}
*/
static EmptyTarget ofMethodReceiver() {
return of(TargetType.METHOD_RECEIVER);
}
/**
* {@return a target for annotations on the type in a formal parameter declaration of a method,
* constructor, or lambda expression}
* @param formalParameterIndex specifies which formal parameter declaration has an annotated type
*/
static FormalParameterTarget ofMethodFormalParameter(int formalParameterIndex) {
return new TargetInfoImpl.FormalParameterTargetImpl(formalParameterIndex);
}
/**
* {@return a target for annotations on the i'th type in the throws clause of a method or
* constructor declaration}
* @param throwsTargetIndex the index into the exception table of the Exceptions attribute of the method
*/
static ThrowsTarget ofThrows(int throwsTargetIndex) {
return new TargetInfoImpl.ThrowsTargetImpl(throwsTargetIndex);
}
/**
* {@return a target for annotations on the type in a local variable declaration,
* including a variable declared as a resource in a try-with-resources statement}
* @param targetType {@link TargetType#LOCAL_VARIABLE} or {@link TargetType#RESOURCE_VARIABLE}
* @param table the list of local variable targets
*/
static LocalVarTarget ofVariable(TargetType targetType, List<LocalVarTargetInfo> table) {
return new TargetInfoImpl.LocalVarTargetImpl(targetType, table);
}
/**
* {@return a target for annotations on the type in a local variable declaration}
* @param table the list of local variable targets
*/
static LocalVarTarget ofLocalVariable(List<LocalVarTargetInfo> table) {
return ofVariable(TargetType.LOCAL_VARIABLE, table);
}
/**
* {@return a target for annotations on the type in a local variable declared
* as a resource in a try-with-resources statement}
* @param table the list of local variable targets
*/
static LocalVarTarget ofResourceVariable(List<LocalVarTargetInfo> table) {
return ofVariable(TargetType.RESOURCE_VARIABLE, table);
}
/**
* {@return a target for annotations on the i'th type in an exception parameter declaration}
* @param exceptionTableIndex the index into the exception table of the Code attribute
*/
static CatchTarget ofExceptionParameter(int exceptionTableIndex) {
return new TargetInfoImpl.CatchTargetImpl(exceptionTableIndex);
}
/**
* {@return a target for annotations on the type in an instanceof expression or a new expression,
* or the type before the :: in a method reference expression}
* {@param targetType {@link TargetType#INSTANCEOF}, {@link TargetType#NEW},
* {@link TargetType#CONSTRUCTOR_REFERENCE},
* or {@link TargetType#METHOD_REFERENCE}}
* @param target the code label corresponding to the instruction
*/
static OffsetTarget ofOffset(TargetType targetType, Label target) {
return new TargetInfoImpl.OffsetTargetImpl(targetType, target);
}
/**
* {@return a target for annotations on the type in an instanceof expression}
* @param target the code label corresponding to the instruction
*/
static OffsetTarget ofInstanceofExpr(Label target) {
return ofOffset(TargetType.INSTANCEOF, target);
}
/**
* {@return a target for annotations on the type in a new expression}
* @param target the code label corresponding to the instruction
*/
static OffsetTarget ofNewExpr(Label target) {
return ofOffset(TargetType.NEW, target);
}
/**
* {@return a target for annotations on the type before the :: in a constructor reference expression}
* @param target the code label corresponding to the instruction
*/
static OffsetTarget ofConstructorReference(Label target) {
return ofOffset(TargetType.CONSTRUCTOR_REFERENCE, target);
}
/**
* {@return a target for annotations on the type before the :: in a method reference expression}
* @param target the code label corresponding to the instruction
*/
static OffsetTarget ofMethodReference(Label target) {
return ofOffset(TargetType.METHOD_REFERENCE, target);
}
/**
* {@return a target for annotations on the i'th type in a cast expression,
* or on the i'th type argument in the explicit type argument list for any of the following:
* a new expression, an explicit constructor invocation statement, a method invocation expression,
* or a method reference expression}
* {@param targetType {@link TargetType#CAST}, {@link TargetType#CONSTRUCTOR_INVOCATION_TYPE_ARGUMENT},
* {@link TargetType#METHOD_INVOCATION_TYPE_ARGUMENT},
* {@link TargetType#CONSTRUCTOR_REFERENCE_TYPE_ARGUMENT},
* or {@link TargetType#METHOD_REFERENCE_TYPE_ARGUMENT}}
* @param target the code label corresponding to the instruction
* @param typeArgumentIndex specifies which type in the cast operator or argument is annotated
*/
static TypeArgumentTarget ofTypeArgument(TargetType targetType, Label target, int typeArgumentIndex) {
return new TargetInfoImpl.TypeArgumentTargetImpl(targetType, target, typeArgumentIndex);
}
/**
* {@return a target for annotations on the i'th type in a cast expression}
* @param target the code label corresponding to the instruction
* @param typeArgumentIndex specifies which type in the cast operator is annotated
*/
static TypeArgumentTarget ofCastExpr(Label target, int typeArgumentIndex) {
return ofTypeArgument(TargetType.CAST, target, typeArgumentIndex);
}
/**
* {@return a target for annotations on the i'th type argument in the explicit type argument list for
* an explicit constructor invocation statement}
* @param target the code label corresponding to the instruction
* @param typeArgumentIndex specifies which type in the argument is annotated
*/
static TypeArgumentTarget ofConstructorInvocationTypeArgument(Label target, int typeArgumentIndex) {
return ofTypeArgument(TargetType.CONSTRUCTOR_INVOCATION_TYPE_ARGUMENT, target, typeArgumentIndex);
}
/**
* {@return a target for annotations on the i'th type argument in the explicit type argument list for
* a method invocation expression}
* @param target the code label corresponding to the instruction
* @param typeArgumentIndex specifies which type in the argument is annotated
*/
static TypeArgumentTarget ofMethodInvocationTypeArgument(Label target, int typeArgumentIndex) {
return ofTypeArgument(TargetType.METHOD_INVOCATION_TYPE_ARGUMENT, target, typeArgumentIndex);
}
/**
* {@return a target for annotations on the i'th type argument in the explicit type argument list for
* a new expression}
* @param target the code label corresponding to the instruction
* @param typeArgumentIndex specifies which type in the argument is annotated
*/
static TypeArgumentTarget ofConstructorReferenceTypeArgument(Label target, int typeArgumentIndex) {
return ofTypeArgument(TargetType.CONSTRUCTOR_REFERENCE_TYPE_ARGUMENT, target, typeArgumentIndex);
}
/**
* {@return a target for annotations on the i'th type argument in the explicit type argument list for
* a method reference expression}
* @param target the code label corresponding to the instruction
* @param typeArgumentIndex specifies which type in the argument is annotated
*/
static TypeArgumentTarget ofMethodReferenceTypeArgument(Label target, int typeArgumentIndex) {
return ofTypeArgument(TargetType.METHOD_REFERENCE_TYPE_ARGUMENT, target, typeArgumentIndex);
}
@ -441,7 +596,7 @@ public sealed interface TypeAnnotation
* Exceptions attribute of the method_info structure enclosing the
* RuntimeVisibleTypeAnnotations attribute.
*
* @return index into the list jdk.internal.classfile.attribute.ExceptionsAttribute.exceptions()
* @return the index into the list jdk.internal.classfile.attribute.ExceptionsAttribute.exceptions()
*/
int throwsTargetIndex();
}
@ -471,7 +626,7 @@ public sealed interface TypeAnnotation
* The given local variable has a value at indices into the code array in the interval
* [start_pc, start_pc + length), that is, between start_pc inclusive and start_pc + length exclusive.
*
* @return the start of the bytecode section.
* @return the start of the bytecode section
*/
Label startLabel();
@ -480,7 +635,7 @@ public sealed interface TypeAnnotation
* The given local variable has a value at indices into the code array in the interval
* [start_pc, start_pc + length), that is, between start_pc inclusive and start_pc + length exclusive.
*
* @return
* @return the end of the bytecode section
*/
Label endLabel();
@ -489,10 +644,16 @@ public sealed interface TypeAnnotation
*
* If the local variable at index is of type double or long, it occupies both index and index + 1.
*
* @return index into the local variables
* @return the index into the local variables
*/
int index();
/**
* {@return local variable target info}
* @param startLabel the code label indicating start of an interval where variable has value
* @param endLabel the code label indicating start of an interval where variable has value
* @param index index into the local variables
*/
static LocalVarTargetInfo of(Label startLabel, Label endLabel, int index) {
return new TargetInfoImpl.LocalVarTargetInfoImpl(startLabel, endLabel, index);
}
@ -526,7 +687,7 @@ public sealed interface TypeAnnotation
* corresponding to the instanceof expression, the new bytecode instruction corresponding to the new
* expression, or the bytecode instruction corresponding to the method reference expression.
*
* @return
* @return the code label corresponding to the instruction
*/
Label target();
}
@ -547,7 +708,7 @@ public sealed interface TypeAnnotation
* instruction corresponding to the method invocation expression, or the bytecode instruction corresponding to
* the method reference expression.
*
* @return
* @return the code label corresponding to the instruction
*/
Label target();
@ -567,31 +728,27 @@ public sealed interface TypeAnnotation
}
/**
* JVMS: Wherever a type is used in a declaration or expression, the type_path structure identifies which part of
* the type is annotated. An annotation may appear on the type itself, but if the type is a reference type, then
* there are additional locations where an annotation may appear:
*
* If an array type T[] is used in a declaration or expression, then an annotation may appear on any component type
* of the array type, including the element type.
*
* If a nested type T1.T2 is used in a declaration or expression, then an annotation may appear on the name of the
* innermost member type and any enclosing type for which a type annotation is admissible {@jls 9.7.4}.
*
* If a parameterized type {@literal T<A> or T<? extends A> or T<? super A>} is used in a declaration or expression, then an
* annotation may appear on any type argument or on the bound of any wildcard type argument.
*
* JVMS: ... each entry in the path array represents an iterative, left-to-right step towards the precise location
* of the annotation in an array type, nested type, or parameterized type. (In an array type, the iteration visits
* the array type itself, then its component type, then the component type of that component type, and so on,
* until the element type is reached.)
* JVMS: Type_path structure identifies which part of the type is annotated,
* as defined in {@jvms 4.7.20.2}
*/
sealed interface TypePathComponent
permits UnboundAttribute.TypePathComponentImpl {
/**
* Type path kind, as defined in {@jvms 4.7.20.2}
*/
public enum Kind {
/** Annotation is deeper in an array type */
ARRAY(0),
/** Annotation is deeper in a nested type */
INNER_TYPE(1),
/** Annotation is on the bound of a wildcard type argument of a parameterized type */
WILDCARD(2),
/** Annotation is on a type argument of a parameterized type */
TYPE_ARGUMENT(3);
private final int tag;
@ -600,13 +757,21 @@ public sealed interface TypeAnnotation
this.tag = tag;
}
/**
* {@return the type path kind value}
*/
public int tag() {
return tag;
}
}
/** static instance for annotation is deeper in an array type */
TypePathComponent ARRAY = new UnboundAttribute.TypePathComponentImpl(Kind.ARRAY, 0);
/** static instance for annotation is deeper in a nested type */
TypePathComponent INNER_TYPE = new UnboundAttribute.TypePathComponentImpl(Kind.INNER_TYPE, 0);
/** static instance for annotation is on the bound of a wildcard type argument of a parameterized type */
TypePathComponent WILDCARD = new UnboundAttribute.TypePathComponentImpl(Kind.WILDCARD, 0);
@ -629,6 +794,11 @@ public sealed interface TypeAnnotation
*/
int typeArgumentIndex();
/**
* {@return type path component of an annotation}
* @param typePathKind the kind of path element
* @param typeArgumentIndex the type argument index
*/
static TypePathComponent of(Kind typePathKind, int typeArgumentIndex) {
return switch (typePathKind) {

View File

@ -37,6 +37,10 @@ import jdk.internal.classfile.impl.UnboundAttribute;
* appear on methods of annotation types, and records the default value
* {@jls 9.6.2} for the element corresponding to this method. Delivered as a
* {@link MethodElement} when traversing the elements of a {@link MethodModel}.
* <p>
* The attribute does not permit multiple instances in a given location.
* Subsequent occurrence of the attribute takes precedence during the attributed
* element build or transformation.
*/
public sealed interface AnnotationDefaultAttribute
extends Attribute<AnnotationDefaultAttribute>, MethodElement

View File

@ -37,6 +37,10 @@ import jdk.internal.classfile.impl.UnboundAttribute;
* Models the {@code BootstrapMethods} attribute {@jvms 4.7.23}, which serves as
* an extension to the constant pool of a classfile. Elements of the bootstrap
* method table are accessed through {@link ConstantPool}.
* <p>
* The attribute does not permit multiple instances in a given location.
* Subsequent occurrence of the attribute takes precedence during the attributed
* element build or transformation.
*/
public sealed interface BootstrapMethodsAttribute
extends Attribute<BootstrapMethodsAttribute>

View File

@ -54,6 +54,8 @@ import jdk.internal.classfile.impl.UnboundAttribute;
* several code index ranges, but there will be a smallest code index range, and
* for each kind of range in which it is enclosed there will be a smallest code
* index range. The character range entries may appear in any order.
* <p>
* The attribute permits multiple instances in a given location.
*/
public sealed interface CharacterRangeTableAttribute
extends Attribute<CharacterRangeTableAttribute>

View File

@ -35,6 +35,10 @@ import jdk.internal.classfile.impl.BoundAttribute;
* non-abstract methods and contains the bytecode of the method body. Delivered
* as a {@link jdk.internal.classfile.MethodElement} when traversing the elements of a
* {@link jdk.internal.classfile.MethodModel}.
* <p>
* The attribute does not permit multiple instances in a given location.
* Subsequent occurrence of the attribute takes precedence during the attributed
* element build or transformation.
*/
public sealed interface CodeAttribute extends Attribute<CodeAttribute>, CodeModel
permits BoundAttribute.BoundCodeAttribute {

View File

@ -37,6 +37,10 @@ import jdk.internal.classfile.impl.UnboundAttribute;
* appear on classes and records the compilation time of the class. Delivered
* as a {@link jdk.internal.classfile.ClassElement} when traversing the elements of
* a {@link jdk.internal.classfile.ClassModel}.
* <p>
* The attribute does not permit multiple instances in a given location.
* Subsequent occurrence of the attribute takes precedence during the attributed
* element build or transformation.
*/
public sealed interface CompilationIDAttribute
extends Attribute<CompilationIDAttribute>, ClassElement

View File

@ -37,6 +37,10 @@ import jdk.internal.classfile.impl.UnboundAttribute;
* fields and indicates that the field's value is a constant. Delivered as a
* {@link jdk.internal.classfile.FieldElement} when traversing the elements of a
* {@link jdk.internal.classfile.FieldModel}.
* <p>
* The attribute does not permit multiple instances in a given location.
* Subsequent occurrence of the attribute takes precedence during the attributed
* element build or transformation.
*/
public sealed interface ConstantValueAttribute
extends Attribute<ConstantValueAttribute>, FieldElement

View File

@ -36,6 +36,8 @@ import jdk.internal.classfile.impl.UnboundAttribute;
* classes, methods, and fields. Delivered as a {@link ClassElement},
* {@link MethodElement}, or {@link FieldElement} when traversing the elements
* of a corresponding model.
* <p>
* The attribute permits multiple instances in a given location.
*/
public sealed interface DeprecatedAttribute
extends Attribute<DeprecatedAttribute>,

View File

@ -43,6 +43,10 @@ import jdk.internal.classfile.impl.Util;
* on classes, and indicates that the class is a local or anonymous class.
* Delivered as a {@link ClassElement} when traversing the elements of a {@link
* jdk.internal.classfile.ClassModel}.
* <p>
* The attribute does not permit multiple instances in a given location.
* Subsequent occurrence of the attribute takes precedence during the attributed
* element build or transformation.
*/
public sealed interface EnclosingMethodAttribute
extends Attribute<EnclosingMethodAttribute>, ClassElement

View File

@ -40,6 +40,10 @@ import jdk.internal.classfile.impl.Util;
* methods, and records the exceptions declared to be thrown by this method.
* Delivered as a {@link MethodElement} when traversing the elements of a
* {@link jdk.internal.classfile.MethodModel}.
* <p>
* The attribute does not permit multiple instances in a given location.
* Subsequent occurrence of the attribute takes precedence during the attributed
* element build or transformation.
*/
public sealed interface ExceptionsAttribute
extends Attribute<ExceptionsAttribute>, MethodElement

View File

@ -37,6 +37,10 @@ import jdk.internal.classfile.impl.UnboundAttribute;
* appear on classes, and records which classes referenced by this classfile
* are inner classes. Delivered as a {@link jdk.internal.classfile.ClassElement} when
* traversing the elements of a {@link jdk.internal.classfile.ClassModel}.
* <p>
* The attribute does not permit multiple instances in a given location.
* Subsequent occurrence of the attribute takes precedence during the attributed
* element build or transformation.
*/
public sealed interface InnerClassesAttribute
extends Attribute<InnerClassesAttribute>, ClassElement

View File

@ -37,6 +37,8 @@ import jdk.internal.classfile.impl.UnboundAttribute;
* Delivered as a {@link jdk.internal.classfile.instruction.LineNumber} when traversing the
* elements of a {@link jdk.internal.classfile.CodeModel}, according to the setting of the
* {@link jdk.internal.classfile.Classfile.LineNumbersOption} option.
* <p>
* The attribute permits multiple instances in a given location.
*/
public sealed interface LineNumberTableAttribute
extends Attribute<LineNumberTableAttribute>

View File

@ -37,6 +37,8 @@ import java.util.List;
* Delivered as a {@link jdk.internal.classfile.instruction.LocalVariable} when traversing the
* elements of a {@link jdk.internal.classfile.CodeModel}, according to the setting of the
* {@link jdk.internal.classfile.Classfile.DebugElementsOption} option.
* <p>
* The attribute permits multiple instances in a given location.
*/
public sealed interface LocalVariableTableAttribute
extends Attribute<LocalVariableTableAttribute>

View File

@ -38,6 +38,8 @@ import java.util.List;
* Delivered as a {@link jdk.internal.classfile.instruction.LocalVariable} when traversing the
* elements of a {@link jdk.internal.classfile.CodeModel}, according to the setting of the
* {@link jdk.internal.classfile.Classfile.LineNumbersOption} option.
* <p>
* The attribute permits multiple instances in a given location.
*/
public sealed interface LocalVariableTypeTableAttribute
extends Attribute<LocalVariableTypeTableAttribute>

View File

@ -37,6 +37,10 @@ import jdk.internal.classfile.impl.UnboundAttribute;
* appear on methods, and records optional information about the method's
* parameters. Delivered as a {@link jdk.internal.classfile.MethodElement} when
* traversing the elements of a {@link jdk.internal.classfile.MethodModel}.
* <p>
* The attribute does not permit multiple instances in a given location.
* Subsequent occurrence of the attribute takes precedence during the attributed
* element build or transformation.
*/
public sealed interface MethodParametersAttribute
extends Attribute<MethodParametersAttribute>, MethodElement

View File

@ -49,6 +49,10 @@ import jdk.internal.classfile.impl.Util;
* appear on classes that represent module descriptors.
* Delivered as a {@link jdk.internal.classfile.ClassElement} when
* traversing the elements of a {@link jdk.internal.classfile.ClassModel}.
* <p>
* The attribute does not permit multiple instances in a given location.
* Subsequent occurrence of the attribute takes precedence during the attributed
* element build or transformation.
*/
public sealed interface ModuleAttribute
@ -72,12 +76,17 @@ public sealed interface ModuleAttribute
return AccessFlag.maskToAccessFlags(moduleFlagsMask(), AccessFlag.Location.MODULE);
}
/**
* Tests presence of module flag
* @param flag the module flag
* @return true if the flag is set
*/
default boolean has(AccessFlag flag) {
return Util.has(AccessFlag.Location.MODULE, moduleFlagsMask(), flag);
}
/**
* {@return version of the module, if present}
* {@return the version of the module, if present}
*/
Optional<Utf8Entry> moduleVersion();
@ -155,40 +164,156 @@ public sealed interface ModuleAttribute
return mb.build();
}
/**
* A builder for module attributes.
*/
public sealed interface ModuleAttributeBuilder
permits ModuleAttributeBuilderImpl {
/**
* Sets the module name
* @param moduleName the module name
* @return this builder
*/
ModuleAttributeBuilder moduleName(ModuleDesc moduleName);
/**
* Sets the module flags
* @param flagsMask the module flags
* @return this builder
*/
ModuleAttributeBuilder moduleFlags(int flagsMask);
/**
* Sets the module flags
* @param moduleFlags the module flags
* @return this builder
*/
default ModuleAttributeBuilder moduleFlags(AccessFlag... moduleFlags) {
return moduleFlags(Util.flagsToBits(AccessFlag.Location.MODULE, moduleFlags));
}
/**
* Sets the module flags
* @param version the module version
* @return this builder
*/
ModuleAttributeBuilder moduleVersion(String version);
/**
* Adds module requirement
* @param module the required module
* @param requiresFlagsMask the requires flags
* @param version the required module version
* @return this builder
*/
ModuleAttributeBuilder requires(ModuleDesc module, int requiresFlagsMask, String version);
/**
* Adds module requirement
* @param module the required module
* @param requiresFlags the requires flags
* @param version the required module version
* @return this builder
*/
default ModuleAttributeBuilder requires(ModuleDesc module, Collection<AccessFlag> requiresFlags, String version) {
return requires(module, Util.flagsToBits(AccessFlag.Location.MODULE_REQUIRES, requiresFlags), version);
}
/**
* Adds module requirement
* @param requires the module require info
* @return this builder
*/
ModuleAttributeBuilder requires(ModuleRequireInfo requires);
/**
* Adds exported package
* @param pkge the exported package
* @param exportsFlagsMask the export flags
* @param exportsToModules the modules to export to
* @return this builder
*/
ModuleAttributeBuilder exports(PackageDesc pkge, int exportsFlagsMask, ModuleDesc... exportsToModules);
/**
* Adds exported package
* @param pkge the exported package
* @param exportsFlags the export flags
* @param exportsToModules the modules to export to
* @return this builder
*/
default ModuleAttributeBuilder exports(PackageDesc pkge, Collection<AccessFlag> exportsFlags, ModuleDesc... exportsToModules) {
return exports(pkge, Util.flagsToBits(AccessFlag.Location.MODULE_EXPORTS, exportsFlags), exportsToModules);
}
/**
* Adds exported package
* @param exports the module export info
* @return this builder
*/
ModuleAttributeBuilder exports(ModuleExportInfo exports);
/**
*
* @param pkge the opened package
* @param opensFlagsMask the open package flags
* @param opensToModules the modules to open to
* @return this builder
*/
ModuleAttributeBuilder opens(PackageDesc pkge, int opensFlagsMask, ModuleDesc... opensToModules);
/**
*
* @param pkge the opened package
* @param opensFlags the open package flags
* @param opensToModules the modules to open to
* @return this builder
*/
default ModuleAttributeBuilder opens(PackageDesc pkge, Collection<AccessFlag> opensFlags, ModuleDesc... opensToModules) {
return opens(pkge, Util.flagsToBits(AccessFlag.Location.MODULE_OPENS, opensFlags), opensToModules);
}
/**
* Opens package
* @param opens the module open info
* @return this builder
*/
ModuleAttributeBuilder opens(ModuleOpenInfo opens);
/**
* Declares use of a service
* @param service the service class used
* @return this builder
*/
ModuleAttributeBuilder uses(ClassDesc service);
/**
* Declares use of a service
* @param uses the service class used
* @return this builder
*/
ModuleAttributeBuilder uses(ClassEntry uses);
/**
* Declares provision of a service
* @param service the service class provided
* @param implClasses the implementation classes
* @return this builder
*/
ModuleAttributeBuilder provides(ClassDesc service, ClassDesc... implClasses);
/**
* Declares provision of a service
* @param provides the module provides info
* @return this builder
*/
ModuleAttributeBuilder provides(ModuleProvideInfo provides);
/**
* Builds module attribute.
* @return the module attribute
*/
ModuleAttribute build();
}
}

View File

@ -63,6 +63,10 @@ import jdk.internal.classfile.impl.UnboundAttribute;
*
* }
* } </pre>
* <p>
* The attribute does not permit multiple instances in a given location.
* Subsequent occurrence of the attribute takes precedence during the attributed
* element build or transformation.
*/
public sealed interface ModuleHashesAttribute
extends Attribute<ModuleHashesAttribute>, ClassElement

View File

@ -38,6 +38,10 @@ import jdk.internal.classfile.impl.UnboundAttribute;
* appear on classes that represent module descriptors.
* Delivered as a {@link jdk.internal.classfile.ClassElement} when
* traversing the elements of a {@link jdk.internal.classfile.ClassModel}.
* <p>
* The attribute does not permit multiple instances in a given location.
* Subsequent occurrence of the attribute takes precedence during the attributed
* element build or transformation.
*/
public sealed interface ModuleMainClassAttribute
extends Attribute<ModuleMainClassAttribute>, ClassElement

View File

@ -56,6 +56,9 @@ public sealed interface ModuleOpenInfo
*/
int opensFlagsMask();
/**
* {@return the access flags}
*/
default Set<AccessFlag> opensFlags() {
return AccessFlag.maskToAccessFlags(opensFlagsMask(), AccessFlag.Location.MODULE_OPENS);
}

View File

@ -41,6 +41,10 @@ import jdk.internal.classfile.impl.UnboundAttribute;
* appear on classes that represent module descriptors.
* Delivered as a {@link jdk.internal.classfile.ClassElement} when
* traversing the elements of a {@link jdk.internal.classfile.ClassModel}.
* <p>
* The attribute does not permit multiple instances in a given location.
* Subsequent occurrence of the attribute takes precedence during the attributed
* element build or transformation.
*/
public sealed interface ModulePackagesAttribute
extends Attribute<ModulePackagesAttribute>, ClassElement

View File

@ -56,6 +56,9 @@ public sealed interface ModuleRequireInfo
*/
int requiresFlagsMask();
/**
* {@return the access flags}
*/
default Set<AccessFlag> requiresFlags() {
return AccessFlag.maskToAccessFlags(requiresFlagsMask(), AccessFlag.Location.MODULE_REQUIRES);
}

View File

@ -56,6 +56,10 @@ import jdk.internal.classfile.impl.UnboundAttribute;
* 0x0008 (WARN_INCUBATING)
* }
* } </pre>
* <p>
* The attribute does not permit multiple instances in a given location.
* Subsequent occurrence of the attribute takes precedence during the attributed
* element build or transformation.
*/
public sealed interface ModuleResolutionAttribute
extends Attribute<ModuleResolutionAttribute>, ClassElement
@ -72,6 +76,7 @@ public sealed interface ModuleResolutionAttribute
* 0x0002 (WARN_DEPRECATED)
* 0x0004 (WARN_DEPRECATED_FOR_REMOVAL)
* 0x0008 (WARN_INCUBATING)
* @return the module resolution flags
*/
int resolutionFlags();

View File

@ -51,6 +51,10 @@ import jdk.internal.classfile.impl.UnboundAttribute;
* u2 target_platform_index;
* }
* } </pre>
* <p>
* The attribute does not permit multiple instances in a given location.
* Subsequent occurrence of the attribute takes precedence during the attributed
* element build or transformation.
*/
public sealed interface ModuleTargetAttribute
extends Attribute<ModuleTargetAttribute>, ClassElement

View File

@ -38,6 +38,10 @@ import jdk.internal.classfile.impl.UnboundAttribute;
* appear on classes to indicate that this class is a member of a nest.
* Delivered as a {@link jdk.internal.classfile.ClassElement} when
* traversing the elements of a {@link jdk.internal.classfile.ClassModel}.
* <p>
* The attribute does not permit multiple instances in a given location.
* Subsequent occurrence of the attribute takes precedence during the attributed
* element build or transformation.
*/
public sealed interface NestHostAttribute extends Attribute<NestHostAttribute>, ClassElement
permits BoundAttribute.BoundNestHostAttribute,

View File

@ -40,6 +40,10 @@ import jdk.internal.classfile.impl.Util;
* appear on classes to indicate that this class is the host of a nest.
* Delivered as a {@link jdk.internal.classfile.ClassElement} when
* traversing the elements of a {@link jdk.internal.classfile.ClassModel}.
* <p>
* The attribute does not permit multiple instances in a given location.
* Subsequent occurrence of the attribute takes precedence during the attributed
* element build or transformation.
*/
public sealed interface NestMembersAttribute extends Attribute<NestMembersAttribute>, ClassElement
permits BoundAttribute.BoundNestMembersAttribute, UnboundAttribute.UnboundNestMembersAttribute {

View File

@ -40,6 +40,10 @@ import jdk.internal.classfile.impl.Util;
* appear on classes to indicate which classes may extend this class.
* Delivered as a {@link jdk.internal.classfile.ClassElement} when
* traversing the elements of a {@link jdk.internal.classfile.ClassModel}.
* <p>
* The attribute does not permit multiple instances in a given location.
* Subsequent occurrence of the attribute takes precedence during the attributed
* element build or transformation.
*/
public sealed interface PermittedSubclassesAttribute
extends Attribute<PermittedSubclassesAttribute>, ClassElement

View File

@ -37,6 +37,10 @@ import jdk.internal.classfile.impl.UnboundAttribute;
* appear on classes to indicate that this class is a record class.
* Delivered as a {@link jdk.internal.classfile.ClassElement} when
* traversing the elements of a {@link jdk.internal.classfile.ClassModel}.
* <p>
* The attribute does not permit multiple instances in a given location.
* Subsequent occurrence of the attribute takes precedence during the attributed
* element build or transformation.
*/
public sealed interface RecordAttribute extends Attribute<RecordAttribute>, ClassElement
permits BoundAttribute.BoundRecordAttribute, UnboundAttribute.UnboundRecordAttribute {

View File

@ -36,6 +36,10 @@ import java.util.List;
* can appear on classes, methods, and fields. Delivered as a
* {@link jdk.internal.classfile.ClassElement}, {@link jdk.internal.classfile.FieldElement}, or
* {@link jdk.internal.classfile.MethodElement} when traversing the corresponding model type.
* <p>
* The attribute does not permit multiple instances in a given location.
* Subsequent occurrence of the attribute takes precedence during the attributed
* element build or transformation.
*/
public sealed interface RuntimeInvisibleAnnotationsAttribute
extends Attribute<RuntimeInvisibleAnnotationsAttribute>,

View File

@ -38,6 +38,10 @@ import jdk.internal.classfile.impl.UnboundAttribute;
* Models the {@code RuntimeInvisibleParameterAnnotations} attribute
* {@jvms 4.7.19}, which can appear on methods. Delivered as a {@link
* jdk.internal.classfile.MethodElement} when traversing a {@link MethodModel}.
* <p>
* The attribute does not permit multiple instances in a given location.
* Subsequent occurrence of the attribute takes precedence during the attributed
* element build or transformation.
*/
public sealed interface RuntimeInvisibleParameterAnnotationsAttribute
extends Attribute<RuntimeInvisibleParameterAnnotationsAttribute>, MethodElement

View File

@ -42,6 +42,10 @@ import jdk.internal.classfile.impl.UnboundAttribute;
* {@link jdk.internal.classfile.ClassElement}, {@link jdk.internal.classfile.FieldElement},
* {@link jdk.internal.classfile.MethodElement}, or {@link CodeElement} when traversing
* the corresponding model type.
* <p>
* The attribute does not permit multiple instances in a given location.
* Subsequent occurrence of the attribute takes precedence during the attributed
* element build or transformation.
*/
public sealed interface RuntimeInvisibleTypeAnnotationsAttribute
extends Attribute<RuntimeInvisibleTypeAnnotationsAttribute>,

View File

@ -36,6 +36,10 @@ import java.util.List;
* can appear on classes, methods, and fields. Delivered as a
* {@link jdk.internal.classfile.ClassElement}, {@link jdk.internal.classfile.FieldElement}, or
* {@link jdk.internal.classfile.MethodElement} when traversing the corresponding model type.
* <p>
* The attribute does not permit multiple instances in a given location.
* Subsequent occurrence of the attribute takes precedence during the attributed
* element build or transformation.
*/
public sealed interface RuntimeVisibleAnnotationsAttribute
extends Attribute<RuntimeVisibleAnnotationsAttribute>,

View File

@ -38,6 +38,10 @@ import jdk.internal.classfile.impl.UnboundAttribute;
* Models the {@code RuntimeVisibleParameterAnnotations} attribute {@jvms 4.7.18}, which
* can appear on methods. Delivered as a {@link jdk.internal.classfile.MethodElement}
* when traversing a {@link MethodModel}.
*
* @apiNote The attribute does not permit multiple instances in a given location.
* Subsequent occurrence of the attribute takes precedence during the attributed
* element build or transformation.
*/
public sealed interface RuntimeVisibleParameterAnnotationsAttribute
extends Attribute<RuntimeVisibleParameterAnnotationsAttribute>, MethodElement

View File

@ -42,6 +42,10 @@ import jdk.internal.classfile.impl.UnboundAttribute;
* {@link jdk.internal.classfile.ClassElement}, {@link jdk.internal.classfile.FieldElement},
* {@link jdk.internal.classfile.MethodElement}, or {@link CodeElement} when traversing
* the corresponding model type.
* <p>
* The attribute does not permit multiple instances in a given location.
* Subsequent occurrence of the attribute takes precedence during the attributed
* element build or transformation.
*/
public sealed interface RuntimeVisibleTypeAnnotationsAttribute
extends Attribute<RuntimeVisibleTypeAnnotationsAttribute>,

View File

@ -43,6 +43,10 @@ import jdk.internal.classfile.impl.UnboundAttribute;
* {@link jdk.internal.classfile.ClassElement}, {@link jdk.internal.classfile.FieldElement}, or
* {@link jdk.internal.classfile.MethodElement} when traversing
* the corresponding model type.
* <p>
* The attribute does not permit multiple instances in a given location.
* Subsequent occurrence of the attribute takes precedence during the attributed
* element build or transformation.
*/
public sealed interface SignatureAttribute
extends Attribute<SignatureAttribute>,

View File

@ -31,9 +31,13 @@ import jdk.internal.classfile.impl.BoundAttribute;
import jdk.internal.classfile.impl.UnboundAttribute;
/**
* Models the {@code SourceDebugExtension} attribute (@@@ need reference).
* Models the {@code SourceDebugExtension} attribute.
* Delivered as a {@link jdk.internal.classfile.ClassElement} when traversing the elements of
* a {@link jdk.internal.classfile.ClassModel}.
* <p>
* The attribute does not permit multiple instances in a given location.
* Subsequent occurrence of the attribute takes precedence during the attributed
* element build or transformation.
*/
public sealed interface SourceDebugExtensionAttribute
extends Attribute<SourceDebugExtensionAttribute>, ClassElement

View File

@ -37,6 +37,10 @@ import jdk.internal.classfile.impl.UnboundAttribute;
* Models the {@code SourceFile} attribute {@jvms 4.7.10}, which
* can appear on classes. Delivered as a {@link jdk.internal.classfile.ClassElement}
* when traversing a {@link ClassModel}.
* <p>
* The attribute does not permit multiple instances in a given location.
* Subsequent occurrence of the attribute takes precedence during the attributed
* element build or transformation.
*/
public sealed interface SourceFileAttribute
extends Attribute<SourceFileAttribute>, ClassElement
@ -47,10 +51,18 @@ public sealed interface SourceFileAttribute
*/
Utf8Entry sourceFile();
/**
* {@return a source file attribute}
* @param sourceFile the source file name
*/
static SourceFileAttribute of(String sourceFile) {
return of(TemporaryConstantPool.INSTANCE.utf8Entry(sourceFile));
}
/**
* {@return a source file attribute}
* @param sourceFile the source file name
*/
static SourceFileAttribute of(Utf8Entry sourceFile) {
return new UnboundAttribute.UnboundSourceFileAttribute(sourceFile);
}

View File

@ -34,9 +34,13 @@ import jdk.internal.classfile.impl.TemporaryConstantPool;
import jdk.internal.classfile.impl.UnboundAttribute;
/**
* Models the {@code SourceID} attribute (@@@ reference needed), which can
* Models the {@code SourceID} attribute, which can
* appear on classes. Delivered as a {@link jdk.internal.classfile.ClassElement} when
* traversing a {@link ClassModel}.
* <p>
* The attribute does not permit multiple instances in a given location.
* Subsequent occurrence of the attribute takes precedence during the attributed
* element build or transformation.
*/
public sealed interface SourceIDAttribute
extends Attribute<SourceIDAttribute>, ClassElement

View File

@ -40,11 +40,32 @@ import static jdk.internal.classfile.Classfile.*;
public sealed interface StackMapFrameInfo
permits StackMapDecoder.StackMapFrameImpl {
/**
* {@return the frame compact form type}
*/
int frameType();
/**
* {@return the frame target label}
*/
Label target();
/**
* {@return the expanded local variable types}
*/
List<VerificationTypeInfo> locals();
/**
* {@return the expanded stack types}
*/
List<VerificationTypeInfo> stack();
/**
* {@return a new stack map frame}
* @param target the location of the frame
* @param locals the complete list of frame locals
* @param stack the complete frame stack
*/
public static StackMapFrameInfo of(Label target,
List<VerificationTypeInfo> locals,
List<VerificationTypeInfo> stack) {
@ -56,6 +77,10 @@ public sealed interface StackMapFrameInfo
* The type of a stack value.
*/
sealed interface VerificationTypeInfo {
/**
* {@return the tag of the type info}
*/
int tag();
}
@ -63,12 +88,26 @@ public sealed interface StackMapFrameInfo
* A simple stack value.
*/
public enum SimpleVerificationTypeInfo implements VerificationTypeInfo {
/** verification type top */
ITEM_TOP(VT_TOP),
/** verification type int */
ITEM_INTEGER(VT_INTEGER),
/** verification type float */
ITEM_FLOAT(VT_FLOAT),
/** verification type double */
ITEM_DOUBLE(VT_DOUBLE),
/** verification type long */
ITEM_LONG(VT_LONG),
/** verification type null */
ITEM_NULL(VT_NULL),
/** verification type uninitializedThis */
ITEM_UNINITIALIZED_THIS(VT_UNINITIALIZED_THIS);
@ -90,19 +129,30 @@ public sealed interface StackMapFrameInfo
sealed interface ObjectVerificationTypeInfo extends VerificationTypeInfo
permits StackMapDecoder.ObjectVerificationTypeInfoImpl {
/**
* {@return a new object verification type info}
* @param className the class of the object
*/
public static ObjectVerificationTypeInfo of(ClassEntry className) {
return new StackMapDecoder.ObjectVerificationTypeInfoImpl(className);
}
/**
* {@return a new object verification type info}
* @param classDesc the class of the object
*/
public static ObjectVerificationTypeInfo of(ClassDesc classDesc) {
return of(TemporaryConstantPool.INSTANCE.classEntry(classDesc));
}
/**
* {@return the class of the value}
* {@return the class of the object}
*/
ClassEntry className();
/**
* {@return the class of the object}
*/
default ClassDesc classSymbol() {
return className().asSymbol();
}
@ -113,8 +163,16 @@ public sealed interface StackMapFrameInfo
*/
sealed interface UninitializedVerificationTypeInfo extends VerificationTypeInfo
permits StackMapDecoder.UninitializedVerificationTypeInfoImpl {
/**
* {@return the {@code new} instruction position that creates this unitialized object}
*/
Label newTarget();
/**
* {@return an unitialized verification type info}
* @param newTarget the {@code new} instruction position that creates this unitialized object
*/
public static UninitializedVerificationTypeInfo of(Label newTarget) {
return new StackMapDecoder.UninitializedVerificationTypeInfoImpl(newTarget);
}

View File

@ -35,6 +35,10 @@ import jdk.internal.classfile.impl.UnboundAttribute;
/**
* Models the {@code StackMapTable} attribute {@jvms 4.7.4}, which can appear
* on a {@code Code} attribute.
* <p>
* The attribute does not permit multiple instances in a given location.
* Subsequent occurrence of the attribute takes precedence during the attributed
* element build or transformation.
*/
public sealed interface StackMapTableAttribute
extends Attribute<StackMapTableAttribute>, CodeElement
@ -45,6 +49,10 @@ public sealed interface StackMapTableAttribute
*/
List<StackMapFrameInfo> entries();
/**
* {@return a stack map table attribute}
* @param entries the stack map frames
*/
public static StackMapTableAttribute of(List<StackMapFrameInfo> entries) {
return new UnboundAttribute.UnboundStackMapTableAttribute(entries);
}

View File

@ -37,6 +37,8 @@ import jdk.internal.classfile.impl.UnboundAttribute;
* classes, methods, and fields. Delivered as a {@link ClassElement},
* {@link MethodElement}, or {@link FieldElement} when traversing the elements
* of a corresponding model.
* <p>
* The attribute permits multiple instances in a given location.
*/
public sealed interface SyntheticAttribute
extends Attribute<SyntheticAttribute>,

View File

@ -51,6 +51,7 @@ public sealed interface BranchInstruction extends Instruction
*
* @param op the opcode for the specific type of branch instruction,
* which must be of kind {@link Opcode.Kind#BRANCH}
* @param target the target of the branch
*/
static BranchInstruction of(Opcode op, Label target) {
Util.checkKind(op, Opcode.Kind.BRANCH);

View File

@ -39,5 +39,9 @@ import jdk.internal.classfile.impl.LabelImpl;
*/
public sealed interface LabelTarget extends PseudoInstruction
permits LabelImpl {
/**
* {@return the label corresponding to this target}
*/
Label label();
}

View File

@ -42,8 +42,15 @@ import jdk.internal.classfile.impl.Util;
public sealed interface LoadInstruction extends Instruction
permits AbstractInstruction.BoundLoadInstruction,
AbstractInstruction.UnboundLoadInstruction {
/**
* {@return the local variable slot to load from}
*/
int slot();
/**
* {@return the type of the value to be loaded}
*/
TypeKind typeKind();
/**

View File

@ -80,6 +80,12 @@ public sealed interface LocalVariable extends PseudoInstruction
*/
Label endScope();
/**
* Writes the local variable to the specified writer
*
* @param buf the writer
* @return true if the variable has been written
*/
boolean writeTo(BufWriter buf);
/**

View File

@ -77,6 +77,12 @@ public sealed interface LocalVariableType extends PseudoInstruction
*/
Label endScope();
/**
* Writes the local variable to the specified writer
*
* @param buf the writer
* @return true if the variable has been written
*/
boolean writeTo(BufWriter buf);
/**

View File

@ -41,6 +41,10 @@ import jdk.internal.classfile.impl.Util;
*/
public sealed interface ReturnInstruction extends Instruction
permits AbstractInstruction.UnboundReturnInstruction {
/**
* {@return the type of the return instruction}
*/
TypeKind typeKind();
/**

View File

@ -41,7 +41,15 @@ import jdk.internal.classfile.impl.Util;
*/
public sealed interface StoreInstruction extends Instruction
permits AbstractInstruction.BoundStoreInstruction, AbstractInstruction.UnboundStoreInstruction {
/**
* {@return the local variable slot to store to}
*/
int slot();
/**
* {@return the type of the value to be stored}
*/
TypeKind typeKind();
/**

View File

@ -43,6 +43,10 @@ import jdk.internal.classfile.impl.Util;
public sealed interface TypeCheckInstruction extends Instruction
permits AbstractInstruction.BoundTypeCheckInstruction,
AbstractInstruction.UnboundTypeCheckInstruction {
/**
* {@return the type against which the instruction checks or casts}
*/
ClassEntry type();
/**

View File

@ -211,7 +211,12 @@
* builders for the constructor and {@code main} method, and in turn use the
* method builders to create a {@code Code} attribute and use the code builders
* to generate the instructions:
* {@snippet lang="java" class="PackageSnippets" region="helloWorld"}
* {@snippet lang="java" class="PackageSnippets" region="helloWorld1"}
* <p>
* The convenience methods {@code ClassBuilder.buildMethodBody} allows us to ask
* {@link ClassBuilder} to create code builders to build method bodies directly,
* skipping the method builder custom lambda:
* {@snippet lang="java" class="PackageSnippets" region="helloWorld2"}
* <p>
* Builders often support multiple ways of expressing the same entity at
* different levels of abstraction. For example, the {@code invokevirtual}
@ -276,9 +281,13 @@
* builder and an element, and an implementation "flatMap"s elements
* into the builder. We could express the above as:
* {@snippet lang="java" class="PackageSnippets" region="stripDebugMethods2"}
* <p>
* {@code ClassTransform.dropping} convenience method allow us to simplify the same
* transformation construction and express the above as:
* {@snippet lang="java" class="PackageSnippets" region="stripDebugMethods3"}
*
* <h3>Lifting transforms</h3>
* While the second example is only slightly shorter than the first, the
* While the example using transformations are only slightly shorter, the
* advantage of expressing transformation in this way is that the transform
* operations can be more easily combined. Suppose we want to redirect
* invocations of static methods on {@code Foo} to the corresponding method on
@ -301,6 +310,11 @@
* ClassTransform ct = ClassTransform.transformingMethods(mt);
* }
* <p>
* or lift the code transform into the class transform directly:
* {@snippet lang=java :
* ClassTransform ct = ClassTransform.transformingMethodBodiess(fooToBar);
* }
* <p>
* and then transform the classfile:
* {@snippet lang=java :
* var cc = Classfile.of();

View File

@ -132,28 +132,41 @@ class PackageSnippets {
private static final MethodTypeDesc MTD_void_StringArray = MethodTypeDesc.of(ConstantDescs.CD_void, ConstantDescs.CD_String.arrayType());
private static final MethodTypeDesc MTD_void_String = MethodTypeDesc.of(ConstantDescs.CD_void, ConstantDescs.CD_String);
void writeHelloWorld() {
// @start region="helloWorld"
byte[] bytes = Classfile.of().build(CD_Hello, cb -> {
cb.withFlags(AccessFlag.PUBLIC);
cb.withMethod(ConstantDescs.INIT_NAME, ConstantDescs.MTD_void, Classfile.ACC_PUBLIC,
mb -> mb.withCode(
b -> b.aload(0)
.invokespecial(ConstantDescs.CD_Object, ConstantDescs.INIT_NAME,
ConstantDescs.MTD_void)
.returnInstruction(TypeKind.VoidType)
)
)
.withMethod("main", MTD_void_StringArray,
Classfile.ACC_PUBLIC,
mb -> mb.withFlags(AccessFlag.STATIC, AccessFlag.PUBLIC)
.withCode(
b -> b.getstatic(CD_System, "out", CD_PrintStream)
.constantInstruction(Opcode.LDC, "Hello World")
.invokevirtual(CD_PrintStream, "println", MTD_void_String)
.returnInstruction(TypeKind.VoidType)
));
});
void writeHelloWorld1() {
// @start region="helloWorld1"
byte[] bytes = Classfile.of().build(CD_Hello,
clb -> clb.withFlags(Classfile.ACC_PUBLIC)
.withMethod(ConstantDescs.INIT_NAME, ConstantDescs.MTD_void,
Classfile.ACC_PUBLIC,
mb -> mb.withCode(
cob -> cob.aload(0)
.invokespecial(ConstantDescs.CD_Object,
ConstantDescs.INIT_NAME, ConstantDescs.MTD_void)
.return_()))
.withMethod("main", MTD_void_StringArray, Classfile.ACC_PUBLIC + Classfile.ACC_STATIC,
mb -> mb.withCode(
cob -> cob.getstatic(CD_System, "out", CD_PrintStream)
.ldc("Hello World")
.invokevirtual(CD_PrintStream, "println", MTD_void_String)
.return_())));
// @end
}
void writeHelloWorld2() {
// @start region="helloWorld2"
byte[] bytes = Classfile.of().build(CD_Hello,
clb -> clb.withFlags(Classfile.ACC_PUBLIC)
.withMethodBody(ConstantDescs.INIT_NAME, ConstantDescs.MTD_void,
Classfile.ACC_PUBLIC,
cob -> cob.aload(0)
.invokespecial(ConstantDescs.CD_Object,
ConstantDescs.INIT_NAME, ConstantDescs.MTD_void)
.return_())
.withMethodBody("main", MTD_void_StringArray, Classfile.ACC_PUBLIC + Classfile.ACC_STATIC,
cob -> cob.getstatic(CD_System, "out", CD_PrintStream)
.ldc("Hello World")
.invokevirtual(CD_PrintStream, "println", MTD_void_String)
.return_()));
// @end
}
@ -161,13 +174,14 @@ class PackageSnippets {
// @start region="stripDebugMethods1"
ClassModel classModel = Classfile.of().parse(bytes);
byte[] newBytes = Classfile.of().build(classModel.thisClass().asSymbol(),
classBuilder -> {
for (ClassElement ce : classModel) {
if (!(ce instanceof MethodModel mm
&& mm.methodName().stringValue().startsWith("debug")))
classBuilder.with(ce);
}
});
classBuilder -> {
for (ClassElement ce : classModel) {
if (!(ce instanceof MethodModel mm
&& mm.methodName().stringValue().startsWith("debug"))) {
classBuilder.with(ce);
}
}
});
// @end
}
@ -182,6 +196,14 @@ class PackageSnippets {
// @end
}
void stripDebugMethods3(byte[] bytes) {
// @start region="stripDebugMethods3"
ClassTransform ct = ClassTransform.dropping(
element -> element instanceof MethodModel mm
&& mm.methodName().stringValue().startsWith("debug"));
// @end
}
void fooToBarTransform() {
// @start region="fooToBarTransform"
CodeTransform fooToBar = (b, e) -> {
@ -199,7 +221,7 @@ class PackageSnippets {
CodeTransform instrumentCalls = (b, e) -> {
if (e instanceof InvokeInstruction i) {
b.getstatic(CD_System, "out", CD_PrintStream)
.constantInstruction(Opcode.LDC, i.name().stringValue())
.ldc(i.name().stringValue())
.invokevirtual(CD_PrintStream, "println", MTD_void_String);
}
b.with(e);