java.lang.classfile package contains API models for reading, writing, and modifying Java class files, as specified in Chapter 4 of the Java Virtual Machine Specification. This package, java.lang.classfile.attribute, java.lang.classfile.constantpool, and java.lang.classfile.instruction form the Class-File API. ClassModel; we convert bytes into a ClassModel with ClassFile.parse(byte[]): ClassModel cm = ClassFile.of().parse(bytes);
parse that let you specify various processing options. A ClassModel is an immutable description of a class file. It provides accessor methods to get at class metadata (e.g., ClassModel.thisClass(), ClassModel.flags()), as well as subordinate classfile entities (ClassModel.fields(), AttributedElement.attributes()). A 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 IllegalArgumentException due to malformed
class file format, as parsing happens lazily.
We can enumerate the names of the fields and methods in a class by:
ClassModel cm = ClassFile.of().parse(bytes);
for (FieldModel fm : cm.fields())
System.out.printf("Field %s%n", fm.fieldName().stringValue());
for (MethodModel mm : cm.methods())
System.out.printf("Method %s%n", mm.methodName().stringValue());
When we enumerate the methods, we get a MethodModel for each method; like a 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 ClassModel is the root of a tree, with children for fields, methods, and attributes, and MethodModel in turn has its own children (attributes, CodeModel, etc.)
Methods like 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 ClassModel also provides us with a view of the classfile as a series of class elements, which may include methods, fields, attributes, and more, and which can be distinguished with pattern matching. We could rewrite the above example as:
ClassModel cm = ClassFile.of().parse(bytes);
for (ClassElement ce : cm) {
switch (ce) {
case MethodModel mm -> System.out.printf("Method %s%n", mm.methodName().stringValue());
case FieldModel fm -> System.out.printf("Field %s%n", fm.fieldName().stringValue());
default -> { }
}
}
The models returned as elements from traversing ClassModel can in turn be sources of elements. If we wanted to traverse a classfile and enumerate all the classes for which we access fields and methods, we can pick out the class elements that describe methods, then in turn pick out the method elements that describe the code attribute, and finally pick out the code elements that describe field access and invocation instructions:
ClassModel cm = ClassFile.of().parse(bytes);
Set<ClassDesc> dependencies = new HashSet<>();
for (ClassElement ce : cm) {
if (ce instanceof MethodModel mm) {
for (MethodElement me : mm) {
if (me instanceof CodeModel xm) {
for (CodeElement e : xm) {
switch (e) {
case InvokeInstruction i -> dependencies.add(i.owner().asSymbol());
case FieldInstruction i -> dependencies.add(i.owner().asSymbol());
default -> { }
}
}
}
}
}
}
This same query could alternately be processed as a stream pipeline over class elements:
ClassModel cm = ClassFile.of().parse(bytes);
Set<ClassDesc> dependencies =
cm.elementStream()
.flatMap(ce -> ce instanceof MethodModel mm ? mm.elementStream() : Stream.empty())
.flatMap(me -> me instanceof CodeModel com ? com.elementStream() : Stream.empty())
.<ClassDesc>mapMulti((xe, c) -> {
switch (xe) {
case InvokeInstruction i -> c.accept(i.owner().asSymbol());
case FieldInstruction i -> c.accept(i.owner().asSymbol());
default -> { }
}
})
.collect(toSet());
ClassModel.methods() accessor) or as a linear sequence of elements. (Elements can in turn also be models; a FieldModel is also an element of a class.) For each model type (e.g., MethodModel), there is a corresponding element type (MethodElement). Models and elements are immutable and are inflated lazily so creating a model does not necessarily require processing its entire content. ClassModel provides a lazily-inflated, read-only view of the constant pool via ClassModel.constantPool(). Descriptions of classfile content is often exposed in the form of various subtypes of PoolEntry, such as ClassEntry or Utf8Entry. Constant pool entries are also exposed through models and elements; in the above traversal example, the InvokeInstruction element exposed a method for owner that corresponds to a
Constant_Class_info entry in the constant pool.
Code attribute. Most attributes are surfaced as elements; for example, SignatureAttribute is a ClassElement, MethodElement, and FieldElement since it can appear in all of those places, and is included when iterating the elements of the corresponding model. Some attributes are not surfaced as elements; these are attributes that are tightly coupled to -- and logically part of -- other parts of the class file. These include the BootstrapMethods, LineNumberTable,
StackMapTable, LocalVariableTable, and
LocalVariableTypeTable attributes. These are processed by the library and treated as part of the structure they are coupled to (the entries of the BootstrapMethods attribute are treated as part of the constant pool; line numbers and local variable metadata are modeled as elements of CodeModel.)
The Code attribute, in addition to being modeled as a MethodElement, is also a model in its own right (CodeModel) due to its complex structure.
Each standard attribute has an interface (in java.lang.classfile.attribute) which exposes the contents of the attribute and provides factories to construct the attribute. For example, the Signature attribute is defined by the SignatureAttribute class, and provides accessors for SignatureAttribute.signature() as well as factories taking Utf8Entry or String.
AttributeMapper. An
AttributeMapper provides the AttributeMapper.readAttribute(AttributedElement, ClassReader, int) method for mapping from the classfile format to an attribute instance, and the 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. There are built-in attribute mappers (in Attributes) for each of the attribute types defined in section 4.7 of The Java Virtual Machine Specification, as well as several common nonstandard attributes used by the JDK such as CharacterRangeTable.
Unrecognized attributes are delivered as elements of type UnknownAttribute, which provide access only to the byte[] contents of the attribute.
For nonstandard attributes, user-provided attribute mappers can be specified through the use of the ClassFile.AttributeMapperOption.of(Function) classfile option. Implementations of custom attributes should extend CustomAttribute.
ClassFile.of(ClassFile.Option[]) accepts a list of options. ClassFile.Option is a base interface for some statically enumerated options, as well as factories for more complex options, including:
ClassFile.AttributeMapperOption.of(Function) -- specify format of custom attributesClassFile.AttributesProcessingOption -- unrecognized or problematic original attributes (default is PASS_ALL_ATTRIBUTES)ClassFile.ClassHierarchyResolverOption.of(ClassHierarchyResolver) -- specify a custom class hierarchy resolver used by stack map generationClassFile.ConstantPoolSharingOption -- share constant pool when transforming (default is SHARED_POOL)ClassFile.DeadCodeOption -- patch out unreachable code (default is PATCH_DEAD_CODE)ClassFile.DeadLabelsOption -- filter unresolved labels (default is FAIL_ON_DEAD_LABELS)ClassFile.DebugElementsOption -- processing of debug information, such as local variable metadata (default is PASS_DEBUG) ClassFile.LineNumbersOption -- processing of line numbers (default is PASS_LINE_NUMBERS) ClassFile.ShortJumpsOption -- automatically rewrite short jumps to long when necessary (default is FIX_SHORT_JUMPS)ClassFile.StackMapsOption -- generate stackmaps (default is STACK_MAPS_WHEN_REQUIRED) ClassFile.AttributeMapperOption and ClassFile.ClassHierarchyResolverOption are critical to the correctness of class file parsing and generation. The attribute mapper is required to parse custom attributes. A correct resolver is required to generate 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.
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 classfile, such as stack maps. Many of these options are to access performance tradeoffs; processing debug information and line numbers has a cost (both in writing and reading.) If you don't need this information, you can suppress it with options to gain some performance.
ClassBuilder, methods through MethodBuilder, etc. Rather than creating builders directly, builders are provided as an argument to a user-provided lambda. To generate the familiar "hello world" program, we ask for a class builder, and use that class builder to create method builders for the constructor and main method, and in turn use the method builders to create a Code attribute and use the code builders to generate the instructions:
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_())));
The convenience methods ClassBuilder.buildMethodBody allows us to ask ClassBuilder to create code builders to build method bodies directly, skipping the method builder custom lambda:
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_()));
Builders often support multiple ways of expressing the same entity at different levels of abstraction. For example, the invokevirtual instruction invoking println could have been generated with CodeBuilder.invokevirtual, CodeBuilder.invoke, or CodeBuilder.with.
The convenience method CodeBuilder.invokevirtual behaves as if it calls the convenience method CodeBuilder.invoke, which in turn behaves as if it calls method CodeBuilder.with. This composing of method calls on the builder enables the composing of transforms (as described later).
Unless otherwise noted, passing a null argument to a constructor or method of any Class-File API class or interface will cause a NullPointerException to be thrown. Additionally, invoking a method with an array or collection containing a null element will cause a NullPointerException, unless otherwise specified.
java.lang.constant such as ClassDesc and MethodTypeDesc, which is less error-prone than using raw strings. If a constant pool entry has a nominal representation then it provides a method returning the corresponding nominal descriptor type e.g. method ClassEntry.asSymbol() returns ClassDesc.
Where appropriate builders provide two methods for building an element with symbolic information, one accepting nominal descriptors, and the other accepting constant pool entries.
IllegalArgumentException. 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 ClassDesc.of(String) 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.
var validClassEntry = constantPoolBuilder.classEntry(ClassDesc.of("mypackage.MyClass"));
On the other hand it is possible to use builders methods and factories accepting constant pool entries directly. Constant pool entries can be constructed also directly from raw values, with no additional conversions or validations. Following example uses intentionally wrong class name form and it is applied without any validation or conversion.
var invalidClassEntry = constantPoolBuilder.classEntry(
constantPoolBuilder.utf8Entry("mypackage.MyClass"));
More complex verification of a classfile can be achieved by invocation of ClassFile.verify(ClassModel).
XxxBuilder has a method with(XxxElement) so that elements that we wish to pass through unchanged can be handed directly back to the builder. If we wanted to strip out methods whose names starts with "debug", we could get an existing ClassModel, build a new classfile that provides a ClassBuilder, iterate the elements of the original ClassModel, and pass through all of them to the builder except the methods we want to drop:
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);
}
}
});
This hands every class element, except for those corresponding to methods whose names start with debug, back to the builder. Transformations can of course be more complicated, diving into method bodies and instructions and transforming those as well, but the same structure is repeated at every level, since every entity has corresponding model, builder, and element abstractions.
Transformation can be viewed as a "flatMap" operation on the sequence of elements; for every element, we could pass it through unchanged, drop it, or replace it with one or more elements. Because transformation is such a common operation on classfiles, each model type has a corresponding
XxxTransform type (which describes a transform on a sequence of
XxxElement) and each builder type has transformYyy methods for transforming its child models. A transform is simply a functional interface that takes a builder and an element, and an implementation "flatMap"s elements into the builder. We could express the above as:
ClassTransform ct = (builder, element) -> {
if (!(element instanceof MethodModel mm && mm.methodName().stringValue().startsWith("debug")))
builder.with(element);
};
var cc = ClassFile.of();
byte[] newBytes = cc.transformClass(cc.parse(bytes), ct);
ClassTransform.dropping convenience method allow us to simplify the same transformation construction and express the above as:
ClassTransform ct = ClassTransform.dropping(
element -> element instanceof MethodModel mm
&& mm.methodName().stringValue().startsWith("debug"));
Foo to the corresponding method on Bar instead. We could express this as a transformation on CodeElement: CodeTransform fooToBar = (b, e) -> {
if (e instanceof InvokeInstruction i
&& 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
}
};
We can then lift this transformation on code elements into a transformation on method elements. This intercepts method elements that correspond to a Code attribute, dives into its code elements, and applies the code transform to them, and passes other method elements through unchanged:
MethodTransform mt = MethodTransform.transformingCode(fooToBar);
and further lift the transform on method elements into one on class elements:
ClassTransform ct = ClassTransform.transformingMethods(mt);
or lift the code transform into the class transform directly:
ClassTransform ct = ClassTransform.transformingMethodBodies(fooToBar);
and then transform the classfile:
var cc = ClassFile.of();
byte[] newBytes = cc.transformClass(cc.parse(bytes), ct);
This is much more concise (and less error-prone) than the equivalent expressed by traversing the classfile structure directly:
byte[] newBytes = ClassFile.of().build(classModel.thisClass().asSymbol(),
classBuilder -> {
for (ClassElement ce : classModel) {
if (ce instanceof MethodModel mm) {
classBuilder.withMethod(mm.methodName().stringValue(), mm.methodTypeSymbol(),
mm.flags().flagsMask(),
methodBuilder -> {
for (MethodElement me : mm) {
if (me instanceof CodeModel xm) {
methodBuilder.withCode(codeBuilder -> {
for (CodeElement e : xm) {
if (e instanceof InvokeInstruction i && i.owner().asInternalName().equals("Foo")
&& i.opcode() == Opcode.INVOKESTATIC)
codeBuilder.invoke(i.opcode(), CD_Bar,
i.name().stringValue(), i.typeSymbol(), i.isInterface());
else codeBuilder.with(e);
}});
}
else
methodBuilder.with(me);
}
});
}
else
classBuilder.with(ce);
}
});
CodeTransform instrumentCalls = (b, e) -> {
if (e instanceof InvokeInstruction i) {
b.getstatic(CD_System, "out", CD_PrintStream)
.ldc(i.name().stringValue())
.invokevirtual(CD_PrintStream, "println", MTD_void_String);
}
b.with(e);
};
Then we can compose fooToBar and instrumentCalls with CodeTransform.andThen(CodeTransform):
var cc = ClassFile.of();
byte[] newBytes = cc.transformClass(cc.parse(bytes),
ClassTransform.transformingMethods(
MethodTransform.transformingCode(
fooToBar.andThen(instrumentCalls))));
instrumentCalls will receive all code elements produced by transform forToBar, either those code elements from the original classfile or replacements (replacing static invocations to Foo with those to Bar). ClassFile.ConstantPoolSharingOption option. Such suppression may be beneficial when transformation removes many elements, resulting in many unreferenced constant pool entries. CodeTransform fooToBar = (b, e) -> {
if (ClassFile.latestMajorVersion() > ClassFile.JAVA_22_VERSION) {
throw new IllegalArgumentException("Cannot run on JDK > 22");
}
switch (e) {
case ArrayLoadInstruction i -> doSomething(b, i);
case ArrayStoreInstruction i -> doSomething(b, i);
default -> b.with(e);
}
};
ClassTransform fooToBar = (b, e) -> {
switch (e) {
case ClassFileVersion v when v.majorVersion() > ClassFile.JAVA_22_VERSION ->
throw new IllegalArgumentException("Cannot transform class file version " + v.majorVersion());
default -> doSomething(b, e);
}
};
CodeTransform fooToBar = (b, e) -> {
switch (e) {
case ArrayLoadInstruction i -> doSomething(b, i);
case ArrayStoreInstruction i -> doSomething(b, i);
case BranchInstruction i -> doSomething(b, i);
case ConstantInstruction i -> doSomething(b, i);
case ConvertInstruction i -> doSomething(b, i);
case DiscontinuedInstruction i -> doSomething(b, i);
case FieldInstruction i -> doSomething(b, i);
case InvokeDynamicInstruction i -> doSomething(b, i);
case InvokeInstruction i -> doSomething(b, i);
case LoadInstruction i -> doSomething(b, i);
case StoreInstruction i -> doSomething(b, i);
case IncrementInstruction i -> doSomething(b, i);
case LookupSwitchInstruction i -> doSomething(b, i);
case MonitorInstruction i -> doSomething(b, i);
case NewMultiArrayInstruction i -> doSomething(b, i);
case NewObjectInstruction i -> doSomething(b, i);
case NewPrimitiveArrayInstruction i -> doSomething(b, i);
case NewReferenceArrayInstruction i -> doSomething(b, i);
case NopInstruction i -> doSomething(b, i);
case OperatorInstruction i -> doSomething(b, i);
case ReturnInstruction i -> doSomething(b, i);
case StackInstruction i -> doSomething(b, i);
case TableSwitchInstruction i -> doSomething(b, i);
case ThrowInstruction i -> doSomething(b, i);
case TypeCheckInstruction i -> doSomething(b, i);
case PseudoInstruction i -> doSomething(b, i);
default ->
throw new IllegalArgumentException("An unknown instruction could not be handled by this transformation");
}
};
Conversely, classfile transforms that are only interested in consuming a portion of classfile elements do not need to concern with new and unknown classfile elements and may pass them through. Following example shows such future-proof code transformation:
CodeTransform fooToBar = (b, e) -> {
switch (e) {
case ArrayLoadInstruction i -> doSomething(b, i);
case ArrayStoreInstruction i -> doSomething(b, i);
default -> b.with(e);
}
};
The API is largely derived from a data model for the classfile format, which defines each element kind (which includes models and attributes) and its properties. For each element kind, there is a 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., CodeBuilder.invokevirtual(ClassDesc, String, MethodTypeDesc)).
Most symbolic information in elements is represented by constant pool entries (for example, the owner of a field is represented by a ClassEntry.) Factories and builders also accept nominal descriptors from java.lang.constant (e.g., ClassDesc.)
ClassElement =
FieldModel*(UtfEntry name, Utf8Entry descriptor)
| MethodModel*(UtfEntry name, Utf8Entry descriptor)
| ModuleAttribute?(int flags, ModuleEntry moduleName, UtfEntry moduleVersion,
List<ModuleRequireInfo> requires, List<ModuleOpenInfo> opens,
List<ModuleExportInfo> exports, List<ModuleProvidesInfo> provides,
List<ClassEntry> uses)
| ModulePackagesAttribute?(List<PackageEntry> packages)
| ModuleTargetAttribute?(Utf8Entry targetPlatform)
| ModuleHashesAttribute?(Utf8Entry algorithm, List<HashInfo> hashes)
| ModuleResolutionAttribute?(int resolutionFlags)
| SourceFileAttribute?(Utf8Entry sourceFile)
| SourceDebugExtensionsAttribute?(byte[] contents)
| CompilationIDAttribute?(Utf8Entry compilationId)
| SourceIDAttribute?(Utf8Entry sourceId)
| NestHostAttribute?(ClassEntry nestHost)
| NestMembersAttribute?(List<ClassEntry> nestMembers)
| RecordAttribute?(List<RecordComponent> components)
| EnclosingMethodAttribute?(ClassEntry className, NameAndTypeEntry method)
| InnerClassesAttribute?(List<InnerClassInfo> classes)
| PermittedSubclassesAttribute?(List<ClassEntry> permittedSubclasses)
| DeclarationElement*
DeclarationElement are the elements that are common to all declarations (classes, methods, fields) and so are factored out: DeclarationElement =
SignatureAttribute?(Utf8Entry signature)
| SyntheticAttribute?()
| DeprecatedAttribute?()
| RuntimeInvisibleAnnotationsAttribute?(List<Annotation> annotations)
| RuntimeVisibleAnnotationsAttribute?(List<Annotation> annotations)
| CustomAttribute*
| UnknownAttribute*
CodeModel (which models the Code attribute along with the code-related attributes: stack map table, local variable table, line number table, etc.) FieldElement =
DeclarationElement
| ConstantValueAttribute?(ConstantValueEntry constant)
MethodElement =
DeclarationElement
| CodeModel?()
| AnnotationDefaultAttribute?(ElementValue defaultValue)
| MethodParametersAttribute?(List<MethodParameterInfo> parameters)
| ExceptionsAttribute?(List<ClassEntry> exceptions)
CodeModel is unique in that its elements are ordered. Elements of Code include ordinary bytecodes, as well as a number of pseudo-instructions representing branch targets, line number metadata, local variable metadata, and catch blocks. CodeElement = Instruction | PseudoInstruction
Instruction =
LoadInstruction(TypeKind type, int slot)
| StoreInstruction(TypeKind type, int slot)
| IncrementInstruction(int slot, int constant)
| BranchInstruction(Opcode opcode, Label target)
| LookupSwitchInstruction(Label defaultTarget, List<SwitchCase> cases)
| TableSwitchInstruction(Label defaultTarget, int low, int high,
List<SwitchCase> cases)
| ReturnInstruction(TypeKind kind)
| ThrowInstruction()
| FieldInstruction(Opcode opcode, FieldRefEntry field)
| InvokeInstruction(Opcode opcode, MemberRefEntry method, boolean isInterface)
| InvokeDynamicInstruction(InvokeDynamicEntry invokedynamic)
| NewObjectInstruction(ClassEntry className)
| NewReferenceArrayInstruction(ClassEntry componentType)
| NewPrimitiveArrayInstruction(TypeKind typeKind)
| NewMultiArrayInstruction(ClassEntry componentType, int dims)
| ArrayLoadInstruction(Opcode opcode)
| ArrayStoreInstruction(Opcode opcode)
| TypeCheckInstruction(Opcode opcode, ClassEntry className)
| ConvertInstruction(TypeKind from, TypeKind to)
| OperatorInstruction(Opcode opcode)
| ConstantInstruction(ConstantDesc constant)
| StackInstruction(Opcode opcode)
| MonitorInstruction(Opcode opcode)
| NopInstruction()
PseudoInstruction =
| LabelTarget(Label label)
| LineNumber(int line)
| ExceptionCatch(Label tryStart, Label tryEnd, Label handler, ClassEntry exception)
| LocalVariable(int slot, UtfEntry name, Utf8Entry type, Label startScope, Label endScope)
| LocalVariableType(int slot, Utf8Entry name, Utf8Entry type, Label startScope, Label endScope)
| CharacterRange(int rangeStart, int rangeEnd, int flags, Label startScope, Label endScope)
| Class | Description |
|---|---|
| AccessFlags | Models the access flags for a class, method, or field. |
| Annotation | |
| AnnotationElement | |
| AnnotationValue | Models an element_value structure, or a value of an element-value pair of an annotation, as defined in JVMS 4.7.16.1. |
| AnnotationValue.OfAnnotation | Models an annotation value of an element-value pair. |
| AnnotationValue.OfArray | Models an array value of an element-value pair. |
| AnnotationValue.OfBoolean | Models a boolean value of an element-value pair. |
| AnnotationValue.OfByte | Models a byte value of an element-value pair. |
| AnnotationValue.OfChar | Models a char value of an element-value pair. |
| AnnotationValue.OfClass | Models a class value of an element-value pair. |
| AnnotationValue.OfConstant | Models a constant value of an element-value pair. |
| AnnotationValue.OfDouble | Models a double value of an element-value pair. |
| AnnotationValue.OfEnum | Models an enum value of an element-value pair. |
| AnnotationValue.OfFloat | Models a float value of an element-value pair. |
| AnnotationValue.OfInt | Models an int value of an element-value pair. |
| AnnotationValue.OfLong | Models a long value of an element-value pair. |
| AnnotationValue.OfShort | Models a short value of an element-value pair. |
| AnnotationValue.OfString | Models a string value of an element-value pair. |
| Attribute<A extends Attribute<A>> | Models an attribute (JVMS 4.7) in the class file format. |
| AttributedElement | A ClassFileElement describing a class file structure that has attributes, such as a class file, a field, a method, a Code attribute, or a record component. |
| AttributeMapper<A extends Attribute<A>> | Bidirectional mapper between the class file representation of an attribute and its API model. |
| AttributeMapper.AttributeStability | Indicates the data dependency of the class file representation of an attribute. |
| Attributes | Attribute mappers for predefined (JVMS 4.7) and JDK-specific nonstandard attributes. |
| BootstrapMethodEntry | Models an entry in the bootstrap method table. |
| BufWriter | Advanced class file writing support for AttributeMappers. |
| ClassBuilder | A builder for a class file. |
| ClassElement | Marker interface for a member element of a ClassModel. |
| ClassFile | Provides ability to parse, transform, and generate class files. |
| ClassFile.AttributeMapperOption | The option describing user-defined attributes for parsing class files. |
| ClassFile.AttributesProcessingOption | The option describing whether to retain or discard attributes that cannot verify their correctness after a transformation. |
| ClassFile.ClassHierarchyResolverOption | The option describing the class hierarchy resolver to use when generating stack maps or verifying classes. |
| ClassFile.ConstantPoolSharingOption | Option describing whether to extend from the original constant pool when transforming a class file. |
| ClassFile.DeadCodeOption | The option describing whether to patch out unreachable code for stack map generation. |
| ClassFile.DeadLabelsOption | The option describing whether to filter unbound labels and drop their enclosing structures if possible. |
| ClassFile.DebugElementsOption | The option describing whether to process or discard debug PseudoInstructions in the traversal of a CodeModel or a CodeBuilder. |
| ClassFile.LineNumbersOption | The option describing whether to process or discard LineNumbers in the traversal of a CodeModel or a CodeBuilder. |
| ClassFile.Option | An option that affects the parsing or writing of class files. |
| ClassFile.ShortJumpsOption | The option describing whether to automatically rewrite short jumps to equivalent instructions when necessary. |
| ClassFile.StackMapsOption | The option describing whether to generate stack maps. |
|
ClassFileBuilder<E extends ClassFileElement, B extends ClassFileBuilder<E, |
A builder for a CompoundElement, which accepts the member elements to be integrated into the built structure. |
| ClassFileElement | Marker interface for structures with special capabilities in the
class file format. |
|
ClassFileTransform<C extends ClassFileTransform<C, |
A transformation on a CompoundElement by processing its individual member elements and sending the results to a ClassFileBuilder, through ClassFileBuilder.transform(CompoundElement, ClassFileTransform). |
| ClassFileVersion | Models the minor and major version numbers of a class file (JVMS 4.1). |
| ClassHierarchyResolver | Provides class hierarchy information for stack maps generation and verification. |
| ClassHierarchyResolver.ClassHierarchyInfo | Information about a resolved class. |
| ClassModel | Models a class file. |
| ClassReader | Advanced class file reading support for AttributeMappers. |
| ClassSignature | Models the generic signature of a class or interface, as defined by JVMS 4.7.9.1. |
| ClassTransform | A transformation on streams of ClassElement. |
| CodeBuilder | A builder for Code attributes (method bodies). |
| CodeBuilder.BlockCodeBuilder | A builder for blocks of code. |
| CodeBuilder.CatchBuilder | A builder to add catch blocks. |
| CodeElement | Marker interface for a member element of a CodeModel. |
| CodeModel | Models the body of a method (the Code attribute). |
| CodeTransform | A transformation on streams of CodeElement. |
| CompoundElement<E extends ClassFileElement> | A class file structure that can be viewed as a composition of its member structures. |
| CustomAttribute<T extends CustomAttribute<T>> | Models a user-defined attribute in a class file. |
| FieldBuilder | A builder for fields. |
| FieldElement | Marker interface for a member element of a FieldModel. |
| FieldModel | Models a field. |
| FieldTransform | A transformation on streams of FieldElement. |
| Instruction | Models an executable instruction in the code array of the Code attribute of a method. |
| Interfaces | Models the interfaces (JVMS 4.1) of a class. |
| Label | A marker for a position within the instructions of a method body. |
| MethodBuilder | A builder for methods. |
| MethodElement | Marker interface for a member element of a MethodModel. |
| MethodModel | Models a method. |
| MethodSignature | Models the generic signature of a method or constructor, as defined by JVMS 4.7.9.1. |
| MethodTransform | A transformation on streams of MethodElement. |
| Opcode | Describes the opcodes of the JVM instruction set, as described in JVMS 6.5. |
| Opcode.Kind | Kinds of opcodes. |
| PseudoInstruction | |
| Signature | Models generic Java type signatures, as defined in JVMS 4.7.9.1. |
| Signature.ArrayTypeSig | Models the signature of an array type. |
| Signature.BaseTypeSig | Models the signature of a primitive type (JLS 4.2) or void. |
| Signature.ClassTypeSig | Models the signature of a possibly-parameterized class or interface type. |
| Signature.RefTypeSig | Models the signature of a reference type, which may be a class, interface, type variable, or array type. |
| Signature.ThrowableSig | Marker interface for a signature for a throwable type. |
| Signature.TypeArg | Models a type argument, an argument to a type parameter. |
| Signature.TypeArg.Bounded | Models a type argument with an explicit bound type. |
| Signature.TypeArg.Bounded.WildcardIndicator | Models a type argument's wildcard indicator. |
| Signature.TypeArg.Unbounded | Models an unbounded wildcard type argument *, or
? in Java programs. |
| Signature.TypeParam | Models a signature for a type parameter of a generic class, interface, method, or constructor, which introduces a type variable. |
| Signature.TypeVarSig | Models the signature of a type variable. |
| Superclass | Models the superclass (JVMS 4.1) of a class. |
| TypeAnnotation | Models a type_annotation structure (JVMS 4.7.20). |
| TypeAnnotation.CatchTarget | Indicates that an annotation appears on the i'th type in an exception parameter declaration. |
| TypeAnnotation.EmptyTarget | Indicates that an annotation appears on either the type in a field declaration, the return type of a method, the type of a newly constructed object, or the receiver type of a method or constructor. |
| TypeAnnotation.FormalParameterTarget | Indicates that an annotation appears on the type in a formal parameter declaration of a method, constructor, or lambda expression. |
| TypeAnnotation.LocalVarTarget | Indicates that an annotation appears on the type in a local variable declaration, including a variable declared as a resource in a try-with-resources statement. |
| TypeAnnotation.LocalVarTargetInfo | Indicates a range of code array offsets within which a local variable has a value, and the index into the local variable array of the current frame at which that local variable can be found. |
| TypeAnnotation.OffsetTarget | Indicates that an annotation appears on either the type in an instanceof expression or a new expression, or the type before the :: in a method reference expression. |
| TypeAnnotation.SupertypeTarget | Indicates that an annotation appears on a type in the extends or implements clause of a class or interface declaration. |
| TypeAnnotation.TargetInfo | Specifies which type in a declaration or expression is being annotated. |
| TypeAnnotation.TargetType | The kind of target on which the annotation appears, as defined in JVMS 4.7.20.1. |
| TypeAnnotation.ThrowsTarget | Indicates that an annotation appears on the i'th type in the throws clause of a method or constructor declaration. |
| TypeAnnotation.TypeArgumentTarget | Indicates that an annotation appears either 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. |
| TypeAnnotation.TypeParameterBoundTarget | Indicates that an annotation appears on the i'th bound of the j'th type parameter declaration of a generic class, interface, method, or constructor. |
| TypeAnnotation.TypeParameterTarget | Indicates that an annotation appears on the declaration of the i'th type parameter of a generic class, generic interface, generic method, or generic constructor. |
| TypeAnnotation.TypePathComponent | JVMS: Type_path structure identifies which part of the type is annotated, as defined in JVMS 4.7.20.2
|
| TypeAnnotation.TypePathComponent.Kind | Type path kind, as defined in JVMS 4.7.20.2
|
| TypeKind | Describes the data types Java Virtual Machine operates on. |
© 1993, 2025, Oracle and/or its affiliates. All rights reserved.
Documentation extracted from Debian's OpenJDK Development Kit package.
Licensed under the GNU General Public License, version 2, with the Classpath Exception.
Various third party code in OpenJDK is licensed under different licenses (see Debian package).
Java and OpenJDK are trademarks or registered trademarks of Oracle and/or its affiliates.
https://docs.oracle.com/en/java/javase/25/docs/api/java.base/java/lang/classfile/package-summary.html