JDK-8331414 : java.lang.classfile.Attributes class performs a lot of static initializations
  • Type: CSR
  • Component: core-libs
  • Sub-Component: java.lang.classfile
  • Priority: P4
  • Status: Closed
  • Resolution: Approved
  • Fix Versions: 23
  • Submitted: 2024-04-30
  • Updated: 2024-05-24
  • Resolved: 2024-05-24
Related Reports
Blocks :  
CSR :  
Relates :  
Relates :  
Description
Summary
-------

Reduce static initialization footprint of `java.lang.classfile.Attributes`.

Problem
-------

`java.lang.classfile.Attributes` is a central point for `AttributeMapper`s of all supported attributes. For each `Attribute` there is a relevant static final  `AttributeMapper` field.
Plus there is a field `PREDEFINED_ATTRIBUTES` initialized with a set of all mappers.
Plus there is a static method `standardAttribute(Utf8Entry name)` providing mapping from `Utf8Entry` to a known `AttributeMapper`.

These statically initialized fields and mapping represents enormous initialization footprint on the JDK critical bootstrap path.

`java.lang.classfile.Attributes` is not declared final, even it is non-instantiable utility class.

Solution
--------

Change all static final fields into static methods with lazy individual initialization of each `AttributeMapper`. Remove `PREDEFINED_ATTRIBUTES` field from the API. Remove `standardAttribute(Utf8Entry name)` static mapping method from the API. Declare `java.lang.classfile.Attributes` as final class.


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

