/* * Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 only, as * published by the Free Software Foundation. Oracle designates this * particular file as subject to the "Classpath" exception as provided * by Oracle in the LICENSE file that accompanied this code. * * This code is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * version 2 for more details (a copy is included in the LICENSE file that * accompanied this code). * * You should have received a copy of the GNU General Public License version * 2 along with this work; if not, write to the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. * * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA * or visit www.oracle.com if you need additional information or have any * questions. */ package java.lang.classfile; import java.util.Collections; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Set; import java.lang.classfile.attribute.AnnotationDefaultAttribute; import java.lang.classfile.attribute.BootstrapMethodsAttribute; import java.lang.classfile.attribute.CharacterRangeInfo; import java.lang.classfile.attribute.CharacterRangeTableAttribute; import java.lang.classfile.attribute.CodeAttribute; import java.lang.classfile.attribute.CompilationIDAttribute; import java.lang.classfile.attribute.ConstantValueAttribute; import java.lang.classfile.attribute.DeprecatedAttribute; import java.lang.classfile.attribute.EnclosingMethodAttribute; import java.lang.classfile.attribute.ExceptionsAttribute; import java.lang.classfile.attribute.InnerClassInfo; import java.lang.classfile.attribute.InnerClassesAttribute; import java.lang.classfile.attribute.LineNumberInfo; import java.lang.classfile.attribute.LineNumberTableAttribute; import java.lang.classfile.attribute.LocalVariableInfo; import java.lang.classfile.attribute.LocalVariableTableAttribute; import java.lang.classfile.attribute.LocalVariableTypeInfo; import java.lang.classfile.attribute.LocalVariableTypeTableAttribute; import java.lang.classfile.attribute.MethodParameterInfo; import java.lang.classfile.attribute.MethodParametersAttribute; import java.lang.classfile.attribute.ModuleAttribute; import java.lang.classfile.attribute.ModuleExportInfo; import java.lang.classfile.attribute.ModuleHashInfo; import java.lang.classfile.attribute.ModuleHashesAttribute; import java.lang.classfile.attribute.ModuleMainClassAttribute; import java.lang.classfile.attribute.ModuleOpenInfo; import java.lang.classfile.attribute.ModulePackagesAttribute; import java.lang.classfile.attribute.ModuleProvideInfo; import java.lang.classfile.attribute.ModuleRequireInfo; import java.lang.classfile.attribute.ModuleResolutionAttribute; import java.lang.classfile.attribute.ModuleTargetAttribute; import java.lang.classfile.attribute.NestHostAttribute; import java.lang.classfile.attribute.NestMembersAttribute; import java.lang.classfile.attribute.PermittedSubclassesAttribute; import java.lang.classfile.attribute.RecordAttribute; import java.lang.classfile.attribute.RecordComponentInfo; import java.lang.classfile.attribute.RuntimeInvisibleAnnotationsAttribute; import java.lang.classfile.attribute.RuntimeInvisibleParameterAnnotationsAttribute; import java.lang.classfile.attribute.RuntimeInvisibleTypeAnnotationsAttribute; import java.lang.classfile.attribute.RuntimeVisibleAnnotationsAttribute; import java.lang.classfile.attribute.RuntimeVisibleParameterAnnotationsAttribute; import java.lang.classfile.attribute.RuntimeVisibleTypeAnnotationsAttribute; import java.lang.classfile.attribute.SignatureAttribute; import java.lang.classfile.attribute.SourceDebugExtensionAttribute; import java.lang.classfile.attribute.SourceFileAttribute; import java.lang.classfile.attribute.SourceIDAttribute; import java.lang.classfile.attribute.StackMapTableAttribute; import java.lang.classfile.attribute.SyntheticAttribute; import java.lang.classfile.constantpool.Utf8Entry; import jdk.internal.classfile.impl.AbstractAttributeMapper; import jdk.internal.classfile.impl.BoundAttribute; import jdk.internal.classfile.impl.CodeImpl; import jdk.internal.classfile.impl.AbstractPoolEntry; import jdk.internal.classfile.impl.StackMapDecoder; import jdk.internal.javac.PreviewFeature; /** * Attribute mappers for standard classfile attributes. * * @see AttributeMapper * * @since 22 */ @PreviewFeature(feature = PreviewFeature.Feature.CLASSFILE_API) public class Attributes { /** AnnotationDefault */ public static final String NAME_ANNOTATION_DEFAULT = "AnnotationDefault"; /** BootstrapMethods */ public static final String NAME_BOOTSTRAP_METHODS = "BootstrapMethods"; /** CharacterRangeTable */ public static final String NAME_CHARACTER_RANGE_TABLE = "CharacterRangeTable"; /** Code */ public static final String NAME_CODE = "Code"; /** CompilationID */ public static final String NAME_COMPILATION_ID = "CompilationID"; /** ConstantValue */ public static final String NAME_CONSTANT_VALUE = "ConstantValue"; /** Deprecated */ public static final String NAME_DEPRECATED = "Deprecated"; /** EnclosingMethod */ public static final String NAME_ENCLOSING_METHOD = "EnclosingMethod"; /** Exceptions */ public static final String NAME_EXCEPTIONS = "Exceptions"; /** InnerClasses */ public static final String NAME_INNER_CLASSES = "InnerClasses"; /** LineNumberTable */ public static final String NAME_LINE_NUMBER_TABLE = "LineNumberTable"; /** LocalVariableTable */ public static final String NAME_LOCAL_VARIABLE_TABLE = "LocalVariableTable"; /** LocalVariableTypeTable */ public static final String NAME_LOCAL_VARIABLE_TYPE_TABLE = "LocalVariableTypeTable"; /** MethodParameters */ public static final String NAME_METHOD_PARAMETERS = "MethodParameters"; /** Module */ public static final String NAME_MODULE = "Module"; /** ModuleHashes */ public static final String NAME_MODULE_HASHES = "ModuleHashes"; /** ModuleMainClass */ public static final String NAME_MODULE_MAIN_CLASS = "ModuleMainClass"; /** ModulePackages */ public static final String NAME_MODULE_PACKAGES = "ModulePackages"; /** ModuleResolution */ public static final String NAME_MODULE_RESOLUTION = "ModuleResolution"; /** ModuleTarget */ public static final String NAME_MODULE_TARGET = "ModuleTarget"; /** NestHost */ public static final String NAME_NEST_HOST = "NestHost"; /** NestMembers */ public static final String NAME_NEST_MEMBERS = "NestMembers"; /** PermittedSubclasses */ public static final String NAME_PERMITTED_SUBCLASSES = "PermittedSubclasses"; /** Record */ public static final String NAME_RECORD = "Record"; /** RuntimeInvisibleAnnotations */ public static final String NAME_RUNTIME_INVISIBLE_ANNOTATIONS = "RuntimeInvisibleAnnotations"; /** RuntimeInvisibleParameterAnnotations */ public static final String NAME_RUNTIME_INVISIBLE_PARAMETER_ANNOTATIONS = "RuntimeInvisibleParameterAnnotations"; /** RuntimeInvisibleTypeAnnotations */ public static final String NAME_RUNTIME_INVISIBLE_TYPE_ANNOTATIONS = "RuntimeInvisibleTypeAnnotations"; /** RuntimeVisibleAnnotations */ public static final String NAME_RUNTIME_VISIBLE_ANNOTATIONS = "RuntimeVisibleAnnotations"; /** RuntimeVisibleParameterAnnotations */ public static final String NAME_RUNTIME_VISIBLE_PARAMETER_ANNOTATIONS = "RuntimeVisibleParameterAnnotations"; /** RuntimeVisibleTypeAnnotations */ public static final String NAME_RUNTIME_VISIBLE_TYPE_ANNOTATIONS = "RuntimeVisibleTypeAnnotations"; /** Signature */ public static final String NAME_SIGNATURE = "Signature"; /** SourceDebugExtension */ public static final String NAME_SOURCE_DEBUG_EXTENSION = "SourceDebugExtension"; /** SourceFile */ public static final String NAME_SOURCE_FILE = "SourceFile"; /** SourceID */ public static final String NAME_SOURCE_ID = "SourceID"; /** StackMapTable */ public static final String NAME_STACK_MAP_TABLE = "StackMapTable"; /** Synthetic */ public static final String NAME_SYNTHETIC = "Synthetic"; private Attributes() { } /** Attribute mapper for the {@code AnnotationDefault} attribute */ public static final AttributeMapper ANNOTATION_DEFAULT = new AbstractAttributeMapper<>(NAME_ANNOTATION_DEFAULT) { @Override public AnnotationDefaultAttribute readAttribute(AttributedElement e, ClassReader cf, int p) { return new BoundAttribute.BoundAnnotationDefaultAttr(cf, this, p); } @Override protected void writeBody(BufWriter buf, AnnotationDefaultAttribute attr) { attr.defaultValue().writeTo(buf); } @Override public AttributeMapper.AttributeStability stability() { return AttributeStability.CP_REFS; } }; /** Attribute mapper for the {@code BootstrapMethods} attribute */ public static final AttributeMapper BOOTSTRAP_METHODS = new AbstractAttributeMapper<>(NAME_BOOTSTRAP_METHODS) { @Override public BootstrapMethodsAttribute readAttribute(AttributedElement e, ClassReader cf, int p) { return new BoundAttribute.BoundBootstrapMethodsAttribute(cf, this, p); } @Override protected void writeBody(BufWriter buf, BootstrapMethodsAttribute attr) { buf.writeList(attr.bootstrapMethods()); } @Override public AttributeMapper.AttributeStability stability() { return AttributeStability.CP_REFS; } }; /** Attribute mapper for the {@code CharacterRangeTable} attribute */ public static final AttributeMapper CHARACTER_RANGE_TABLE = new AbstractAttributeMapper<>(NAME_CHARACTER_RANGE_TABLE, true) { @Override public CharacterRangeTableAttribute readAttribute(AttributedElement e, ClassReader cf, int p) { return new BoundAttribute.BoundCharacterRangeTableAttribute(cf, this, p); } @Override protected void writeBody(BufWriter buf, CharacterRangeTableAttribute attr) { List ranges = attr.characterRangeTable(); buf.writeU2(ranges.size()); for (CharacterRangeInfo info : ranges) { buf.writeU2(info.startPc()); buf.writeU2(info.endPc()); buf.writeInt(info.characterRangeStart()); buf.writeInt(info.characterRangeEnd()); buf.writeU2(info.flags()); } } @Override public AttributeMapper.AttributeStability stability() { return AttributeStability.LABELS; } }; /** Attribute mapper for the {@code Code} attribute */ public static final AttributeMapper CODE = new AbstractAttributeMapper<>(NAME_CODE) { @Override public CodeAttribute readAttribute(AttributedElement e, ClassReader cf, int p) { return new CodeImpl(e, cf, this, p); } @Override protected void writeBody(BufWriter buf, CodeAttribute attr) { throw new UnsupportedOperationException("Code attribute does not support direct write"); } @Override public AttributeMapper.AttributeStability stability() { return AttributeStability.CP_REFS; } }; /** Attribute mapper for the {@code CompilationID} attribute */ public static final AttributeMapper COMPILATION_ID = new AbstractAttributeMapper<>(NAME_COMPILATION_ID, true) { @Override public CompilationIDAttribute readAttribute(AttributedElement e, ClassReader cf, int p) { return new BoundAttribute.BoundCompilationIDAttribute(cf, this, p); } @Override protected void writeBody(BufWriter buf, CompilationIDAttribute attr) { buf.writeIndex(attr.compilationId()); } @Override public AttributeMapper.AttributeStability stability() { return AttributeStability.CP_REFS; } }; /** Attribute mapper for the {@code ConstantValue} attribute */ public static final AttributeMapper CONSTANT_VALUE = new AbstractAttributeMapper<>(NAME_CONSTANT_VALUE) { @Override public ConstantValueAttribute readAttribute(AttributedElement e, ClassReader cf, int p) { return new BoundAttribute.BoundConstantValueAttribute(cf, this, p); } @Override protected void writeBody(BufWriter buf, ConstantValueAttribute attr) { buf.writeIndex(attr.constant()); } @Override public AttributeMapper.AttributeStability stability() { return AttributeStability.CP_REFS; } }; /** Attribute mapper for the {@code Deprecated} attribute */ public static final AttributeMapper DEPRECATED = new AbstractAttributeMapper<>(NAME_DEPRECATED, true) { @Override public DeprecatedAttribute readAttribute(AttributedElement e, ClassReader cf, int p) { return new BoundAttribute.BoundDeprecatedAttribute(cf, this, p); } @Override protected void writeBody(BufWriter buf, DeprecatedAttribute attr) { // empty } @Override public AttributeMapper.AttributeStability stability() { return AttributeStability.STATELESS; } }; /** Attribute mapper for the {@code EnclosingMethod} attribute */ public static final AttributeMapper ENCLOSING_METHOD = new AbstractAttributeMapper<>(NAME_ENCLOSING_METHOD) { @Override public EnclosingMethodAttribute readAttribute(AttributedElement e, ClassReader cf, int p) { return new BoundAttribute.BoundEnclosingMethodAttribute(cf, this, p); } @Override protected void writeBody(BufWriter buf, EnclosingMethodAttribute attr) { buf.writeIndex(attr.enclosingClass()); buf.writeIndexOrZero(attr.enclosingMethod().orElse(null)); } @Override public AttributeMapper.AttributeStability stability() { return AttributeStability.CP_REFS; } }; /** Attribute mapper for the {@code Exceptions} attribute */ public static final AttributeMapper EXCEPTIONS = new AbstractAttributeMapper<>(NAME_EXCEPTIONS) { @Override public ExceptionsAttribute readAttribute(AttributedElement e, ClassReader cf, int p) { return new BoundAttribute.BoundExceptionsAttribute(cf, this, p); } @Override protected void writeBody(BufWriter buf, ExceptionsAttribute attr) { buf.writeListIndices(attr.exceptions()); } @Override public AttributeMapper.AttributeStability stability() { return AttributeStability.CP_REFS; } }; /** Attribute mapper for the {@code InnerClasses} attribute */ public static final AttributeMapper INNER_CLASSES = new AbstractAttributeMapper<>(NAME_INNER_CLASSES) { @Override public InnerClassesAttribute readAttribute(AttributedElement e, ClassReader cf, int p) { return new BoundAttribute.BoundInnerClassesAttribute(cf, this, p); } @Override protected void writeBody(BufWriter buf, InnerClassesAttribute attr) { List classes = attr.classes(); buf.writeU2(classes.size()); for (InnerClassInfo ic : classes) { buf.writeIndex(ic.innerClass()); buf.writeIndexOrZero(ic.outerClass().orElse(null)); buf.writeIndexOrZero(ic.innerName().orElse(null)); buf.writeU2(ic.flagsMask()); } } @Override public AttributeMapper.AttributeStability stability() { return AttributeStability.CP_REFS; } }; /** Attribute mapper for the {@code LineNumberTable} attribute */ public static final AttributeMapper LINE_NUMBER_TABLE = new AbstractAttributeMapper<>(NAME_LINE_NUMBER_TABLE, true) { @Override public LineNumberTableAttribute readAttribute(AttributedElement e, ClassReader cf, int p) { return new BoundAttribute.BoundLineNumberTableAttribute(cf, this, p); } @Override protected void writeBody(BufWriter buf, LineNumberTableAttribute attr) { List lines = attr.lineNumbers(); buf.writeU2(lines.size()); for (LineNumberInfo line : lines) { buf.writeU2(line.startPc()); buf.writeU2(line.lineNumber()); } } @Override public AttributeMapper.AttributeStability stability() { return AttributeStability.LABELS; } }; /** Attribute mapper for the {@code LocalVariableTable} attribute */ public static final AttributeMapper LOCAL_VARIABLE_TABLE = new AbstractAttributeMapper<>(NAME_LOCAL_VARIABLE_TABLE, true) { @Override public LocalVariableTableAttribute readAttribute(AttributedElement e, ClassReader cf, int p) { return new BoundAttribute.BoundLocalVariableTableAttribute(e, cf, this, p); } @Override protected void writeBody(BufWriter buf, LocalVariableTableAttribute attr) { List infos = attr.localVariables(); buf.writeU2(infos.size()); for (LocalVariableInfo info : infos) { buf.writeU2(info.startPc()); buf.writeU2(info.length()); buf.writeIndex(info.name()); buf.writeIndex(info.type()); buf.writeU2(info.slot()); } } @Override public AttributeMapper.AttributeStability stability() { return AttributeStability.LABELS; } }; /** Attribute mapper for the {@code LocalVariableTypeTable} attribute */ public static final AttributeMapper LOCAL_VARIABLE_TYPE_TABLE = new AbstractAttributeMapper<>(NAME_LOCAL_VARIABLE_TYPE_TABLE, true) { @Override public LocalVariableTypeTableAttribute readAttribute(AttributedElement e, ClassReader cf, int p) { return new BoundAttribute.BoundLocalVariableTypeTableAttribute(e, cf, this, p); } @Override protected void writeBody(BufWriter buf, LocalVariableTypeTableAttribute attr) { List infos = attr.localVariableTypes(); buf.writeU2(infos.size()); for (LocalVariableTypeInfo info : infos) { buf.writeU2(info.startPc()); buf.writeU2(info.length()); buf.writeIndex(info.name()); buf.writeIndex(info.signature()); buf.writeU2(info.slot()); } } @Override public AttributeMapper.AttributeStability stability() { return AttributeStability.LABELS; } }; /** Attribute mapper for the {@code MethodParameters} attribute */ public static final AttributeMapper METHOD_PARAMETERS = new AbstractAttributeMapper<>(NAME_METHOD_PARAMETERS) { @Override public MethodParametersAttribute readAttribute(AttributedElement e, ClassReader cf, int p) { return new BoundAttribute.BoundMethodParametersAttribute(cf, this, p); } @Override protected void writeBody(BufWriter buf, MethodParametersAttribute attr) { List parameters = attr.parameters(); buf.writeU1(parameters.size()); for (MethodParameterInfo info : parameters) { buf.writeIndexOrZero(info.name().orElse(null)); buf.writeU2(info.flagsMask()); } } @Override public AttributeMapper.AttributeStability stability() { return AttributeStability.CP_REFS; } }; /** Attribute mapper for the {@code Module} attribute */ public static final AttributeMapper MODULE = new AbstractAttributeMapper<>(NAME_MODULE) { @Override public ModuleAttribute readAttribute(AttributedElement e, ClassReader cf, int p) { return new BoundAttribute.BoundModuleAttribute(cf, this, p); } @Override protected void writeBody(BufWriter buf, ModuleAttribute attr) { buf.writeIndex(attr.moduleName()); buf.writeU2(attr.moduleFlagsMask()); buf.writeIndexOrZero(attr.moduleVersion().orElse(null)); buf.writeU2(attr.requires().size()); for (ModuleRequireInfo require : attr.requires()) { buf.writeIndex(require.requires()); buf.writeU2(require.requiresFlagsMask()); buf.writeIndexOrZero(require.requiresVersion().orElse(null)); } buf.writeU2(attr.exports().size()); for (ModuleExportInfo export : attr.exports()) { buf.writeIndex(export.exportedPackage()); buf.writeU2(export.exportsFlagsMask()); buf.writeListIndices(export.exportsTo()); } buf.writeU2(attr.opens().size()); for (ModuleOpenInfo open : attr.opens()) { buf.writeIndex(open.openedPackage()); buf.writeU2(open.opensFlagsMask()); buf.writeListIndices(open.opensTo()); } buf.writeListIndices(attr.uses()); buf.writeU2(attr.provides().size()); for (ModuleProvideInfo provide : attr.provides()) { buf.writeIndex(provide.provides()); buf.writeListIndices(provide.providesWith()); } } @Override public AttributeMapper.AttributeStability stability() { return AttributeStability.CP_REFS; } }; /** Attribute mapper for the {@code ModuleHashes} attribute */ public static final AttributeMapper MODULE_HASHES = new AbstractAttributeMapper<>(NAME_MODULE_HASHES) { @Override public ModuleHashesAttribute readAttribute(AttributedElement e, ClassReader cf, int p) { return new BoundAttribute.BoundModuleHashesAttribute(cf, this, p); } @Override protected void writeBody(BufWriter buf, ModuleHashesAttribute attr) { buf.writeIndex(attr.algorithm()); List hashes = attr.hashes(); buf.writeU2(hashes.size()); for (ModuleHashInfo hash : hashes) { buf.writeIndex(hash.moduleName()); buf.writeU2(hash.hash().length); buf.writeBytes(hash.hash()); } } @Override public AttributeMapper.AttributeStability stability() { return AttributeStability.CP_REFS; } }; /** Attribute mapper for the {@code ModuleMainClass} attribute */ public static final AttributeMapper MODULE_MAIN_CLASS = new AbstractAttributeMapper<>(NAME_MODULE_MAIN_CLASS) { @Override public ModuleMainClassAttribute readAttribute(AttributedElement e, ClassReader cf, int p) { return new BoundAttribute.BoundModuleMainClassAttribute(cf, this, p); } @Override protected void writeBody(BufWriter buf, ModuleMainClassAttribute attr) { buf.writeIndex(attr.mainClass()); } @Override public AttributeMapper.AttributeStability stability() { return AttributeStability.CP_REFS; } }; /** Attribute mapper for the {@code ModulePackages} attribute */ public static final AttributeMapper MODULE_PACKAGES = new AbstractAttributeMapper<>(NAME_MODULE_PACKAGES) { @Override public ModulePackagesAttribute readAttribute(AttributedElement e, ClassReader cf, int p) { return new BoundAttribute.BoundModulePackagesAttribute(cf, this, p); } @Override protected void writeBody(BufWriter buf, ModulePackagesAttribute attr) { buf.writeListIndices(attr.packages()); } @Override public AttributeMapper.AttributeStability stability() { return AttributeStability.CP_REFS; } }; /** Attribute mapper for the {@code ModuleResolution} attribute */ public static final AttributeMapper MODULE_RESOLUTION = new AbstractAttributeMapper<>(NAME_MODULE_RESOLUTION) { @Override public ModuleResolutionAttribute readAttribute(AttributedElement e, ClassReader cf, int p) { return new BoundAttribute.BoundModuleResolutionAttribute(cf, this, p); } @Override protected void writeBody(BufWriter buf, ModuleResolutionAttribute attr) { buf.writeU2(attr.resolutionFlags()); } @Override public AttributeMapper.AttributeStability stability() { return AttributeStability.STATELESS; } }; /** Attribute mapper for the {@code ModuleTarget} attribute */ public static final AttributeMapper MODULE_TARGET = new AbstractAttributeMapper<>(NAME_MODULE_TARGET) { @Override public ModuleTargetAttribute readAttribute(AttributedElement e, ClassReader cf, int p) { return new BoundAttribute.BoundModuleTargetAttribute(cf, this, p); } @Override protected void writeBody(BufWriter buf, ModuleTargetAttribute attr) { buf.writeIndex(attr.targetPlatform()); } @Override public AttributeMapper.AttributeStability stability() { return AttributeStability.CP_REFS; } }; /** Attribute mapper for the {@code NestHost} attribute */ public static final AttributeMapper NEST_HOST = new AbstractAttributeMapper<>(NAME_NEST_HOST) { @Override public NestHostAttribute readAttribute(AttributedElement e, ClassReader cf, int p) { return new BoundAttribute.BoundNestHostAttribute(cf, this, p); } @Override protected void writeBody(BufWriter buf, NestHostAttribute attr) { buf.writeIndex(attr.nestHost()); } @Override public AttributeMapper.AttributeStability stability() { return AttributeStability.CP_REFS; } }; /** Attribute mapper for the {@code NestMembers} attribute */ public static final AttributeMapper NEST_MEMBERS = new AbstractAttributeMapper<>(NAME_NEST_MEMBERS) { @Override public NestMembersAttribute readAttribute(AttributedElement e, ClassReader cf, int p) { return new BoundAttribute.BoundNestMembersAttribute(cf, this, p); } @Override protected void writeBody(BufWriter buf, NestMembersAttribute attr) { buf.writeListIndices(attr.nestMembers()); } @Override public AttributeMapper.AttributeStability stability() { return AttributeStability.CP_REFS; } }; /** Attribute mapper for the {@code PermittedSubclasses} attribute */ public static final AttributeMapper PERMITTED_SUBCLASSES = new AbstractAttributeMapper<>(NAME_PERMITTED_SUBCLASSES) { @Override public PermittedSubclassesAttribute readAttribute(AttributedElement e, ClassReader cf, int p) { return new BoundAttribute.BoundPermittedSubclassesAttribute(cf, this, p); } @Override protected void writeBody(BufWriter buf, PermittedSubclassesAttribute attr) { buf.writeListIndices(attr.permittedSubclasses()); } @Override public AttributeMapper.AttributeStability stability() { return AttributeStability.CP_REFS; } }; /** Attribute mapper for the {@code Record} attribute */ public static final AttributeMapper RECORD = new AbstractAttributeMapper<>(NAME_RECORD) { @Override public RecordAttribute readAttribute(AttributedElement e, ClassReader cf, int p) { return new BoundAttribute.BoundRecordAttribute(cf, this, p); } @Override protected void writeBody(BufWriter buf, RecordAttribute attr) { List components = attr.components(); buf.writeU2(components.size()); for (RecordComponentInfo info : components) { buf.writeIndex(info.name()); buf.writeIndex(info.descriptor()); buf.writeList(info.attributes()); } } @Override public AttributeMapper.AttributeStability stability() { return AttributeStability.CP_REFS; } }; /** Attribute mapper for the {@code RuntimeInvisibleAnnotations} attribute */ public static final AttributeMapper RUNTIME_INVISIBLE_ANNOTATIONS = new AbstractAttributeMapper<>(NAME_RUNTIME_INVISIBLE_ANNOTATIONS) { @Override public RuntimeInvisibleAnnotationsAttribute readAttribute(AttributedElement enclosing, ClassReader cf, int pos) { return new BoundAttribute.BoundRuntimeInvisibleAnnotationsAttribute(cf, pos); } @Override protected void writeBody(BufWriter buf, RuntimeInvisibleAnnotationsAttribute attr) { buf.writeList(attr.annotations()); } @Override public AttributeMapper.AttributeStability stability() { return AttributeStability.CP_REFS; } }; /** Attribute mapper for the {@code RuntimeInvisibleParameterAnnotations} attribute */ public static final AttributeMapper RUNTIME_INVISIBLE_PARAMETER_ANNOTATIONS = new AbstractAttributeMapper<>(NAME_RUNTIME_INVISIBLE_PARAMETER_ANNOTATIONS) { @Override public RuntimeInvisibleParameterAnnotationsAttribute readAttribute(AttributedElement e, ClassReader cf, int p) { return new BoundAttribute.BoundRuntimeInvisibleParameterAnnotationsAttribute(cf, this, p); } @Override protected void writeBody(BufWriter buf, RuntimeInvisibleParameterAnnotationsAttribute attr) { List> lists = attr.parameterAnnotations(); buf.writeU1(lists.size()); for (List list : lists) buf.writeList(list); } @Override public AttributeMapper.AttributeStability stability() { return AttributeStability.CP_REFS; } }; /** Attribute mapper for the {@code RuntimeInvisibleTypeAnnotations} attribute */ public static final AttributeMapper RUNTIME_INVISIBLE_TYPE_ANNOTATIONS = new AbstractAttributeMapper<>(NAME_RUNTIME_INVISIBLE_TYPE_ANNOTATIONS) { @Override public RuntimeInvisibleTypeAnnotationsAttribute readAttribute(AttributedElement e, ClassReader cf, int p) { return new BoundAttribute.BoundRuntimeInvisibleTypeAnnotationsAttribute(e, cf, this, p); } @Override protected void writeBody(BufWriter buf, RuntimeInvisibleTypeAnnotationsAttribute attr) { buf.writeList(attr.annotations()); } @Override public AttributeMapper.AttributeStability stability() { return AttributeStability.UNSTABLE; } }; /** Attribute mapper for the {@code RuntimeVisibleAnnotations} attribute */ public static final AttributeMapper RUNTIME_VISIBLE_ANNOTATIONS = new AbstractAttributeMapper<>(NAME_RUNTIME_VISIBLE_ANNOTATIONS) { @Override public RuntimeVisibleAnnotationsAttribute readAttribute(AttributedElement enclosing, ClassReader cf, int pos) { return new BoundAttribute.BoundRuntimeVisibleAnnotationsAttribute(cf, pos); } @Override protected void writeBody(BufWriter buf, RuntimeVisibleAnnotationsAttribute attr) { buf.writeList(attr.annotations()); } @Override public AttributeMapper.AttributeStability stability() { return AttributeStability.CP_REFS; } }; /** Attribute mapper for the {@code RuntimeVisibleParameterAnnotations} attribute */ public static final AttributeMapper RUNTIME_VISIBLE_PARAMETER_ANNOTATIONS = new AbstractAttributeMapper<>(NAME_RUNTIME_VISIBLE_PARAMETER_ANNOTATIONS) { @Override public RuntimeVisibleParameterAnnotationsAttribute readAttribute(AttributedElement e, ClassReader cf, int p) { return new BoundAttribute.BoundRuntimeVisibleParameterAnnotationsAttribute(cf, this, p); } @Override protected void writeBody(BufWriter buf, RuntimeVisibleParameterAnnotationsAttribute attr) { List> lists = attr.parameterAnnotations(); buf.writeU1(lists.size()); for (List list : lists) buf.writeList(list); } @Override public AttributeMapper.AttributeStability stability() { return AttributeStability.CP_REFS; } }; /** Attribute mapper for the {@code RuntimeVisibleTypeAnnotations} attribute */ public static final AttributeMapper RUNTIME_VISIBLE_TYPE_ANNOTATIONS = new AbstractAttributeMapper<>(NAME_RUNTIME_VISIBLE_TYPE_ANNOTATIONS) { @Override public RuntimeVisibleTypeAnnotationsAttribute readAttribute(AttributedElement e, ClassReader cf, int p) { return new BoundAttribute.BoundRuntimeVisibleTypeAnnotationsAttribute(e, cf, this, p); } @Override protected void writeBody(BufWriter buf, RuntimeVisibleTypeAnnotationsAttribute attr) { buf.writeList(attr.annotations()); } @Override public AttributeMapper.AttributeStability stability() { return AttributeStability.UNSTABLE; } }; /** Attribute mapper for the {@code Signature} attribute */ public static final AttributeMapper SIGNATURE = new AbstractAttributeMapper<>(NAME_SIGNATURE) { @Override public SignatureAttribute readAttribute(AttributedElement e, ClassReader cf, int p) { return new BoundAttribute.BoundSignatureAttribute(cf, this, p); } @Override protected void writeBody(BufWriter buf, SignatureAttribute attr) { buf.writeIndex(attr.signature()); } @Override public AttributeMapper.AttributeStability stability() { return AttributeStability.CP_REFS; } }; /** Attribute mapper for the {@code SourceDebugExtension} attribute */ public static final AttributeMapper SOURCE_DEBUG_EXTENSION = new AbstractAttributeMapper<>(NAME_SOURCE_DEBUG_EXTENSION) { @Override public SourceDebugExtensionAttribute readAttribute(AttributedElement e, ClassReader cf, int p) { return new BoundAttribute.BoundSourceDebugExtensionAttribute(cf, this, p); } @Override protected void writeBody(BufWriter buf, SourceDebugExtensionAttribute attr) { buf.writeBytes(attr.contents()); } @Override public AttributeMapper.AttributeStability stability() { return AttributeStability.STATELESS; } }; /** Attribute mapper for the {@code SourceFile} attribute */ public static final AttributeMapper SOURCE_FILE = new AbstractAttributeMapper<>(NAME_SOURCE_FILE) { @Override public SourceFileAttribute readAttribute(AttributedElement e, ClassReader cf, int p) { return new BoundAttribute.BoundSourceFileAttribute(cf, this, p); } @Override protected void writeBody(BufWriter buf, SourceFileAttribute attr) { buf.writeIndex(attr.sourceFile()); } @Override public AttributeMapper.AttributeStability stability() { return AttributeStability.CP_REFS; } }; /** Attribute mapper for the {@code SourceID} attribute */ public static final AttributeMapper SOURCE_ID = new AbstractAttributeMapper<>(NAME_SOURCE_ID) { @Override public SourceIDAttribute readAttribute(AttributedElement e, ClassReader cf, int p) { return new BoundAttribute.BoundSourceIDAttribute(cf, this, p); } @Override protected void writeBody(BufWriter buf, SourceIDAttribute attr) { buf.writeIndex(attr.sourceId()); } @Override public AttributeMapper.AttributeStability stability() { return AttributeStability.CP_REFS; } }; /** Attribute mapper for the {@code StackMapTable} attribute */ public static final AttributeMapper STACK_MAP_TABLE = new AbstractAttributeMapper<>(NAME_STACK_MAP_TABLE) { @Override public StackMapTableAttribute readAttribute(AttributedElement e, ClassReader cf, int p) { return new BoundAttribute.BoundStackMapTableAttribute((CodeImpl)e, cf, this, p); } @Override protected void writeBody(BufWriter b, StackMapTableAttribute attr) { StackMapDecoder.writeFrames(b, attr.entries()); } @Override public AttributeMapper.AttributeStability stability() { return AttributeStability.LABELS; } }; /** Attribute mapper for the {@code Synthetic} attribute */ public static final AttributeMapper SYNTHETIC = new AbstractAttributeMapper<>(NAME_SYNTHETIC, true) { @Override public SyntheticAttribute readAttribute(AttributedElement e, ClassReader cf, int p) { return new BoundAttribute.BoundSyntheticAttribute(cf, this, p); } @Override protected void writeBody(BufWriter buf, SyntheticAttribute attr) { // empty } @Override public AttributeMapper.AttributeStability stability() { return AttributeStability.STATELESS; } }; /** * {@return the attribute mapper for a standard attribute} * * @param name the name of the attribute to find */ public static AttributeMapper standardAttribute(Utf8Entry name) { return _ATTR_MAP.get(name); } /** * All standard attribute mappers. */ public static final Set> 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); private static final Map> _ATTR_MAP; //no lambdas here as this is on critical JDK boostrap path static { var map = new HashMap>(64); for (var am : PREDEFINED_ATTRIBUTES) { map.put(AbstractPoolEntry.rawUtf8EntryFromStandardAttributeName(am.name()), am); } _ATTR_MAP = Collections.unmodifiableMap(map); } }