8342465: Improve API documentation for java.lang.classfile

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

View file

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