src/java.base/share/classes/java/lang/classfile/Attributes.java
```
- public class Attributes {
-    /** Attribute mapper for the {@code AnnotationDefault} attribute */
-    public static final AttributeMapper<AnnotationDefaultAttribute>
-            ANNOTATION_DEFAULT = new AbstractAttributeMapper<>(NAME_ANNOTATION_DEFAULT) {
-    /** Attribute mapper for the {@code BootstrapMethods} attribute */
-    public static final AttributeMapper<BootstrapMethodsAttribute>
-            BOOTSTRAP_METHODS = new AbstractAttributeMapper<>(NAME_BOOTSTRAP_METHODS) {
-    /** Attribute mapper for the {@code CharacterRangeTable} attribute */
-    public static final AttributeMapper<CharacterRangeTableAttribute>
-            CHARACTER_RANGE_TABLE = new AbstractAttributeMapper<>(NAME_CHARACTER_RANGE_TABLE, true) {
-    /** Attribute mapper for the {@code Code} attribute */
-    public static final AttributeMapper<CodeAttribute>
-            CODE = new AbstractAttributeMapper<>(NAME_CODE) {
-    /** Attribute mapper for the {@code CompilationID} attribute */
-    public static final AttributeMapper<CompilationIDAttribute>
-            COMPILATION_ID = new AbstractAttributeMapper<>(NAME_COMPILATION_ID, true) {
-    /** Attribute mapper for the {@code ConstantValue} attribute */
-    public static final AttributeMapper<ConstantValueAttribute>
-            CONSTANT_VALUE = new AbstractAttributeMapper<>(NAME_CONSTANT_VALUE) {
-    /** Attribute mapper for the {@code Deprecated} attribute */
-    public static final AttributeMapper<DeprecatedAttribute>
-            DEPRECATED = new AbstractAttributeMapper<>(NAME_DEPRECATED, true) {
-    /** Attribute mapper for the {@code EnclosingMethod} attribute */
-    public static final AttributeMapper<EnclosingMethodAttribute>
-            ENCLOSING_METHOD = new AbstractAttributeMapper<>(NAME_ENCLOSING_METHOD) {
-    /** Attribute mapper for the {@code Exceptions} attribute */
-    public static final AttributeMapper<ExceptionsAttribute>
-            EXCEPTIONS = new AbstractAttributeMapper<>(NAME_EXCEPTIONS) {
-    /** Attribute mapper for the {@code InnerClasses} attribute */
-    public static final AttributeMapper<InnerClassesAttribute>
-            INNER_CLASSES = new AbstractAttributeMapper<>(NAME_INNER_CLASSES) {
-    /** Attribute mapper for the {@code LineNumberTable} attribute */
-    public static final AttributeMapper<LineNumberTableAttribute>
-            LINE_NUMBER_TABLE = new AbstractAttributeMapper<>(NAME_LINE_NUMBER_TABLE, true) {
-    /** Attribute mapper for the {@code LocalVariableTable} attribute */
-    public static final AttributeMapper<LocalVariableTableAttribute>
-            LOCAL_VARIABLE_TABLE = new AbstractAttributeMapper<>(NAME_LOCAL_VARIABLE_TABLE, true) {
-    /** Attribute mapper for the {@code LocalVariableTypeTable} attribute */
-    public static final AttributeMapper<LocalVariableTypeTableAttribute>
-            LOCAL_VARIABLE_TYPE_TABLE = new AbstractAttributeMapper<>(NAME_LOCAL_VARIABLE_TYPE_TABLE, true) {
-    /** Attribute mapper for the {@code MethodParameters} attribute */
-    public static final AttributeMapper<MethodParametersAttribute>
-            METHOD_PARAMETERS = new AbstractAttributeMapper<>(NAME_METHOD_PARAMETERS) {
-    /** Attribute mapper for the {@code Module} attribute */
-    public static final AttributeMapper<ModuleAttribute>
-            MODULE = new AbstractAttributeMapper<>(NAME_MODULE) {
-    /** Attribute mapper for the {@code ModuleHashes} attribute */
-    public static final AttributeMapper<ModuleHashesAttribute>
-            MODULE_HASHES = new AbstractAttributeMapper<>(NAME_MODULE_HASHES) {
-    /** Attribute mapper for the {@code ModuleMainClass} attribute */
-    public static final AttributeMapper<ModuleMainClassAttribute>
-            MODULE_MAIN_CLASS = new AbstractAttributeMapper<>(NAME_MODULE_MAIN_CLASS) {
-    /** Attribute mapper for the {@code ModulePackages} attribute */
-    public static final AttributeMapper<ModulePackagesAttribute>
-            MODULE_PACKAGES = new AbstractAttributeMapper<>(NAME_MODULE_PACKAGES) {
-    /** Attribute mapper for the {@code ModuleResolution} attribute */
-    public static final AttributeMapper<ModuleResolutionAttribute>
-            MODULE_RESOLUTION = new AbstractAttributeMapper<>(NAME_MODULE_RESOLUTION) {
-    /** Attribute mapper for the {@code ModuleTarget} attribute */
-    public static final AttributeMapper<ModuleTargetAttribute>
-            MODULE_TARGET = new AbstractAttributeMapper<>(NAME_MODULE_TARGET) {
-    /** Attribute mapper for the {@code NestHost} attribute */
-    public static final AttributeMapper<NestHostAttribute>
-            NEST_HOST = new AbstractAttributeMapper<>(NAME_NEST_HOST) {
-    /** Attribute mapper for the {@code NestMembers} attribute */
-    public static final AttributeMapper<NestMembersAttribute>
-            NEST_MEMBERS = new AbstractAttributeMapper<>(NAME_NEST_MEMBERS) {
-    /** Attribute mapper for the {@code PermittedSubclasses} attribute */
-    public static final AttributeMapper<PermittedSubclassesAttribute>
-            PERMITTED_SUBCLASSES = new AbstractAttributeMapper<>(NAME_PERMITTED_SUBCLASSES) {
-    /** Attribute mapper for the {@code Record} attribute */
-    public static final AttributeMapper<RecordAttribute>
-            RECORD = new AbstractAttributeMapper<>(NAME_RECORD) {
-    /** Attribute mapper for the {@code RuntimeInvisibleAnnotations} attribute */
-    public static final AttributeMapper<RuntimeInvisibleAnnotationsAttribute>
-            RUNTIME_INVISIBLE_ANNOTATIONS = new AbstractAttributeMapper<>(NAME_RUNTIME_INVISIBLE_ANNOTATIONS) {
-    /** Attribute mapper for the {@code RuntimeInvisibleParameterAnnotations} attribute */
-    public static final AttributeMapper<RuntimeInvisibleParameterAnnotationsAttribute>
-            RUNTIME_INVISIBLE_PARAMETER_ANNOTATIONS = new AbstractAttributeMapper<>(NAME_RUNTIME_INVISIBLE_PARAMETER_ANNOTATIONS) {
-    /** Attribute mapper for the {@code RuntimeInvisibleTypeAnnotations} attribute */
-    public static final AttributeMapper<RuntimeInvisibleTypeAnnotationsAttribute>
-            RUNTIME_INVISIBLE_TYPE_ANNOTATIONS = new AbstractAttributeMapper<>(NAME_RUNTIME_INVISIBLE_TYPE_ANNOTATIONS) {
-    /** Attribute mapper for the {@code RuntimeVisibleAnnotations} attribute */
-    public static final AttributeMapper<RuntimeVisibleAnnotationsAttribute>
-            RUNTIME_VISIBLE_ANNOTATIONS = new AbstractAttributeMapper<>(NAME_RUNTIME_VISIBLE_ANNOTATIONS) {
-    /** Attribute mapper for the {@code RuntimeVisibleParameterAnnotations} attribute */
-    public static final AttributeMapper<RuntimeVisibleParameterAnnotationsAttribute>
-            RUNTIME_VISIBLE_PARAMETER_ANNOTATIONS = new AbstractAttributeMapper<>(NAME_RUNTIME_VISIBLE_PARAMETER_ANNOTATIONS) {
-    /** Attribute mapper for the {@code RuntimeVisibleTypeAnnotations} attribute */
-    public static final AttributeMapper<RuntimeVisibleTypeAnnotationsAttribute>
-            RUNTIME_VISIBLE_TYPE_ANNOTATIONS = new AbstractAttributeMapper<>(NAME_RUNTIME_VISIBLE_TYPE_ANNOTATIONS) {
-    /** Attribute mapper for the {@code Signature} attribute */
-    public static final AttributeMapper<SignatureAttribute>
-            SIGNATURE = new AbstractAttributeMapper<>(NAME_SIGNATURE) {
-    /** Attribute mapper for the {@code SourceDebugExtension} attribute */
-    public static final AttributeMapper<SourceDebugExtensionAttribute>
-            SOURCE_DEBUG_EXTENSION = new AbstractAttributeMapper<>(NAME_SOURCE_DEBUG_EXTENSION) {
-    /** Attribute mapper for the {@code SourceFile} attribute */
-    public static final AttributeMapper<SourceFileAttribute>
-            SOURCE_FILE = new AbstractAttributeMapper<>(NAME_SOURCE_FILE) {
-    /** Attribute mapper for the {@code SourceID} attribute */
-    public static final AttributeMapper<SourceIDAttribute>
-            SOURCE_ID = new AbstractAttributeMapper<>(NAME_SOURCE_ID) {
-    /** Attribute mapper for the {@code StackMapTable} attribute */
-    public static final AttributeMapper<StackMapTableAttribute>
-            STACK_MAP_TABLE = new AbstractAttributeMapper<>(NAME_STACK_MAP_TABLE) {
-    /** Attribute mapper for the {@code Synthetic} attribute */
-    public static final AttributeMapper<SyntheticAttribute>
-            SYNTHETIC = new AbstractAttributeMapper<>(NAME_SYNTHETIC, true) {
-   /**
-     * All standard attribute mappers.
-     */
-    public static final Set<AttributeMapper<?>> PREDEFINED_ATTRIBUTES = Set.of(
-            ANNOTATION_DEFAULT,
-            BOOTSTRAP_METHODS,
-            CHARACTER_RANGE_TABLE,
-            CODE,
-            COMPILATION_ID,
-            CONSTANT_VALUE,
-            DEPRECATED,
-            ENCLOSING_METHOD,
-            EXCEPTIONS,
-            INNER_CLASSES,
-            LINE_NUMBER_TABLE,
-            LOCAL_VARIABLE_TABLE,
-            LOCAL_VARIABLE_TYPE_TABLE,
-            METHOD_PARAMETERS,
-            MODULE,
-            MODULE_HASHES,
-            MODULE_MAIN_CLASS,
-            MODULE_PACKAGES,
-            MODULE_RESOLUTION,
-            MODULE_TARGET,
-            NEST_HOST,
-            NEST_MEMBERS,
-            PERMITTED_SUBCLASSES,
-            RECORD,
-            RUNTIME_INVISIBLE_ANNOTATIONS,
-            RUNTIME_INVISIBLE_PARAMETER_ANNOTATIONS,
-            RUNTIME_INVISIBLE_TYPE_ANNOTATIONS,
-            RUNTIME_VISIBLE_ANNOTATIONS,
-            RUNTIME_VISIBLE_PARAMETER_ANNOTATIONS,
-            RUNTIME_VISIBLE_TYPE_ANNOTATIONS,
-            SIGNATURE,
-            SOURCE_DEBUG_EXTENSION,
-            SOURCE_FILE,
-            SOURCE_ID,
-            STACK_MAP_TABLE,
-            SYNTHETIC);
 /**
  * Attribute mappers for standard classfile attributes.
+ * <p>
+ * Unless otherwise specified, mappers returned by each method
+ * do not permit multiple attribute instances in a given location.
+ * <p>
+ * The most stable {@link AttributeStability#STATELESS STATELESS} mappers are:
+ * <ul>
+ * <li>{@link #deprecated()}
+ * <li>{@link #moduleResolution()}
+ * <li>{@link #sourceDebugExtension()}
+ * <li>{@link #synthetic()}
+ * </ul>
+ *
+ * The mappers with {@link AttributeStability#CP_REFS CP_REFS} stability are:
+ * <ul>
+ * <li>{@link #annotationDefault()}
+ * <li>{@link #bootstrapMethods()}
+ * <li>{@link #code()}
+ * <li>{@link #compilationId()}
+ * <li>{@link #constantValue()}
+ * <li>{@link #enclosingMethod()}
+ * <li>{@link #exceptions()}
+ * <li>{@link #innerClasses()}
+ * <li>{@link #methodParameters()}
+ * <li>{@link #module()}
+ * <li>{@link #moduleHashes()}
+ * <li>{@link #moduleMainClass()}
+ * <li>{@link #modulePackages()}
+ * <li>{@link #moduleTarget()}
+ * <li>{@link #nestHost()}
+ * <li>{@link #nestMembers()}
+ * <li>{@link #permittedSubclasses()}
+ * <li>{@link #record()}
+ * <li>{@link #runtimeInvisibleAnnotations()}
+ * <li>{@link #runtimeInvisibleParameterAnnotations()}
+ * <li>{@link #runtimeVisibleAnnotations()}
+ * <li>{@link #runtimeVisibleParameterAnnotations()}
+ * <li>{@link #signature()}
+ * <li>{@link #sourceFile()}
+ * <li>{@link #sourceId()}
+ * </ul>
+ *
+ * The mappers with {@link AttributeStability#LABELS LABELS} stability are:
+ * <ul>
+ * <li>{@link #characterRangeTable()}
+ * <li>{@link #lineNumberTable()}
+ * <li>{@link #localVariableTable()}
+ * <li>{@link #localVariableTypeTable()}
+ * </ul>
+ *
+ * The {@link AttributeStability#UNSTABLE UNSTABLE} mappers are:
+ * <ul>
+ * <li>{@link #runtimeInvisibleTypeAnnotations()}
+ * <li>{@link #runtimeVisibleTypeAnnotations()}
+ * </ul>
  *
  * @see AttributeMapper
  *
  * @since 22
  */
 @PreviewFeature(feature = PreviewFeature.Feature.CLASSFILE_API)
+ public final class Attributes {
+
+    /**
+     * {@return Attribute mapper for the {@code AnnotationDefault} attribute}
+     * @since 23
+     */
+    public static AttributeMapper<AnnotationDefaultAttribute> annotationDefault() {
+        return AnnotationDefaultMapper.INSTANCE;
+    }
+
+    /**
+     * {@return Attribute mapper for the {@code BootstrapMethods} attribute}
+     * @since 23
+     */
+    public static AttributeMapper<BootstrapMethodsAttribute> bootstrapMethods() {
+        return BootstrapMethodsMapper.INSTANCE;
+    }
+
+    /**
+     * {@return Attribute mapper for the {@code CharacterRangeTable} attribute}
+     * The mapper permits multiple instances in a given location.
+     * @since 23
+     */
+    public static AttributeMapper<CharacterRangeTableAttribute> characterRangeTable() {
+        return CharacterRangeTableMapper.INSTANCE;
+    }
+
+    /**
+     * {@return Attribute mapper for the {@code Code} attribute}
+     * @since 23
+     */
+    public static AttributeMapper<CodeAttribute> code() {
+        return CodeMapper.INSTANCE;
+    }
+
+    /**
+     * {@return Attribute mapper for the {@code CompilationID} attribute}
+     * @since 23
+     */
+    public static AttributeMapper<CompilationIDAttribute> compilationId() {
+        return CompilationIDMapper.INSTANCE;
+    }
+
+    /**
+     * {@return Attribute mapper for the {@code ConstantValue} attribute}
+     * @since 23
+     */
+    public static AttributeMapper<ConstantValueAttribute> constantValue() {
+        return ConstantValueMapper.INSTANCE;
+    }
+
+    /**
+     * {@return Attribute mapper for the {@code Deprecated} attribute}
+     * The mapper permits multiple instances in a given location.
+     * @since 23
+     */
+    public static AttributeMapper<DeprecatedAttribute> deprecated() {
+        return DeprecatedMapper.INSTANCE;
+    }
+
+    /**
+     * {@return Attribute mapper for the {@code EnclosingMethod} attribute}
+     * @since 23
+     */
+    public static AttributeMapper<EnclosingMethodAttribute> enclosingMethod() {
+        return EnclosingMethodMapper.INSTANCE;
+    }
+
+    /**
+     * {@return Attribute mapper for the {@code Exceptions} attribute}
+     * @since 23
+     */
+    public static AttributeMapper<ExceptionsAttribute> exceptions() {
+        return ExceptionsMapper.INSTANCE;
+    }
+
+    /**
+     * {@return Attribute mapper for the {@code InnerClasses} attribute}
+     * @since 23
+     */
+    public static AttributeMapper<InnerClassesAttribute> innerClasses() {
+        return InnerClassesMapper.INSTANCE;
+    }
+
+    /**
+     * {@return Attribute mapper for the {@code LineNumberTable} attribute}
+     * The mapper permits multiple instances in a given location.
+     * @since 23
+     */
+    public static AttributeMapper<LineNumberTableAttribute> lineNumberTable() {
+        return LineNumberTableMapper.INSTANCE;
+    }
+
+    /**
+     * {@return Attribute mapper for the {@code LocalVariableTable} attribute}
+     * The mapper permits multiple instances in a given location.
+     * @since 23
+     */
+    public static AttributeMapper<LocalVariableTableAttribute> localVariableTable() {
+        return LocalVariableTableMapper.INSTANCE;
+    }
+
+    /**
+     * {@return Attribute mapper for the {@code LocalVariableTypeTable} attribute}
+     * The mapper permits multiple instances in a given location.
+     * @since 23
+     */
+    public static AttributeMapper<LocalVariableTypeTableAttribute> localVariableTypeTable() {
+        return LocalVariableTypeTableMapper.INSTANCE;
+    }
+
+    /**
+     * {@return Attribute mapper for the {@code MethodParameters} attribute}
+     * @since 23
+     */
+    public static AttributeMapper<MethodParametersAttribute> methodParameters() {
+        return MethodParametersMapper.INSTANCE;
+    }
+
+    /**
+     * {@return Attribute mapper for the {@code Module} attribute}
+     * @since 23
+     */
+    public static AttributeMapper<ModuleAttribute> module() {
+        return ModuleMapper.INSTANCE;
+    }
+
+    /**
+     * {@return Attribute mapper for the {@code ModuleHashes} attribute}
+     * @since 23
+     */
+    public static AttributeMapper<ModuleHashesAttribute> moduleHashes() {
+        return ModuleHashesMapper.INSTANCE;
+    }
+
+    /**
+     * {@return Attribute mapper for the {@code ModuleMainClass} attribute}
+     * @since 23
+     */
+    public static AttributeMapper<ModuleMainClassAttribute> moduleMainClass() {
+        return ModuleMainClassMapper.INSTANCE;
+    }
+
+    /**
+     * {@return Attribute mapper for the {@code ModulePackages} attribute}
+     * @since 23
+     */
+    public static AttributeMapper<ModulePackagesAttribute> modulePackages() {
+        return ModulePackagesMapper.INSTANCE;
+    }
+
+    /**
+     * {@return Attribute mapper for the {@code ModuleResolution} attribute}
+     * @since 23
+     */
+    public static AttributeMapper<ModuleResolutionAttribute> moduleResolution() {
+        return ModuleResolutionMapper.INSTANCE;
+    }
+
+    /**
+     * {@return Attribute mapper for the {@code ModuleTarget} attribute}
+     * @since 23
+     */
+    public static AttributeMapper<ModuleTargetAttribute> moduleTarget() {
+        return ModuleTargetMapper.INSTANCE;
+    }
+
+    /**
+     * {@return Attribute mapper for the {@code NestHost} attribute}
+     * @since 23
+     */
+    public static AttributeMapper<NestHostAttribute> nestHost() {
+        return NestHostMapper.INSTANCE;
+    }
+
+    /**
+     * {@return Attribute mapper for the {@code NestMembers} attribute}
+     * @since 23
+     */
+    public static AttributeMapper<NestMembersAttribute> nestMembers() {
+        return NestMembersMapper.INSTANCE;
+    }
+
+    /**
+     * {@return Attribute mapper for the {@code PermittedSubclasses} attribute}
+     * @since 23
+     */
+    public static AttributeMapper<PermittedSubclassesAttribute> permittedSubclasses() {
+        return PermittedSubclassesMapper.INSTANCE;
+    }
+
+    /**
+     * {@return Attribute mapper for the {@code Record} attribute}
+     * @since 23
+     */
+    public static AttributeMapper<RecordAttribute> record() {
+        return RecordMapper.INSTANCE;
+    }
+
+    /**
+     * {@return Attribute mapper for the {@code RuntimeInvisibleAnnotations} attribute}
+     * @since 23
+     */
+    public static AttributeMapper<RuntimeInvisibleAnnotationsAttribute> runtimeInvisibleAnnotations() {
+        return RuntimeInvisibleAnnotationsMapper.INSTANCE;
+    }
+
+    /**
+     * {@return Attribute mapper for the {@code RuntimeInvisibleParameterAnnotations} attribute}
+     * @since 23
+     */
+    public static AttributeMapper<RuntimeInvisibleParameterAnnotationsAttribute> runtimeInvisibleParameterAnnotations() {
+        return RuntimeInvisibleParameterAnnotationsMapper.INSTANCE;
+    }
+
+    /**
+     * {@return Attribute mapper for the {@code RuntimeInvisibleTypeAnnotations} attribute}
+     * @since 23
+     */
+    public static AttributeMapper<RuntimeInvisibleTypeAnnotationsAttribute> runtimeInvisibleTypeAnnotations() {
+        return RuntimeInvisibleTypeAnnotationsMapper.INSTANCE;
+    }
+
+    /**
+     * {@return Attribute mapper for the {@code RuntimeVisibleAnnotations} attribute}
+     * @since 23
+     */
+    public static AttributeMapper<RuntimeVisibleAnnotationsAttribute> runtimeVisibleAnnotations() {
+        return RuntimeVisibleAnnotationsMapper.INSTANCE;
+    }
+
+    /**
+     * {@return Attribute mapper for the {@code RuntimeVisibleParameterAnnotations} attribute}
+     * @since 23
+     */
+    public static AttributeMapper<RuntimeVisibleParameterAnnotationsAttribute> runtimeVisibleParameterAnnotations() {
+        return RuntimeVisibleParameterAnnotationsMapper.INSTANCE;
+    }
+
+    /**
+     * {@return Attribute mapper for the {@code RuntimeVisibleTypeAnnotations} attribute}
+     * @since 23
+     */
+    public static AttributeMapper<RuntimeVisibleTypeAnnotationsAttribute> runtimeVisibleTypeAnnotations() {
+        return RuntimeVisibleTypeAnnotationsMapper.INSTANCE;
+    }
+
+    /**
+     * {@return Attribute mapper for the {@code Signature} attribute}
+     * @since 23
+     */
+    public static AttributeMapper<SignatureAttribute> signature() {
+        return SignatureMapper.INSTANCE;
+    }
+
+    /**
+     * {@return Attribute mapper for the {@code SourceDebugExtension} attribute}
+     * @since 23
+     */
+    public static AttributeMapper<SourceDebugExtensionAttribute> sourceDebugExtension() {
+        return SourceDebugExtensionMapper.INSTANCE;
+    }
+
+    /**
+     * {@return Attribute mapper for the {@code SourceFile} attribute}
+     * @since 23
+     */
+    public static AttributeMapper<SourceFileAttribute> sourceFile() {
+        return SourceFileMapper.INSTANCE;
+    }
+
+    /**
+     * {@return Attribute mapper for the {@code SourceID} attribute}
+     * @since 23
+     */
+    public static AttributeMapper<SourceIDAttribute> sourceId() {
+        return SourceIDMapper.INSTANCE;
+    }
+ 
+    /**
+     * {@return Attribute mapper for the {@code StackMapTable} attribute}
+     * @since 23
+     */
+    public static AttributeMapper<StackMapTableAttribute> stackMapTable() {
+        return StackMapTableMapper.INSTANCE;
+    }
+ 
+    /**
+     * {@return Attribute mapper for the {@code Synthetic} attribute}
+     * The mapper permits multiple instances in a given location.
+     * @since 23
+     */
+    public static AttributeMapper<SyntheticAttribute> synthetic() {
+        return SyntheticMapper.INSTANCE;
+    }

```


