JDK-8308754 : Class-File API (Preview)
  • Type: CSR
  • Component: core-libs
  • Priority: P4
  • Status: Closed
  • Resolution: Approved
  • Fix Versions: 22
  • Submitted: 2023-05-24
  • Updated: 2023-12-04
  • Resolved: 2023-12-04
Related Reports
CSR :  
Sub Tasks
JDK-8308842 :  
JDK-8308899 :  
JDK-8312491 :  
Description
Summary
-------

Provide a standard API for parsing, generating, and transforming Java class
files.  This is a [preview API](https://openjdk.org/jeps/12). 

Problem
-------

Class-file generation, parsing, and instrumentation is ubiquitous in the Java
ecosystem.  Many tools and libraries process class files, and frameworks often
perform on-the-fly bytecode instrumentation, transformation, and generation.

The Java ecosystem has many different libraries for class-file parsing and
generation, each with different design goals, strengths and weaknesses.  In the
last decade the JDK has made extensive use of the [ASM] library in its
implementation, for tasks such as lambda proxy generation.  However, there are a
number of reasons why it makes sense for the JDK to include its own
authoritative class-file library.

- _JVM evolution_ — The JVM and the class-file format are evolving much faster
now than in the early years of the platform. While some evolutions are simple,
for example adding new attributes such as `NestMembers`, others are more
complex.  Project Valhalla, for example, will bring new bytecodes and field
descriptors.  At some point it may become prohibitively expensive to evolve
existing libraries to support these new features.  A JDK class-file library can
evolve with the class-file format, reducing the friction of implementing and
testing new class-file features.

- _JDK consolidation_ — The JDK itself is a significant dealer in class files.
For historical reasons it contains four distinct internal class-file libraries:

  - A [custom library][cst.javac.jvm] in the `jdk.compiler` module, used by the
`javac` compiler and the `javadoc` tool;

  - Another [custom library][cst.classfile] in the `jdk.jdeps` module, used by
the `javap`, `jdeps`, `jdeprscan`, and `jlink` tools;

  - A fork of [BCEL] in the `java.xml` module, used in a fork of [Xalan]; and

  - A fork of [ASM] in the `java.base` module, used in the implementation of
lambdas, method handles, modules, dynamic proxies, JFR, and the `jar`, `jimage`,
`jlink`, and `jshell` tools.

  In the case of ASM, using it to implement fundamental elements of the platform
imposes a delay on the use of new class-file features.  The ASM version for
JDK _N_ cannot finalize until JDK _N_ finalizes, hence JDK tools such
as `jlink` cannot process class-file features that are new in JDK _N_,
hence `javac` cannot generate class-file features that are new in JDK _N_
until JDK _N+1_.  JDK developers need a class-file library that is kept
up-to-date with the JVM.

[cst.javac.jvm]: https://github.com/openjdk/jdk/tree/master/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm
[cst.classfile]: https://github.com/openjdk/jdk/tree/master/src/jdk.jdeps/share/classes/com/sun/tools/classfile
[BCEL]: https://commons.apache.org/proper/commons-bcel/
[Xalan]: https://xalan.apache.org/index.html

- _Version skew between frameworks and the running JDK_ — Applications which use
frameworks that process class files generally bundle a class-file library. But
new class-file features can appear in any JDK release, and the rate of JDK
releases accelerated substantially after JDK 9, so applications are more
frequently encountering class files that are newer than the library that they
bundle.  This results in runtime errors or, worse, frameworks trying to parse
class files from the future and engaging in leaps of faith that nothing too
serious has changed.  Application and framework developers need a class-file
library that they can count on to be up-to-date with the running JDK.

- _Language improvements_ — An obvious idea is to "just" merge ASM into the JDK
and take on responsibility for its ongoing maintenance, but this is not the
right choice.  ASM is an old code base with a lot of legacy baggage, it is
difficult to evolve, and the design priorities that informed its architecture
are likely not what we would choose today.  Moreover, the Java language has
improved substantially since ASM was created, so what might have been the best
API idioms in 2002 may not be ideal two decades later.


Solution
--------

Class-file API as an integral part of `java.base` module aims to address the issues. We have adopted the following design goals and principles for the API.

- _Class-file entities are represented by immutable objects_ — All class-file
entities, such as methods, fields, attributes, instructions, annotations, etc.,
are represented by immutable objects.  This facilitates reliable sharing when a
class file is being transformed.

- _Tree-structured representation_ — A class file has a tree structure.  A class
has some metadata (name, supertype, etc.), and a variable number of fields,
methods, and attributes. Fields and methods themselves have metadata and further
contain attributes, including the `Code` attribute.  The `Code` attribute
further contains instructions, exception handlers, and so forth.  The API for
navigating and building class files should reflect this structure.

- _User-driven navigation_ — The path we take through the class-file tree is
driven by user choices.  If the user cares only about annotations on fields then
we should only have to parse as far down as the annotation attributes inside the
`field_info` structure; we should not have to look into any of the class
attributes or the bodies of methods, or at other attributes of the field.  Users
should be able to deal with compound entities, such as methods, either as single
units or broken into streams of their constituent parts, as desired.

- _Laziness_ — User-driven navigation enables significant efficiencies, such as
not parsing any more of the class file than is required to satisfy the user's
needs.  If the user is not going to dive into the contents of a method then we
need not parse any more of the `method_info` structure than is needed to figure
out where the next class-file element starts. We can lazily inflate, and cache,
the full representation when the user asks for it.

- _Unified streaming and materialized views_ — Like ASM, we want to support both
a streaming and a materialized view of a class file. The streaming view is
suitable for the majority of use cases, while the materialized view is more
general since it allows random access.  We can provide a materialized view far
less expensively than ASM through laziness, as enabled by immutability.  We can,
further, align the streaming and materialized views so that they use a common
vocabulary and can be used in coordination, as is convenient for each use case.

- _Emergent transformation_ — If the class-file reading and writing APIs are
sufficiently aligned then transformation can be an emergent property that does
not require its own special mode or significant new API surface.  (ASM achieves
this by using a common visitor structure for readers and writers.)  If classes,
methods, fields, and code bodies are readable and writable as streams of
elements then a transformation can be viewed as a flat-map operation on this
stream, defined by lambdas.

- _Detail hiding_ — Many parts of a class file (constant pool, bootstrap method
table, stack maps, etc.) are derived from other parts of the class file. It
makes no sense to ask the user to construct these directly; this is extra work
for the user and increases the chance of error.  The library will automatically
generate entities that are tightly coupled to other entities based on the
methods, fields, and instructions added to the class file.

- _Lean into the language_ — In 2002, the visitor approach used by ASM seemed
clever, and was surely more pleasant to use than what came before. However, the
Java programming language has improved tremendously since then — with the
introduction of lambdas, records, sealed classes, and pattern matching — and the
platform now has a standard API for describing class-file constants
(`java.lang.constant`). We can use these to design an API that is more flexible
and pleasant to use, less verbose, and less error-prone.

Specification
-------------

The javadoc for the packages with the implementation as of November 20, 2023 is at
https://cr.openjdk.org/~asotona/JDK-8308753-preview/api/java.base/java/lang/classfile/package-summary.html

More details can be found in the JEP issue https://bugs.openjdk.org/browse/JDK-8280389

The implementation of Class-file API exports the following packages, defined in module `java.base`.

### Package `java.lang.classfile`
**Interfaces**

`AccessFlags`
: Models the access flags for a class, method, or field.

`Annotation`
: Models an annotation on a declaration.

`AnnotationElement`
: Models a key-value pair of an annotation.

`AnnotationValue`
: Models the value of a key-value pair of an annotation.

`AnnotationValue.OfAnnotation`
: Models an annotation-valued element

`AnnotationValue.OfArray`
: Models an array-valued element

`AnnotationValue.OfBoolean`
: Models a constant-valued element

`AnnotationValue.OfByte`
: Models a constant-valued element

`AnnotationValue.OfCharacter`
: Models a constant-valued element

`AnnotationValue.OfClass`
: Models a class-valued element

`AnnotationValue.OfConstant`
: Models a constant-valued element

`AnnotationValue.OfDouble`
: Models a constant-valued element

`AnnotationValue.OfEnum`
: Models an enum-valued element

`AnnotationValue.OfFloat`
: Models a constant-valued element

`AnnotationValue.OfInteger`
: Models a constant-valued element

`AnnotationValue.OfLong`
: Models a constant-valued element

`AnnotationValue.OfShort`
: Models a constant-valued element

`AnnotationValue.OfString`
: Models a constant-valued element

`Attribute<A extends Attribute<A>>`
: Models a classfile attribute 4.7.

`AttributedElement`
: A ClassFileElement describing an entity that has attributes, such as a class, field, method, code attribute, or record component.

`AttributeMapper<A>`
: Bidirectional mapper between the classfile representation of an attribute and how that attribute is modeled in the API.

`BootstrapMethodEntry`
: Models an entry in the bootstrap method table.

`BufWriter`
: Supports writing portions of a classfile to a growable buffer.

`ClassBuilder`
: A builder for classfiles.

`ClassElement`
: A ClassFileElement that can appear when traversing the elements of a ClassModel or be presented to a ClassBuilder.

`ClassFile`
: Represents a context for parsing, transforming, and generating classfiles.

`ClassFile.AttributeMapperOption`
: Option describing attribute mappers for custom attributes.

`ClassFile.ClassHierarchyResolverOption`
: Option describing the class hierarchy resolver to use when generating stack maps.

`ClassFile.Option`
: An option that affects the writing of classfiles.

`ClassFileBuilder<E extends ClassFileElement,B extends ClassFileBuilder<E,B>>`
: A builder for a classfile or portion of a classfile.

`ClassFileElement`
: Immutable model for a portion of (or the entirety of) a classfile.

`ClassFileTransform<C extends ClassFileTransform<C,E,B>,E extends ClassFileElement,B extends ClassFileBuilder<E,B>>`
: A transformation on streams of elements.

`ClassFileTransform.ResolvedTransform<E extends ClassFileElement>`
: The result of binding a transform to a builder.

`ClassFileVersion`
: Models the classfile version information for a class.

`ClassHierarchyResolver`
: Provides class hierarchy information for generating correct stack maps during code building.

`ClassModel`
: Models a classfile.

`ClassReader`
: Supports reading from a classfile.

`ClassSignature`
: Models the generic signature of a class file, as defined by 4.7.9.

`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`
: A ClassFileElement that can appear when traversing the elements of a CodeModel or be presented to a CodeBuilder.

`CodeModel`
: Models the body of a method (the Code attribute).

`CodeTransform`
: A transformation on streams of CodeElement.

`CompoundElement<E extends ClassFileElement>`
: A ClassFileElement that has complex structure defined in terms of other classfile elements, such as a method, field, method body, or entire class.

`FieldBuilder`
: A builder for fields.

`FieldElement`
: A ClassFileElement that can appear when traversing the elements of a FieldModel or be presented to a FieldBuilder.

`FieldModel`
: Models a field.

`FieldTransform`
: A transformation on streams of FieldElement.

`Instruction`
: Models an executable instruction in a method body.

`Interfaces`
: Models the interfaces of a class.

`Label`
: A marker for a position within the instructions of a method body.

`MethodBuilder`
: A builder for methods.

`MethodElement`
: A ClassFileElement that can appear when traversing the elements of a MethodModel or be presented to a MethodBuilder.

`MethodModel`
: Models a method.

`MethodSignature`
: Models the generic signature of a method, as defined by 4.7.9.

`MethodTransform`
: A transformation on streams of MethodElement.

`PseudoInstruction`
: Models metadata about a CodeAttribute, such as entries in the exception table, line number table, local variable table, or the mapping between instructions and labels.

`Signature`
: Models generic Java type signatures, as defined in 4.7.9.1.

`Signature.ArrayTypeSig`
: Models the signature of an array type.

`Signature.BaseTypeSig`
: Models the signature of a primitive type 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`
: Models a signature for a throwable type.

`Signature.TypeArg`
: Models the type argument.

`Signature.TypeParam`
: Models a signature for a type parameter of a generic class or method.

`Signature.TypeVarSig`
: Models the signature of a type variable.

`Superclass`
: Models the superclass of a class.

`TypeAnnotation`
: Models an annotation on a type use.

`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.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: Wherever a type is used in a declaration or expression, the type_path structure identifies which part of the type is annotated.

`WritableElement<T>`
: A classfile element that can encode itself as a stream of bytes in the encoding expected by the classfile format.

**Classes**

`Attributes`
: Attribute mappers for standard classfile attributes.

`CustomAttribute<T extends CustomAttribute<T>>`
: Models a non-standard attribute of a classfile.

**Enum Classes**

`ClassFile.ConstantPoolSharingOption`
: Option describing whether to preserve the original constant pool when transforming a classfile.

`ClassFile.DeadCodeOption`
: Option describing whether or not to patch out unreachable code.

`ClassFile.DeadLabelsOption`
: Option describing whether or not to filter unresolved labels.

`ClassFile.DebugElementsOption`
: Option describing whether to process or discard debug elements.

`ClassFile.LineNumbersOption`
: Option describing whether to process or discard line numbers.

`ClassFile.ShortJumpsOption`
: Option describing whether or not to automatically rewrite short jumps to long when necessary.

`ClassFile.StackMapsOption`
: Option describing whether or not to generate stackmaps.

`ClassFile.UnknownAttributesOption`
: Option describing whether to process or discard unrecognized attributes.

`Opcode`
: Describes the opcodes of the JVM instruction set, as well as a number of pseudo-instructions that may be encountered when traversing the instructions of a method.

`Opcode.Kind`
: Kinds of opcodes.

`Signature.TypeArg.WildcardIndicator`
: Indicator for whether a wildcard has default bound, no bound, an upper bound, or a lower bound

`TypeAnnotation.TargetType`
: The kind of target on which the annotation appears.

`TypeAnnotation.TypePathComponent.Kind`
: &nbsp;
 
`TypeKind`
: Describes the types that can be part of a field or method descriptor.

**Record Class**

`ClassHierarchyResolver.ClassHierarchyInfo`
: Information about a resolved class.

### Package `java.lang.classfile.attribute`
**Interfaces**



`AnnotationDefaultAttribute`
: Models the AnnotationDefault attribute 4.7.22, which can appear on methods of annotation types, and records the default value 9.6.2 for the element corresponding to this method.

`BootstrapMethodsAttribute`
: Models the BootstrapMethods attribute 4.7.23, which serves as an extension to the constant pool of a classfile.

`CharacterRangeInfo`
: Models a single character range in the CharacterRangeTableAttribute.

`CharacterRangeTableAttribute`
: The CharacterRangeTable attribute is an optional variable-length attribute in the attributes table of a Code attribute.

`CodeAttribute`
: Models the Code attribute 4.7.3, appears on non-native, non-abstract methods and contains the bytecode of the method body.

`CompilationIDAttribute`
: Models the CompilationID attribute (@@@ need reference), which can appear on classes and records the compilation time of the class.

`ConstantValueAttribute`
: Models the ConstantValue attribute 4.7.2, which can appear on fields and indicates that the field's value is a constant.

`DeprecatedAttribute`
: Models the Deprecated attribute 4.7.15, which can appear on classes, methods, and fields.

`EnclosingMethodAttribute`
: Models the EnclosingMethod attribute 4.7.7, which can appear on classes, and indicates that the class is a local or anonymous class.

`ExceptionsAttribute`
: Models the Exceptions attribute 4.7.5, which can appear on methods, and records the exceptions declared to be thrown by this method.

`InnerClassesAttribute`
: Models the InnerClasses attribute 4.7.6, which can appear on classes, and records which classes referenced by this classfile are inner classes.

`InnerClassInfo`
: Models a single inner class in the InnerClassesAttribute.

`LineNumberInfo`
: Models a single line number in the LineNumberTableAttribute.

`LineNumberTableAttribute`
: Models the LineNumberTable attribute 4.7.12, which can appear on a Code attribute, and records the mapping between indexes into the code table and line numbers in the source file.

`LocalVariableInfo`
: Models a single local variable in the LocalVariableTableAttribute.

`LocalVariableTableAttribute`
: Models the LocalVariableTable attribute 4.7.13, which can appear on a Code attribute, and records debug information about local variables.

`LocalVariableTypeInfo`
: Models a single local variable in the LocalVariableTypeTableAttribute.

`LocalVariableTypeTableAttribute`
: Models the LocalVariableTypeTable attribute 4.7.14, which can appear on a Code attribute, and records debug information about local variables.

`MethodParameterInfo`
: Models a single method parameter in the MethodParametersAttribute.

`MethodParametersAttribute`
: Models the MethodParameters attribute 4.7.24, which can appear on methods, and records optional information about the method's parameters.

`ModuleAttribute`
: Models the Module attribute 4.7.25, which can appear on classes that represent module descriptors.

`ModuleAttribute.ModuleAttributeBuilder`
: &nbsp;

`ModuleExportInfo`
: Models a single "exports" declaration in the ModuleAttribute.

`ModuleHashesAttribute`
: Models the ModuleHashes attribute, which can appear on classes that represent module descriptors.

`ModuleHashInfo`
: Models hash information for a single module in the ModuleHashesAttribute.

`ModuleMainClassAttribute`
: Models the ModuleMainClass attribute 4.7.27, which can appear on classes that represent module descriptors.

`ModuleOpenInfo`
: Models a single "opens" declaration in the ModuleAttribute.

`ModulePackagesAttribute`
: Models the ModulePackages attribute 4.7.26, which can appear on classes that represent module descriptors.

`ModuleProvideInfo`
: Models a single "provides" declaration in the ModuleAttribute.

`ModuleRequireInfo`
: Models a single "requires" declaration in the ModuleAttribute.

`ModuleResolutionAttribute`
: Models the ModuleResolution attribute, which can appear on classes that represent module descriptors.

`ModuleTargetAttribute`
: Models the ModuleTarget attribute, which can appear on classes that represent module descriptors.

`NestHostAttribute`
: Models the NestHost attribute 4.7.28, which can appear on classes to indicate that this class is a member of a nest.

`NestMembersAttribute`
: Models the NestMembers attribute 4.7.29, which can appear on classes to indicate that this class is the host of a nest.

`PermittedSubclassesAttribute`
: Models the PermittedSubclasses attribute 4.7.31, which can appear on classes to indicate which classes may extend this class.

`RecordAttribute`
: Models the Record attribute 4.7.30, which can appear on classes to indicate that this class is a record class.

`RecordComponentInfo`
: Models a single record component in the RecordAttribute.

`RuntimeInvisibleAnnotationsAttribute`
: Models the RuntimeInvisibleAnnotations attribute 4.7.17, which can appear on classes, methods, and fields.

`RuntimeInvisibleParameterAnnotationsAttribute`
: Models the RuntimeInvisibleParameterAnnotations attribute 4.7.19, which can appear on methods.

`RuntimeInvisibleTypeAnnotationsAttribute`
: Models the RuntimeInvisibleTypeAnnotations attribute 4.7.21, which can appear on classes, methods, fields, and code attributes.

`RuntimeVisibleAnnotationsAttribute`
: Models the RuntimeVisibleAnnotations attribute 4.7.16, which can appear on classes, methods, and fields.

`RuntimeVisibleParameterAnnotationsAttribute`
: Models the RuntimeVisibleParameterAnnotations attribute 4.7.18, which can appear on methods.

`RuntimeVisibleTypeAnnotationsAttribute`
: Models the RuntimeVisibleTypeAnnotations attribute 4.7.20, which can appear on classes, methods, fields, and code attributes.

`SignatureAttribute`
: Models the Signature attribute 4.7.9, which can appear on classes, methods, or fields.

`SourceDebugExtensionAttribute`
: SourceDebugExtensionAttribute.

`SourceFileAttribute`
: Models the SourceFile attribute 4.7.10, which can appear on classes.

`SourceIDAttribute`
: Models the SourceFile attribute (@@@ reference needed), which can appear on classes.

`StackMapFrameInfo`
: Models stack map frame of StackMapTable attribute 4.7.4.

`StackMapFrameInfo.ObjectVerificationTypeInfo`
: A stack value for an object type.

`StackMapFrameInfo.UninitializedVerificationTypeInfo`
: An uninitialized stack value.

`StackMapFrameInfo.VerificationTypeInfo`
: The type of a stack value.

`StackMapTableAttribute`
: Models the StackMapTable attribute 4.7.4, which can appear on a Code attribute.

`SyntheticAttribute`
: Models the Synthetic attribute 4.7.8, which can appear on classes, methods, and fields.

`UnknownAttribute`
: Models an unknown attribute on a class, method, or field.

**Enum Class**

`StackMapFrameInfo.SimpleVerificationTypeInfo`
: A simple stack value.

### Package `java.lang.classfile.components`
**Interfaces**

`ClassPrinter.LeafNode`
: A leaf node holding single printable value.

`ClassPrinter.ListNode`
: A tree node holding List of nested nodes.

`ClassPrinter.MapNode`
: A tree node holding Map of nested nodes.

`ClassPrinter.Node`
: Named, traversable, and printable node parent.

`ClassRemapper`
: ClassRemapper is a ClassTransform, FieldTransform, MethodTransform and CodeTransform deeply re-mapping all class references in any form, according to given map or map function.

`CodeLocalsShifter`
: CodeLocalsShifter is a CodeTransform shifting locals to newly allocated positions to avoid conflicts during code injection.

`CodeRelabeler`
: A code relabeler is a CodeTransform replacing all occurrences of Label in the transformed code with new instances.

`CodeStackTracker`
: CodeStackTracker is a CodeTransform tracking stack content and calculating max stack size.

**Class**

`ClassPrinter`
: A printer of classfiles and its elements.

**Enum Class**

`ClassPrinter.Verbosity`
: Level of detail to print or export.

### Package `java.lang.classfile.constantpool`
**Interfaces**

`AnnotationConstantValueEntry`
: A constant pool entry that may be used as an annotation constant, which includes the four kinds of primitive constants, and UTF8 constants.

`ClassEntry`
: Models a CONSTANT_Class_info constant in the constant pool of a classfile.

`ConstantDynamicEntry`
: Models a CONSTANT_Dynamic_info constant in the constant pool of a classfile.

`ConstantPool`
: Provides read access to the constant pool and bootstrap method table of a classfile.

`ConstantPoolBuilder`
: Builder for the constant pool of a classfile.

`ConstantValueEntry`
: Models a constant pool entry that can be used as the constant in a ConstantValue attribute; this includes the four primitive constant types and String constants.

`DoubleEntry`
: Models a CONSTANT_Double_info constant in the constant pool of a classfile.

`DynamicConstantPoolEntry`
: Models a dynamic constant pool entry, which is either ConstantDynamicEntry or InvokeDynamicEntry.

`FieldRefEntry`
: Models a CONSTANT_Fieldref_info constant in the constant pool of a classfile.

`FloatEntry`
: Models a CONSTANT_Float_info constant in the constant pool of a classfile.

`IntegerEntry`
: Models a CONSTANT_Integer_info constant in the constant pool of a classfile.

`InterfaceMethodRefEntry`
: Models a CONSTANT_InterfaceMethodRef_info constant in the constant pool of a classfile.

`InvokeDynamicEntry`
: Models a constant pool entry for a dynamic call site.

`LoadableConstantEntry`
: Marker interface for constant pool entries suitable for loading via the LDC instructions.

`LongEntry`
: Models a CONSTANT_Long_info constant in the constant pool of a classfile.

`MemberRefEntry`
: Models a member reference constant in the constant pool of a classfile, which includes references to fields, methods, and interface methods.

`MethodHandleEntry`
: Models a CONSTANT_MethodHandle_info constant in the constant pool of a classfile.

`MethodRefEntry`
: Models a CONSTANT_MethodRef_info constant in the constant pool of a classfile.

`MethodTypeEntry`
: Models a CONSTANT_MethodType_info constant in the constant pool of a classfile.

`ModuleEntry`
: Models a CONSTANT_Module_info constant in the constant pool of a classfile.

`NameAndTypeEntry`
: Models a CONSTANT_NameAndType_info constant in the constant pool of a classfile.

`PackageEntry`
: Models a CONSTANT_Package_info constant in the constant pool of a classfile.

`PoolEntry`
: Models an entry in the constant pool of a classfile.

`StringEntry`
: Models a CONSTANT_String_info constant in the constant pool of a classfile.

`Utf8Entry`
: Models a CONSTANT_UTF8_info constant in the constant pool of a classfile.

### Package `java.lang.classfile.instruction`
**Interfaces**

`ArrayLoadInstruction`
: Models an array load instruction in the code array of a Code attribute.

`ArrayStoreInstruction`
: Models an array store instruction in the code array of a Code attribute.

`BranchInstruction`
: Models a branching instruction (conditional or unconditional) in the code array of a Code attribute.

`CharacterRange`
: A pseudo-instruction which models a single entry in the CharacterRangeTableAttribute.

`ConstantInstruction`
: Models a constant-load instruction in the code array of a Code attribute, including "intrinsic constant" instructions (e.g., iconst_0), "argument constant" instructions (e.g., bipush), and "load constant" instructions (e.g., LDC).

`ConstantInstruction.ArgumentConstantInstruction`
: Models an "argument constant" instruction (e.g., bipush).

`ConstantInstruction.IntrinsicConstantInstruction`
: Models an "intrinsic constant" instruction (e.g., iconst_0).

`ConstantInstruction.LoadConstantInstruction`
: Models a "load constant" instruction (e.g., ldc).

`ConvertInstruction`
: Models a primitive conversion instruction in the code array of a Code attribute, such as i2l.

`DiscontinuedInstruction`
: Models instruction discontinued from the code array of a Code attribute.

`DiscontinuedInstruction.JsrInstruction`
: Models JSR and JSR_W instructions discontinued from the code array of a Code attribute since class file version 51.0.

`DiscontinuedInstruction.RetInstruction`
: Models RET and RET_W instructions discontinued from the code array of a Code attribute since class file version 51.0.

`ExceptionCatch`
: A pseudo-instruction modeling an entry in the exception table of a code attribute.

`FieldInstruction`
: Models a field access instruction in the code array of a Code attribute.

`IncrementInstruction`
: Models a local variable increment instruction in the code array of a Code attribute.

`InvokeDynamicInstruction`
: Models an invokedynamic instruction in the code array of a Code attribute.

`InvokeInstruction`
: Models a method invocation instruction in the code array of a Code attribute, other than invokedynamic.

`LabelTarget`
: A pseudo-instruction which indicates that the specified label corresponds to the current position in the Code attribute.

`LineNumber`
: A pseudo-instruction which models a single entry in the LineNumberTableAttribute.

`LoadInstruction`
: Models a local variable load instruction in the code array of a Code attribute.

`LocalVariable`
: A pseudo-instruction which models a single entry in the LocalVariableTableAttribute.

`LocalVariableType`
: A pseudo-instruction which models a single entry in the LocalVariableTypeTableAttribute.

`LookupSwitchInstruction`
: Models a lookupswitch instruction in the code array of a Code attribute.

`MonitorInstruction`
: Models a monitorenter or monitorexit instruction in the code array of a Code attribute.

`NewMultiArrayInstruction`
: Models a multianewarray invocation instruction in the code array of a Code attribute.

`NewObjectInstruction`
: Models a new instruction in the code array of a Code attribute.

`NewPrimitiveArrayInstruction`
: Models a newarray invocation instruction in the code array of a Code attribute.

`NewReferenceArrayInstruction`
: Models a anewarray invocation instruction in the code array of a Code attribute.

`NopInstruction`
: Models a nop invocation instruction in the code array of a Code attribute.

`OperatorInstruction`
: Models an arithmetic operator instruction in the code array of a Code attribute.

`ReturnInstruction`
: Models a return-from-method instruction in the code array of a Code attribute.

`StackInstruction`
: Models a stack manipulation instruction in the code array of a Code attribute.

`StoreInstruction`
: Models a local variable store instruction in the code array of a Code attribute.

`SwitchCase`
: Models a single case in a lookupswitch or tableswitch instruction.

`TableSwitchInstruction`
: Models a tableswitch instruction in the code array of a Code attribute.

`ThrowInstruction`
: Models an athrow instruction in the code array of a Code attribute.

`TypeCheckInstruction`
: Models an instanceof or checkcast instruction in the code array of a Code attribute.


Comments
Thank you!
04-12-2023

Moving to Approved as a Preview API, serving as the nominal reviewer. Good to see this API progress; I'd expect to have other rounds of comments before the API ships as a non-preview API in the future.
04-12-2023

Two new transformation snippets have been added to the packgage-info + minor javadoc corrections.
20-11-2023

Two possible reactions of user transformation on a new element received (coming from future JDK when parsing future class file version) have been already described (see [javadoc][1]): - Pass an unknown element through - Fail on an unknown class file element when it appears Now I see a request to handle even potential threat of a new element that may appear. I can add another two possible "early" reactions to the above javadoc paragraph: - Fail when parsing a class file with version higher than the transform has been designed for: ``` if (el instanceof ClassFileVersion v && v.majorVersion() > ClassFile.JAVA_22_VERSION) throw... ``` - Fail immediately when the transform is executed on a higher JDK version than designed for: ``` if (ClassFile.latestMajorVersion() > ClassFile.JAVA_22_VERSION) throw... ``` [1]: https://cr.openjdk.org/~asotona/JDK-8308753-preview/api/java.base/java/lang/classfile/package-summary.html#transformation-handling-of-unknown-classfile-elements-heading
01-11-2023

PS As a concrete suggestion, to gain confidence on handling future constructs, if it has not already been done, I recommend working through the the consequences of adding each new kind of entity in the class file API, new instruction, new attribute, etc. (For `javax.lang.model` we did validate the design could handle adding a new top-level construct, like modules, before GA, but didn't work through in as much detail adding a new kind of an existing element, such as a record being a new kind of class. We were able to accommodate the smaller additions with the model too, but it would have been good to have worked through more of the detail ahead of time.)
31-10-2023

I think the analogue of `Processor` here is closer to `Classfile`; all classfile operations have a trail of breadcrumbs back to `Classfile`. I would definitely also be negative about ballooning `Transform` past its very simple flatmappy interface here, though adding some more options to communicate "highest understood version" and how to handle mismatches to the `Classfile` options is not so disruptive. The API already (almost) lets the client ask "what's the maximum classfile version"; there's a static final field `Classfile.LATEST_MAJOR_VERSION`, which, because of inlining, is the latest version _as of the time the client was compiled_. The latest version supported by the library is always the currently running version, which is available from other places but we could reasonably add a static method to `Classfile` to return it in the convenient form. As to "what if the library yields elements that are unknown to an older client", our answer to this is that we are building on sealed types, and so the answer here is not specific to the classfile library, but a more general question of designing APIs evolveable through sealed types. To which the answer is pretty reasonable; clients can choose between "the easy default" (which might end up throwing MatchException out of a switch if a novel subtype shows up) and a more proactive handling of novel subtypes.
31-10-2023

To clarify my points, I would consider a processor/transformer to be a partial function if it threw an exception for some inputs and returned normally for other inputs. Again to use an analogy with annotation processing, the `javax.lang.model` API for a particular JDK fully supports whatever language version is native to that JDK -- language changes "from the future" will just get rejected by `javac`. However, that of course does not imply that any processors that may run on that JDK also know about the same language versions as that JDK supports. It seems to me that the processors/transformers would benefit from a distinct mechanism to signal "I may need to be updated." In `javax.lang.model`, the various unknown entity exception types play that role. Since visitors happen to be used as the recommended dispatching mechanism in `javax.lang.model`, visitors defined in the API are specified to throw the unknown entity exceptions in various circumstances, but that throwing occurs _on behalf of user-code_. The annotation processing implementation itself, i.e. javac, does not throw those exceptions.
31-10-2023

I agree it might be better to arrange a meeting, however short comments may enlighten the API handling of compatibility. According to your definition of a processor is ClassFileTransform always a full function and can never be just a partial. It is a functional interface and it must respond to all received instances of ClassFileElement, whether they are known or coming from a future JDK version. And because there are no partial transformations, ClassFile API does not have any mechanics turning them into a total function. Absence of such mechanics allows ClassFile API to be agnostic to the transformations and may use them without any further knowledge. Comments to the three goals you pointed out: 1. Completeness of the API has been partly triaged on JDK use cases (see [JDK-8294957][1]) and any enhancements are welcome to discussion. 2. Transformations are functional interfaces mostly expected to be implemented as lambdas. Inheritance of transformations is unexpected and there is no support for inheritance-based abstraction of transformations in the API. Transformations can be chained, composed, layered and there are plenty of API methods supporting these principles. 3. There are no unknown entities expected for the ClassFile API as it is in sync with the JDK and it refuses to parse future versions of class files (similar as class loaders refuse to load them). ClassFile API treats all user-provided transformations agnostically. Providing special exception types for the only purpose to be suggested to users (to be thrown in certain situations) seems to me confusing. Such exception have no use in the ClassFile API, no special handling, no meaning for the API and no use for any API application across the JDK. Existence of such exceptions in the API may confuse users thinking they have some special handling or meaning. ClassFile API unifies on IllegalArgumentException (and its subtypes) for situations where a class file corruption is identified while parsing. [1]: https://bugs.openjdk.org/browse/JDK-8294957
31-10-2023

Might be better to discuss this topic in a meeting, until such a meeting is arranged, if needed, some additional background on the matter. There are high-level similarities between the class file API and portions of both generations of annotation processing APIs, first `apt` in JDK 5.0 and then `javax.lang.model` in JDK 6 and later revisions. Both the class file API and annotation processing have an API model of some structured entity (class file and Java programming language declarations, respectively) and provide various facilities for user-written "processors" to inspect the model and take various actions in response. Of course, many of the details differ. The intention of this discussion is to allow the class file API to benefit from prior experience maintaining the `javax.lang.model` API over time without having to first relive that experience ;-) One of the main technical differences between apt and `javax.lang.model` was that `apt` made no attempt to represent multiple language levels and had no facilities for or plan to migrate processors from old language levels to new ones. As a point of comparison, at the time of writing the `javax.lang.model` API includes: - On the Processor interface, a method so the _environment_ can query the latest language level supported _by the processor_ - Environmental queries so _processors_ can find the source version being used _by the environment_, as well as preview-enabled status. - Facilities to cope with the expression problem (https://en.wikipedia.org/wiki/Expression_problem) in the visitors; tl;dr the API includes a series of versioned visitors where a visitor for version $N by default throws an exception if it comes across something from version $(N+1) or later. In abstract terms, a processor can be thought of as a total function over the set of possible inputs up to version $V, the latest version it supports. For versions ($V + k), in principle the processor is a partial function of the new kinds of structures. It is impossible to "do the right thing" in all cases when turning a partial function into a total function because it depends on the semantics of the processor. I think the key points of the policy are: 1. provide enough information in the API for the processors to get the information they need to make a decision 2. provide API support for a reasonable default, a default that can be entirely overridden or ignored at the user's option 3. provide defined exception types for when various "unknown entities" are encountered My guidance is to achieve these three goals in a way consistent with the overall design of the class file API (suitable for pattern matching, etc.)
31-10-2023

As a result of earlier review comments, we decided to actually _roll back_ on attempts to perform validation of attributes and other classfile metadata based on version numbers; we felt we could not do an even decent job, and doing a bad job was worse than doing nothing. These comments are aimed at the other end of the compatibility pipeline, which is about what happens when an "old" client runs on a "new" classfile. And the answer is: it very much depends what they are doing. Many clients are interested only in coarse-grained metadata such as class hierarchy information; it would be a shame to fail them out of the gate because the client is older than the library. ASM has tried to version their API to address this, but this hasn't been all that great either. So our approach has been that the library will reflect the classfile into objects according to the JVMS that governs the currently running JDK, and clients get to decide what to do if they encounter something "from the future". Currently, the library does not even know what classfile constructs are understood by a given client -- there is no "I am aware of versions up to X" parameter when creating a classfile context -- so we would not even know when to throw such a FromFutureException. And I'm not convinced that requiring such information of the client is a winning move either. I think it is a reasonable area for future exploration to investigate whether optionally adding such information would allow the library to perform better validation, but I don't see an obviously beneficial concrete action right now.
26-10-2023

Hi [~asotona], yes among the dozens (hundreds?) of new types proposed in this API, I think there can be room for a handful of exception types intended for use by clients of the API.
26-10-2023

I see your concerns. Do you suggest to add a special exception type to the API, despite the fact it will not be used anywhere inside the API, implementation and JDK?
26-10-2023

[~asotona], a few more thoughts on this point. While it is true that the user-written instrospector/transformer has the freedom to take any action in response to "future" inputs, that does not imply the class file API should not provide guidance and/or API support for taking a particular action in that situation. Especially if a collection of instrospectors/transformers are envisioned to be composed by a third party, I think it would be helpful to get particular exceptions "throw new FutureClassFileConstructFound("try to upgrade your instrospector/transformer" to a later version.")" rather than a unspecialized IllegalArgumentException or similar result.
25-10-2023

Thanks [~darcy] for the review comments. Let me address your concerns about user-written introspectors/transformers running on "future" versions of the JDK, parsing "future" versions of class files. The whole architecture of the API is based on tree of (sealed) interfaces representing individual class file elements (members, attributes, instructions, etc...). Any user-written introspector represents a consumer of a class file element, and each transformer represents a bi-consumer of an element and a builder. This architecture is completely future-proof and caller of an instrospector/transformer does not assume any compatibility (and so does not throw any exception directly). Compatibility constraints of user-written instrospectors/transformers is purely up to the user decision. A user-written introspector/transformer may receive an unknown (at the time of its compilation) class file element and it is up to the user code how to react (whether to pass an unknown element by or throw and what exception to throw). Two possible reactions are described at: https://cr.openjdk.org/~asotona/JDK-8308753-preview/api/java.base/java/lang/classfile/package-summary.html#transformation-handling-of-unknown-classfile-elements-heading
25-10-2023

Moving to Provisional, not Approved. Before the request is Approved, I expect I'll have several more rounds of comments.
25-10-2023

A further comment on the evolution of user-written introspectors and transformers. Let's say user-written introspectors/transformer is written against class file format (major) version N. What should happen if the introspector/transformer is presented with a class file of major version (N+1) on JDK (N+1)? A true, but not immediately helpful answer is "it depends." To be clear, the host JDK fully supports version (N+1), the question is the semantics of the client of the class file API that were written to an earlier iteration of the API. Depending on the semantics of the introspector/transformer, sometimes the appropriate result would be to simply ignore the new attributes, instructions, etc. In other circumstances, some kind of exception should be thrown by the introspectors/transformer it indicate it cannot properly handle the new entities. For this latter case, I believe one or more exceptions should be defined in the API for introspectors/transformers to signal something they came across is out-of-bounds for their semantics.
25-10-2023

I've applied suggestions from pull request for better phrasing of some of the package info paragraphs.
12-10-2023

I've added @sealedGraph tag to all sealed interfaces with API-exposed subtypes and the latest attached specdiffs contain the graphs. Also onlinejavadoc has been updated with the graphs. Thank you for all the reviews.
10-10-2023

Exceptions thrown from ClassFile API has been unified on `IllegalArgumentException` or its more specific subclasses (`ConstantPoolException`). An attempt to introduce a custom sub-tree of exceptions failed on very complicated try-catching and wrapping of `IllegalArgumentException`s thrown from other parts of the Java SE API used by ClassFile API.
09-10-2023

> On the topic of future proofing, I strongly suggest a specific new unchecked exception be added to the class file API to indicate a "from the future" class file structure was encountered. This would be analagous to javax.lang.model.UnknownEntityException and its sub-exceptions. Iteration through possible compatibility scenarios revealed that the library already covers most (but not all) cases: - As the library is a part of java.base, there is basic assumption that it knows all elements from the actual and all previous versions of the JDK. - User parsing or transformation code may be compiled with older version of the library/JDK and running on the newer JDK. Architecture of the library allows user to decide what strategy to use and optionally what exception to throw (this is out of the library scope). - The only unhandled case is when trying to parse/transform a classfile with version higher than the actual library/JDK knows. This scenario assumes existence of a newer JDK (where the classfile came from) than the actual JDK used for parsing/transformation. I propose to throw `IllegalArgumentException` immediately when the unknown classfile version is observed. Existence of a newer JDK allows us to be strict, refuse parsing classfiles from a future and recommend to use the newer JDK. When considering unknown elements from the internal perspective, there are following scenarios: - an unknown attribute appears (matching no known or user-provided mappers) - the library can continue parsing and such attribute is processed according to `AttributesProcessingOption` - an unknown constant pool entry appears - the library cannot continue parsing because it does not know the entry size and `ConstantPoolException` (subclass of `IllegalArgumentException`) is thrown - an unknown instruction appears during explosion of the `Code` attribute - the library cannot continue and `UnsupportedOperationException` is thrown - this case will be unified with the rest of the library to throw `IllegalArgumentException` or its subclass. - a structure of the classfile is corrupted or any other way incompatible - the library cannot continue and also throws `IllegalArgumentException` or its subclass (we should do more testing of this to safely cover all possible ways of the classfile corruption).
09-10-2023

> PS If it is not already being used, given the prevalence of sealed hierarchies in this this API, I recommend considering use of the @sealedGraph javadoc tag. (If it is already being used, it might not be being displayed in the specdiffs I looked at.) Thanks for catching this, I'll double check why the graphs are missing. The @sealedGraph tag is currently present in the root sealed interfaces: `ClassFileBuilder`, `ClassFileElement`, `ClassFileTransform`, `ConstantPool` and `Signature`. Do you think the tag should be added also to all sub-interfaces?
09-10-2023

> Even if the default answer is "sealed interface", I don't think that should imply "never any records." Right, however in this case the `ClassFileVersion` is also a `ClassElement` and its implementation extends `impl.AbstractElement`. This flexibility in implementation would not be possible if the API elements are records.
09-10-2023

> Adding start and end methods introduces the notion that the attributes can go away at some point in the future. As alluded to elsewhere, the ACC_STRICT flag has been retired and is no longer recognized as of JDK 17 so there is precedence for this sort of change in the access flags space. Part of some older mailing list discussion was this kind of JVMS info exposure through the API with no practical use. The unrealized result of the discussion was to remove `AttributeMapper::validSince` method. The library is agnostic in parsing and transformations and it does not perform any attributes checks based on the classfile version. Exposition of the JVMS info fragments through the API is not a goal. Here I would like to realize the original plan, remove also `AttributeMapper::validSince` method and add relevant information to the attributes javadoc instead.
09-10-2023

PS If it is not already being used, given the prevalence of sealed hierarchies in this this API, I recommend considering use of the `@sealedGraph` javadoc tag. (If it is already being used, it might not be being displayed in the specdiffs I looked at.)
06-10-2023

> Would ClassFileVersion be better as a record rather than an interface? > > General decision was to prefer sealed interface. Even if the default answer is "sealed interface", I don't think that should imply "never any records."
06-10-2023

> AttributeMapper: Add validUntil? default to most recent version? > > Do we have any use case for that already? So don't think it is unreasonable to anticipate possible future needs and include them in the initial design (taking into account YAGNI -- "you aint gonna' need it" sentiments, etc., as appropriate). Adding start and end methods introduces the notion that the attributes can go away at some point in the future. As alluded to elsewhere, the ACC_STRICT flag has been retired and is no longer recognized as of JDK 17 so there is precedence for this sort of change in the access flags space.
05-10-2023

On the topic of future proofing, I strongly suggest a specific new unchecked exception be added to the class file API to indicate a "from the future" class file structure was encountered. This would be analagous to javax.lang.model.UnknownEntityException and its sub-exceptions.
05-10-2023

Incremental and full specdiffs with fixes are attached. Online javadoc at https://cr.openjdk.org/~asotona/JDK-8308753-preview/api/java.base/java/lang/classfile/package-summary.html is also updated. Thank you.
05-10-2023

> Should ClassModel have a single classFileVersion method has opposed to a pair of majorVersion()/minorVersion() methods? majorVersion and minorVersion methods are convenient shortcuts, while an instance of ClassFileVersion is one of the class elements streamed and transformed. Convenient methods have been considered and selected individually, so they may not follow the same pattern. There have been long discussions about what to include in the conveniences and what can be accessible only by class elements traverse. Majority of the use cases led to the majorVersion question only, so reading also minor version and construction of ClassFileVersion instance seems to be obsolete. However it is possible to re-open this discussion at the mailing list and change it (or add it). > Shouldn't ClassReader have a Set accessFlags() method? This method is available for ClassModel. ClassReader is exposed mainly to support user-provided custom attribute mappers. > CustomAttribute -- I assume something went awry in the docs run. Oops, I'll fix it, thanks for catching it. > If there is an Opcode enum, does the API need a separate list of public static int with the opcode value? We run through several iterations trying to spread constants across related classes or aggregate them in a dedicated class. Final decision after these attempts was to co-locate all constants in ClassFile. Main reasons for that decision were reachability, low learning step and minimal set of imports necessary. Despite our effort to avoid direct use of constants by users, the reality is different and having them in one place is better then spread across many classes. > Can the ClassPrinter printed have additional methods to return some kind of schema/grammar for the each of the JSON, XML, YAML methods to follow? That is good idea. It would be worth to collect related use cases and evaluate how such "dynamic" schema helps them.
05-10-2023

Thank you for the review! I've added my comments below and fixes will follow. > AccessFlags -- versioning of of$FOO methods -- "according to latest class file format version"... for decoding AFAIK, Valhalla is planning to reuse the ACC_STRICT bit position so there won't be a one-to-one mapping from kind-of-entity to what an access flag being set means. Yes, this can be added, however primary source of version-aware access flags is `java.lang.reflect.AccessFlag::maskToAccessFlags`, more specifically there is missing method override accepting ClassFileFormatVersion. Actually it is only possible to get flags for the latest class file format version. I would prefer to solve this topic in a separate CSR extending `java.lang.reflect.AccessFlag` and `java.lang.classfile.AccessFlags`. > java.lang.classfile.Annotation -- include helper methods in interface definition :-| Maybe not the best name? Can you, please, point me to the helper methods you see in `java.lang.classfile.Annotation`? > Are there plans to add repeating annotation support in the future? I'm not aware of that plans yet, however definitely possible. All work on extensions of the high-level API conveniences have been temporary deferred. It is important to see public response first and evaluate the most required extensions before letting the API to grow too much. > AnnotationValue.of Returns an annotation element. The value parameter must be a primitive, a String, a ClassDesc, an enum constant, or an array of one of these. (Object value) And what if it isn't? Illegal argument exception? Primitive or wrapper of primitive, technically. Yes, there is missing important part of the javadoc. I'll add it, thanks for catching it. > AttributeMapper: Add validUntil? default to most recent version? Do we have any use case for that already? > BufWriter typo: "Method are provided" rather than " Method*s* are provided..." I'll fix it, thanks for catching it. > In the API, interfaces like ClassElement serve to mark which subinterfaces are for class elements. I suggest changing the javadoc to make this intention explicit "A marker interface for elements that can appear..." I'll apply you suggestion, thanks. > A bit unusual to see so may static ints defined in the ClassFile interface. Also the fields don't seem to have informative javadoc. "The integer value used to encode the AALOAD instruction." etc. Yes, this part of the javadoc requires more attention. I'll fix it, thanks. > Would ClassFileVersion be better as a record rather than an interface? General decision was to prefer sealed interface.
05-10-2023

> This is a more general comment ahead of more specific comments on the current draft. I think the API needs a bit more explicit attention paid to the possibility of incompatible class file changes being made in the future. In particular, at some point I'd like to see worked examples on what readers / writers would look like when encountering new kinds of class file entities created after the readers / writers were authored. In part, this guidance stems from experience in the JSR 269 annotation processing API were accommodations to unknown future language changes was a key component of the API compared to its apt predecessor. Right, future changes is very important topic. Here is a paragraph added to the package javadoc showing two different approaches for user-built transformations: [java.base/java/lang/classfile/package-summary.html#transformation-handling-of-unknown-classfile-elements-heading][1] Transformation represents combination of reader and writer, so the same principles apply. [1]: https://cr.openjdk.org/~asotona/JDK-8308753-preview/api/java.base/java/lang/classfile/package-summary.html#transformation-handling-of-unknown-classfile-elements-heading
05-10-2023

Part 2: Should ClassModel have a single classFileVersion method has opposed to a pair of majorVersion()/minorVersion() methods? Shouldn't ClassReader have a Set<AccessFlag> accessFlags() method? CustomAttribute -- I assume something went awry in the docs run. If there is an Opcode enum, does the API need a separate list of public static int with the opcode value? Can the ClassPrinter printed have additional methods to return some kind of schema/grammar for the each of the JSON, XML, YAML methods to follow? Please plan to provide both an increment specdiff and a full specdiff for future revisions. Thanks.
05-10-2023

Part 1 of the next round of comments: AccessFlags -- versioning of of$FOO methods -- "according to latest class file format version"... for decoding AFAIK, Valhalla is planning to reuse the ACC_STRICT bit position so there won't be a one-to-one mapping from kind-of-entity to what an access flag being set means. java.lang.classfile.Annotation -- include helper methods in interface definition :-| Maybe not the best name? Are there plans to add repeating annotation support in the future? AnnotationValue.of Returns an annotation element. The value parameter must be a primitive, a String, a ClassDesc, an enum constant, or an array of one of these. (Object value) And what if it isn't? Illegal argument exception? Primitive or wrapper of primitive, technically. AttributeMapper: Add validUntil? default to most recent version? BufWriter typo: "Method are provided" rather than " Method**s** are provided..." In the API, interfaces like ClassElement serve to mark which subinterfaces are for class elements. I suggest changing the javadoc to make this intention explicit "A marker interface for elements that can appear..." A bit unusual to see so may static ints defined in the ClassFile _interface_. Also the fields don't seem to have informative javadoc. "The integer value used to encode the AALOAD instruction." etc. Would ClassFileVersion be better as a record rather than an interface?
05-10-2023

This is a more general comment ahead of more specific comments on the current draft. I think the API needs a bit more explicit attention paid to the possibility of incompatible class file changes being made in the future. In particular, at some point I'd like to see worked examples on what readers / writers would look like when encountering new kinds of class file entities created after the readers / writers were authored. In part, this guidance stems from experience in the JSR 269 annotation processing API were accommodations to unknown future language changes was a key component of the API compared to its apt predecessor.
04-10-2023

Added incremental specdiff with changes based on https://github.com/openjdk/jdk/pull/15706 conversation.
03-10-2023

I've added trimmed javadoc (all packages except java.lang.classfile.** excluded to reduce zip size) and initial specdiff.
02-10-2023

[~asotona], for archival purposes, please attach some kind of stand-alone representation of the API, such as a tar or zip of the javadoc output or a specdiff of the changes.
30-09-2023

According to JEP discussion I've updated all `Classfile*` classes and interfaces to `ClassFile* `.
25-09-2023

Online javadoc link above is up-to-date. I hope I addressed all comments, so setting this CSR back to `PROPOSED`.
21-09-2023

Regarding the int -> AccessFlags conversion we depend on `java.lang.reflect.AccessFlag:maskToAccessFlags(int mask, Location location)`, however a new method `java.lang.reflect.AccessFlag:maskToAccessFlags(int mask, Location location, ClassFileFormatVersion cffv)` would be necessary to add to be able to reflect classfile version for the conversions.
21-09-2023

Regarding the consistency checks and constraints I've added package info paragraph [Consistency checks, syntax checks and verification][1] and improved javadoc on multiple places, see [commit][2] [1]: https://cr.openjdk.org/~asotona/JDK-8308753-preview/api/java.base/java/lang/classfile/package-summary.html#consistency-checks-syntax-checks-and-verification-heading [2]: https://github.com/openjdk/jdk/pull/15706/commits/8d23c465f12cf3cf77a2e44466aadb95764cb105
21-09-2023

Added package doc section [Transformation handling of unknown classfile elements from a future][1] [1]: https://cr.openjdk.org/~asotona/JDK-8308753-preview/api/java.base/java/lang/classfile/package-summary.html#transformation-handling-of-unknown-classfile-elements-from-a-future-heading
20-09-2023

I've tried to create a visual description of a classfile structure, however I could not find the right place for it in the Classfile API javadoc. The visual should be probably a part of the JVMS (as it describes the classfile structure), however placing it into the Classfile API documentation is rather confusing. When placed in the Classfile API javadoc it looks more like an attempt to inaccurately re-specify some parts of the JVMS and without direct relation to Classfile API. Direct links to JVMS are clear, however JVMS-interpreting schematics are more confusing than helping. I would appreciate more info about desired content of the paragraphs describing content of the classfile.
20-09-2023

Hi [~darcy], thanks for the comments. They are now being addressed. > The API feature extensive use of sealed interfaces. For non sealed interfaces with default methods, it is important to use an implSpec tag to specify the behavior. This is less important for sealed interface since there is more control over instantiation; however, some kind of note about the behavior would still be appropriate. I've added `@implSpec` tags to all default methods of non-sealed interfaces (namely `AttributeMapper`, `ClassHierarchyResolver`, `ClassTransform`, `CodeTrasform`, `FieldTransform` and `MethodTransform`). It will be visible in the javadoc link above after refresh. > The various "of" methods to created instance of objects from various arguments are largely silent on what consistency checks, if any, are implemented by the API. Some mention of this is appropriate for an API in the JDK. If the basic of method do check, there could be overloads taking a ClassFileFormatVersion argument that do, or a separate validate(ClassFileFormatVersion cffv) method, etc. Yes, consistency checks inspection and documentation is now in progress. > I suggest expanding the package-level discussion a bit, including a high-level paragraph or two discussing of the structure of a class file in more detail. Yes, I will add some more visual description of the class file structure. > How would language compilers targeting the JVM define and use custom attributes using this API? (Perhaps this is not a supported use case.) There is already a paragraph in the package info about [custom attributes][1]. Perhaps additional code snippet may help? > If I'm writing a transformer for class files today, what guidance is there to write the transformer so it does something sensible on class file formats defined in the future? I would like to add a paragraph comparing strict versus benevolent reaction approach of the transform on a new future class element. > For EnclosingMethodAttribute, the default methods enclosingMethodName() and enclosingMethodType() are presumably written in terms of OptionalenclosingMethod(). The sort of (expected) constraints among return values could be documented. Yes, I'll forward the constrains description from related JVMS parts. > ExceptionsAttribute: do the static of methods to any error checking, repeated exceptions, etc.? InnerClassesAttribute.of -- same question I'll add the constraints description. Basically factory methods do only null-checking, so they can be used to construct also invalid classes for testing purposes. Error checking is applied when constructing "symbols" (for example `ClassDesc` or `MethodTypeDesc` constructors perform checks). However it is possible to construct `ClassEntry` from `Utf8Entry`, `Utf8Entry` from plain `String` and then no checks are applied (except for null-checks). > ModuleResolutionAttribute.resolutionFlags method javadoc looks like it is missing a "" block. Thanks for pointing it out. This is fixed now and it will appear in the javadoc link above after refresh (soon). > UnknownAttribute should this be sealed? (Thinking about extensibility.) Yes, `UnknownAtrtibute` is not extensible. However `CustomAttribute` is not sealed and it is a root for all [user-provided attributes][1]. > Are the interfaces like ClassPrinter.LeafNode and ClassPrinter.ListNode intentionally public? From an initial look, they don't seem required as parts of the API. Yes, their purpose it to expose a "printable tree" in its minimal form. It may be used to build a custom format printer around the tree or even traverse the tree directly (for example in tests) without printing anything (see [class printer section of components package info][2]). > Should the toJson, toXml, toYml methods have some kind of documented grammar/schema for the output? I've added comment "Printing is for debugging purposes only. Printed text schema and tree content and structure not guaranteed. It may change anytime in a future." I think we cannot commit to keep the schema compatibility by documenting it in the API javadoc (at least for now). > Consistency requirement for DynamicConstantPoolEntry methods? Bootstrap methods are fully handled internally (BSM attribute is generated automatically) and so there are no extra consistency requirements (with respect to synchronize CP with BSM attribute). I'll add some note about that. > In Opcode, for JSR/RET I was expected some kind of comment on them not being supported in later class file versions, etc. Perhaps links to DiscontinuedInstruction? Added references, thanks for the comment. It will appear in the javadoc (link above) after refresh. > For the AccessFlags methods that provide an int -> AccessFlags or AccessFlag... -> AccessFlags method, there should be discussion of whether or not there are checks for validity, for ints, what version of the class file format is assumed (since bit positions may be undefined or change meaning for class file version). The conversion now fully depends on the default conversion implemented in `java.lang.reflect.AccessFlag`, so it assumes the latest version. We should probably add conversion methods with class version parameter to cover all possible use cases. However that does not automatically trigger an exception during transformation of older classes. Conversion from int to set of flags is not implicitly called by the library and user has to explicitly call it in the transformation or while parsing. Internally the library works with unconstrained ints. I'll finish the work in progress mentioned above, update the online javadoc available from the link above and set this CSR for another round. Thank you, Adam [1]: https://cr.openjdk.org/~asotona/JDK-8308753-preview/api/java.base/java/lang/classfile/package-summary.html#custom-attributes-heading [2]: https://cr.openjdk.org/~asotona/JDK-8308753-preview/api/java.base/java/lang/classfile/components/package-summary.html#classprinter-heading
20-09-2023

Initial round of comments: The API feature extensive use of sealed interfaces. For _non_ sealed interfaces with default methods, it is important to use an implSpec tag to specify the behavior. This is less important for sealed interface since there is more control over instantiation; however, some kind of note about the behavior would still be appropriate. The various "of" methods to created instance of objects from various arguments are largely silent on what consistency checks, if any, are implemented by the API. Some mention of this is appropriate for an API in the JDK. If the basic of method do check, there could be overloads taking a ClassFileFormatVersion argument that do, or a separate validate(ClassFileFormatVersion cffv) method, etc. I suggest expanding the package-level discussion a bit, including a high-level paragraph or two discussing of the structure of a class file in more detail. How would language compilers targeting the JVM define and use custom attributes using this API? (Perhaps this is not a supported use case.) If I'm writing a transformer for class files today, what guidance is there to write the transformer so it does something sensible on class file formats defined in the future? Some more detailed comments: For EnclosingMethodAttribute, the default methods enclosingMethodName() and enclosingMethodType() are presumably written in terms of Optional<NameAndTypeEntryPREVIEW>enclosingMethod(). The sort of (expected) constraints among return values could be documented. ExceptionsAttribute: do the static of methods to any error checking, repeated exceptions, etc.? InnerClassesAttribute.of -- same question ModuleResolutionAttribute.resolutionFlags method javadoc looks like it is missing a "<core><pre>" block. UnknownAttribute should this be sealed? (Thinking about extensibility.) Are the interfaces like ClassPrinter.LeafNode and ClassPrinter.ListNode intentionally public? From an initial look, they don't seem required as parts of the API. Should the toJson, toXml, toYml methods have some kind of documented grammar/schema for the output? Consistency requirement for DynamicConstantPoolEntry methods? In Opcode, for JSR/RET I was expected some kind of comment on them not being supported in later class file versions, etc. Perhaps links to DiscontinuedInstruction? For the AccessFlags methods that provide an int -> AccessFlags or AccessFlag... -> AccessFlags method, there should be discussion of whether or not there are checks for validity, for ints, what version of the class file format is assumed (since bit positions may be undefined or change meaning for class file version). Moving back to Draft.
14-09-2023

Thank you [~asotona] for submitting the CSR early in the release cycle. I've started my review of the API. To help set expectations, it is likely I'll perform multiple passes over the API and have questions/comments at different levels of granularity, from details of individual methods to the overall design. So this CSR may go through multiple Proposed -> Provisional back to Proposed cycles before it gets Finalized.
29-08-2023

Hi Adam, thanks for the info. Looking forward to this!
10-08-2023

[~acobbs] Thank you for your comments and questions. > What is the universe of classfiles that (a) can be successfully parsed by this library, and (b) can be successfully generated by this library? Is there an official declaration of where this boundary lies? The official boundary is JVMS Chapter 4. > Probably it won't be possible to generate a classfile with invalid UTF-8 - that's reasonable. Constant pool entries are primary generated from "symbols" (like for example `ClassDesc` -> `ClassEntry`), where validation to match the spec is performed during symbol construction - this is the safe way. Or CP entries can be created from raw Strings without any validation (for example `String` -> `Utf8Entry` -> `ClassEntry`) - this is the raw way of ASM and many other libraries. However there is no "hacker" way at the moment to create CP entry from raw bytes. > But will it be possible to generate a classfile with bytecode that doesn't pass the verifier, but is otherwise structurally valid? Yes, this is absolutely possible. You just may have to turn the stack map generation off (`Classfile.StackMapsOption.DROP_STACK_MAPS`), as the generator will fail to generate stack maps for invalid bytecode array, which is otherwise structurally valid. Classfile API does not implicitly verify generated bytecode, however generation of stack maps is a partial verification process by itself, or you may explicitly call `ClassModel::verify` to perform full verification. The limits to generate "invalid" bytecode are similar to the limits for constant pool. As `Label` is a symbol representing index into the bytecode array, you cannot generate for example branch instruction pointing out of the bytecode array. However you can generate dead bytecode, invalid loops causing stack overflow, etc... There are many cases of structurally valid (however failing to verify) bytecode you can generate with Classfile API. > If this is not already documented, it would be good to explicitly document this "boundary". > Such a boundary could be defined by referring to (parts of) JVMS Chapter 4. There are approximately 40 references to JVMS Chapter 4 from the Classfile API javadoc, there is work in progress to improve it (se for example [PR/14968][1]) and we are open to all suggestions. Thank you, Adam [1]: https://github.com/openjdk/jdk/pull/14968
10-08-2023

I think this will be great. One question/food for thought: What is the universe of classfiles that (a) can be successfully parsed by this library, and (b) can be successfully generated by this library? Is there an official declaration of where this boundary lies? A library like this is often very useful for JDK regression tests, when a "custom" classfile of some kind needs to be constructed. Often such a classfile is odd, broken, or special/different in some way. For example, consider [JDK-8303623 - Compiler should disallow non-standard UTF-8 string encodings][1]. Probably it won't be possible to generate a classfile with invalid UTF-8 - that's reasonable. But will it be possible to generate a classfile with bytecode that doesn't pass the verifier, but is otherwise structurally valid? Etc. If this is not already documented, it would be good to explicitly document this "boundary". Such a boundary could be defined by referring to (parts of) JVMS Chapter 4. [1]: https://bugs.openjdk.org/browse/JDK-8303623
09-08-2023