Comments
Moving updated request to Approved.
24-05-2024

I've added class-level statement: `Unless otherwise specified, mappers returned by each method do not permit multiple attribute instances in a given location.` All "otherwise" mappers are now documented with statement: `The mapper permits multiple instances in a given location.` Lists of mappers organized by stability has been added to the class-level docs as suggested. Name of the mapper is already documented in `AttributeMapper::name` javadoc: `{@return the name of the attribute}` Thank you for the review.
24-05-2024

Sorry for the belated review; moving to Provisional, not Approved. How/where is the behavior of the AttributeMapper's specified? That is, the result of allowMultiple(), name(), stability(), etc. for each attribute? I think it would be fine to largely do much of this with class-level docs. "The AttributeMapper returned by each method in this class a name() that is equal to .... The AttributeMapper with CP_REFS stability are ..." If there is a common figuration, that default could be listed in the class with with a comment like "Unless otherwise specified, AttributeMapper returned by each method in this class do X, Y, and Z." where the particular method documented the variance from the default. Please re-Finalize the request once an approach to address this point, if needed, is determined. Thanks.
24-05-2024

This Class-File API change is critical for JDK bootstrap performance, significantly affects work on JDK-8332457 and blocks integration of JDK-8294960. Please review. Thank you!
20-05-2024