8343881: java.lang.classfile.Attribute attributeName() method should return Utf8Entry

Reviewed-by: liach
This commit is contained in:
Adam Sotona 2024-11-15 11:40:15 +00:00
parent 75c651f859
commit ba39321902
29 changed files with 415 additions and 45 deletions

View file

@ -25,6 +25,7 @@
package java.lang.classfile;
import java.lang.classfile.attribute.*;
import java.lang.classfile.constantpool.Utf8Entry;
import jdk.internal.classfile.impl.BoundAttribute;
import jdk.internal.classfile.impl.UnboundAttribute;
@ -65,7 +66,7 @@ public sealed interface Attribute<A extends Attribute<A>>
/**
* {@return the name of the attribute}
*/
String attributeName();
Utf8Entry attributeName();
/**
* {@return the {@link AttributeMapper} associated with this attribute}

View file

@ -24,6 +24,8 @@
*/
package java.lang.classfile;
import java.lang.classfile.constantpool.Utf8Entry;
import jdk.internal.classfile.impl.TemporaryConstantPool;
import jdk.internal.javac.PreviewFeature;
/**
@ -55,8 +57,8 @@ public abstract non-sealed class CustomAttribute<T extends CustomAttribute<T>>
}
@Override
public final String attributeName() {
return mapper.name();
public Utf8Entry attributeName() {
return TemporaryConstantPool.INSTANCE.utf8Entry(mapper.name());
}
@Override

View file

@ -64,7 +64,7 @@ public sealed abstract class AbstractAttributeMapper<T extends Attribute<T>>
@Override
public final void writeAttribute(BufWriter writer, T attr) {
BufWriterImpl buf = (BufWriterImpl) writer;
buf.writeIndex(buf.constantPool().utf8Entry(name));
buf.writeIndex(attr.attributeName());
int lengthIndex = buf.skip(4);
writeBody(buf, attr);
int written = buf.size() - lengthIndex - 4;

View file

@ -47,6 +47,7 @@ public abstract sealed class BoundAttribute<T extends Attribute<T>>
private final AttributeMapper<T> mapper;
final ClassReaderImpl classReader;
final int payloadStart;
Utf8Entry name;
BoundAttribute(ClassReader classReader, AttributeMapper<T> mapper, int payloadStart) {
this.mapper = mapper;
@ -59,8 +60,11 @@ public abstract sealed class BoundAttribute<T extends Attribute<T>>
}
@Override
public String attributeName() {
return mapper.name();
public Utf8Entry attributeName() {
if (name == null) {
name = classReader.readEntry(payloadStart - 6, Utf8Entry.class);
}
return name;
}
@Override

View file

@ -574,7 +574,7 @@ public final class ClassPrinterImpl {
list("flags", "flag", clm.flags().flags().stream().map(AccessFlag::name)),
leaf("superclass", clm.superclass().map(ClassEntry::asInternalName).orElse("")),
list("interfaces", "interface", clm.interfaces().stream().map(ClassEntry::asInternalName)),
list("attributes", "attribute", clm.attributes().stream().map(Attribute::attributeName)))
list("attributes", "attribute", clm.attributes().stream().map(Attribute::attributeName).map(Utf8Entry::stringValue)))
.with(constantPoolToTree(clm.constantPool(), verbosity))
.with(attributesToTree(clm.attributes(), verbosity))
.with(new ListNodeImpl(BLOCK, "fields", clm.fields().stream().map(f ->
@ -672,7 +672,7 @@ public final class ClassPrinterImpl {
"flag", f.flags().flags().stream().map(AccessFlag::name)),
leaf("field type", f.fieldType().stringValue()),
list("attributes",
"attribute", f.attributes().stream().map(Attribute::attributeName)))
"attribute", f.attributes().stream().map(Attribute::attributeName).map(Utf8Entry::stringValue)))
.with(attributesToTree(f.attributes(), verbosity));
}
@ -683,7 +683,7 @@ public final class ClassPrinterImpl {
"flag", m.flags().flags().stream().map(AccessFlag::name)),
leaf("method type", m.methodType().stringValue()),
list("attributes",
"attribute", m.attributes().stream().map(Attribute::attributeName)))
"attribute", m.attributes().stream().map(Attribute::attributeName).map(Utf8Entry::stringValue)))
.with(attributesToTree(m.attributes(), verbosity))
.with(codeToTree((CodeAttribute)m.code().orElse(null), verbosity));
}
@ -694,7 +694,7 @@ public final class ClassPrinterImpl {
codeNode.with(leaf("max stack", com.maxStack()));
codeNode.with(leaf("max locals", com.maxLocals()));
codeNode.with(list("attributes",
"attribute", com.attributes().stream().map(Attribute::attributeName)));
"attribute", com.attributes().stream().map(Attribute::attributeName).map(Utf8Entry::stringValue)));
var stackMap = new MapNodeImpl(BLOCK, "stack map frames");
var visibleTypeAnnos = new LinkedHashMap<Integer, List<TypeAnnotation>>();
var invisibleTypeAnnos = new LinkedHashMap<Integer, List<TypeAnnotation>>();
@ -996,7 +996,7 @@ public final class ClassPrinterImpl {
"name", rc.name().stringValue(),
"type", rc.descriptor().stringValue()))
.with(list("attributes", "attribute", rc.attributes().stream()
.map(Attribute::attributeName)))
.map(Attribute::attributeName).map(Utf8Entry::stringValue)))
.with(attributesToTree(rc.attributes(), verbosity)))));
case AnnotationDefaultAttribute ada ->
nodes.add(new MapNodeImpl(FLOW, "annotation default").with(elementValueToTree(ada.defaultValue())));

View file

@ -241,6 +241,11 @@ public final class DirectCodeBuilder
if (crSize < characterRangesCount)
b.patchU2(pos, crSize);
}
@Override
public Utf8Entry attributeName() {
return constantPool.utf8Entry(Attributes.NAME_CHARACTER_RANGE_TABLE);
}
};
attributes.withAttribute(a);
}
@ -265,6 +270,11 @@ public final class DirectCodeBuilder
if (lvSize < localVariablesCount)
b.patchU2(pos, lvSize);
}
@Override
public Utf8Entry attributeName() {
return constantPool.utf8Entry(Attributes.NAME_LOCAL_VARIABLE_TABLE);
}
};
attributes.withAttribute(a);
}
@ -289,6 +299,11 @@ public final class DirectCodeBuilder
if (lvtSize < localVariableTypesCount)
b.patchU2(pos, lvtSize);
}
@Override
public Utf8Entry attributeName() {
return constantPool.utf8Entry(Attributes.NAME_LOCAL_VARIABLE_TYPE_TABLE);
}
};
attributes.withAttribute(a);
}
@ -371,6 +386,11 @@ public final class DirectCodeBuilder
dcb.attributes.writeTo(buf);
buf.setLabelContext(null);
}
@Override
public Utf8Entry attributeName() {
return constantPool.utf8Entry(Attributes.NAME_CODE);
}
};
}
@ -416,6 +436,11 @@ public final class DirectCodeBuilder
b.writeU2(buf.size() / 4);
b.writeBytes(buf);
}
@Override
public Utf8Entry attributeName() {
return buf.constantPool().utf8Entry(Attributes.NAME_LINE_NUMBER_TABLE);
}
}
private boolean codeAndExceptionsMatch(int codeLength) {

View file

@ -146,6 +146,11 @@ public final class SplitConstantPool implements ConstantPoolBuilder {
for (int i = 0; i < bsmSize; i++)
bootstrapMethodEntry(i).writeTo(buf);
}
@Override
public Utf8Entry attributeName() {
return utf8Entry(Attributes.NAME_BOOTSTRAP_METHODS);
}
};
a.writeTo(buf);
}

View file

@ -35,6 +35,7 @@ import java.lang.classfile.constantpool.ConstantDynamicEntry;
import java.lang.classfile.constantpool.ConstantPoolBuilder;
import java.lang.classfile.constantpool.InvokeDynamicEntry;
import java.lang.classfile.constantpool.MemberRefEntry;
import java.lang.classfile.constantpool.Utf8Entry;
import java.lang.constant.ClassDesc;
import java.lang.constant.MethodTypeDesc;
import java.util.ArrayList;
@ -401,6 +402,11 @@ public final class StackMapGenerator {
prevFrame = fr;
}
}
@Override
public Utf8Entry attributeName() {
return cp.utf8Entry(Attributes.NAME_STACK_MAP_TABLE);
}
};
}

View file

@ -54,11 +54,6 @@ public abstract sealed class UnboundAttribute<T extends Attribute<T>>
return mapper;
}
@Override
public String attributeName() {
return mapper.name();
}
@Override
@SuppressWarnings("unchecked")
public void writeTo(BufWriterImpl buf) {
@ -93,6 +88,8 @@ public abstract sealed class UnboundAttribute<T extends Attribute<T>>
extends UnboundAttribute<ConstantValueAttribute>
implements ConstantValueAttribute {
private static final Utf8Entry NAME = TemporaryConstantPool.INSTANCE.utf8Entry(Attributes.NAME_CONSTANT_VALUE);
private final ConstantValueEntry entry;
public UnboundConstantValueAttribute(ConstantValueEntry entry) {
@ -105,27 +102,50 @@ public abstract sealed class UnboundAttribute<T extends Attribute<T>>
return entry;
}
@Override
public Utf8Entry attributeName() {
return NAME;
}
}
public static final class UnboundDeprecatedAttribute
extends UnboundAttribute<DeprecatedAttribute>
implements DeprecatedAttribute {
private static final Utf8Entry NAME = TemporaryConstantPool.INSTANCE.utf8Entry(Attributes.NAME_DEPRECATED);
public UnboundDeprecatedAttribute() {
super(Attributes.deprecated());
}
@Override
public Utf8Entry attributeName() {
return NAME;
}
}
public static final class UnboundSyntheticAttribute
extends UnboundAttribute<SyntheticAttribute>
implements SyntheticAttribute {
private static final Utf8Entry NAME = TemporaryConstantPool.INSTANCE.utf8Entry(Attributes.NAME_SYNTHETIC);
public UnboundSyntheticAttribute() {
super(Attributes.synthetic());
}
@Override
public Utf8Entry attributeName() {
return NAME;
}
}
public static final class UnboundSignatureAttribute
extends UnboundAttribute<SignatureAttribute>
implements SignatureAttribute {
private static final Utf8Entry NAME = TemporaryConstantPool.INSTANCE.utf8Entry(Attributes.NAME_SIGNATURE);
private final Utf8Entry signature;
public UnboundSignatureAttribute(Utf8Entry signature) {
@ -137,11 +157,19 @@ public abstract sealed class UnboundAttribute<T extends Attribute<T>>
public Utf8Entry signature() {
return signature;
}
@Override
public Utf8Entry attributeName() {
return NAME;
}
}
public static final class UnboundExceptionsAttribute
extends UnboundAttribute<ExceptionsAttribute>
implements ExceptionsAttribute {
private static final Utf8Entry NAME = TemporaryConstantPool.INSTANCE.utf8Entry(Attributes.NAME_EXCEPTIONS);
private final List<ClassEntry> exceptions;
public UnboundExceptionsAttribute(List<ClassEntry> exceptions) {
@ -153,11 +181,19 @@ public abstract sealed class UnboundAttribute<T extends Attribute<T>>
public List<ClassEntry> exceptions() {
return exceptions;
}
@Override
public Utf8Entry attributeName() {
return NAME;
}
}
public static final class UnboundAnnotationDefaultAttribute
extends UnboundAttribute<AnnotationDefaultAttribute>
implements AnnotationDefaultAttribute {
private static final Utf8Entry NAME = TemporaryConstantPool.INSTANCE.utf8Entry(Attributes.NAME_ANNOTATION_DEFAULT);
private final AnnotationValue annotationDefault;
public UnboundAnnotationDefaultAttribute(AnnotationValue annotationDefault) {
@ -169,10 +205,18 @@ public abstract sealed class UnboundAttribute<T extends Attribute<T>>
public AnnotationValue defaultValue() {
return annotationDefault;
}
@Override
public Utf8Entry attributeName() {
return NAME;
}
}
public static final class UnboundSourceFileAttribute extends UnboundAttribute<SourceFileAttribute>
implements SourceFileAttribute {
private static final Utf8Entry NAME = TemporaryConstantPool.INSTANCE.utf8Entry(Attributes.NAME_SOURCE_FILE);
private final Utf8Entry sourceFile;
public UnboundSourceFileAttribute(Utf8Entry sourceFile) {
@ -185,10 +229,17 @@ public abstract sealed class UnboundAttribute<T extends Attribute<T>>
return sourceFile;
}
@Override
public Utf8Entry attributeName() {
return NAME;
}
}
public static final class UnboundStackMapTableAttribute extends UnboundAttribute<StackMapTableAttribute>
implements StackMapTableAttribute {
private static final Utf8Entry NAME = TemporaryConstantPool.INSTANCE.utf8Entry(Attributes.NAME_STACK_MAP_TABLE);
private final List<StackMapFrameInfo> entries;
public UnboundStackMapTableAttribute(List<StackMapFrameInfo> entries) {
@ -200,11 +251,19 @@ public abstract sealed class UnboundAttribute<T extends Attribute<T>>
public List<StackMapFrameInfo> entries() {
return entries;
}
@Override
public Utf8Entry attributeName() {
return NAME;
}
}
public static final class UnboundInnerClassesAttribute
extends UnboundAttribute<InnerClassesAttribute>
implements InnerClassesAttribute {
private static final Utf8Entry NAME = TemporaryConstantPool.INSTANCE.utf8Entry(Attributes.NAME_INNER_CLASSES);
private final List<InnerClassInfo> innerClasses;
public UnboundInnerClassesAttribute(List<InnerClassInfo> innerClasses) {
@ -216,11 +275,19 @@ public abstract sealed class UnboundAttribute<T extends Attribute<T>>
public List<InnerClassInfo> classes() {
return innerClasses;
}
@Override
public Utf8Entry attributeName() {
return NAME;
}
}
public static final class UnboundRecordAttribute
extends UnboundAttribute<RecordAttribute>
implements RecordAttribute {
private static final Utf8Entry NAME = TemporaryConstantPool.INSTANCE.utf8Entry(Attributes.NAME_RECORD);
private final List<RecordComponentInfo> components;
public UnboundRecordAttribute(List<RecordComponentInfo> components) {
@ -232,11 +299,19 @@ public abstract sealed class UnboundAttribute<T extends Attribute<T>>
public List<RecordComponentInfo> components() {
return components;
}
@Override
public Utf8Entry attributeName() {
return NAME;
}
}
public static final class UnboundEnclosingMethodAttribute
extends UnboundAttribute<EnclosingMethodAttribute>
implements EnclosingMethodAttribute {
private static final Utf8Entry NAME = TemporaryConstantPool.INSTANCE.utf8Entry(Attributes.NAME_ENCLOSING_METHOD);
private final ClassEntry classEntry;
private final NameAndTypeEntry method;
@ -255,11 +330,19 @@ public abstract sealed class UnboundAttribute<T extends Attribute<T>>
public Optional<NameAndTypeEntry> enclosingMethod() {
return Optional.ofNullable(method);
}
@Override
public Utf8Entry attributeName() {
return NAME;
}
}
public static final class UnboundMethodParametersAttribute
extends UnboundAttribute<MethodParametersAttribute>
implements MethodParametersAttribute {
private static final Utf8Entry NAME = TemporaryConstantPool.INSTANCE.utf8Entry(Attributes.NAME_METHOD_PARAMETERS);
private final List<MethodParameterInfo> parameters;
public UnboundMethodParametersAttribute(List<MethodParameterInfo> parameters) {
@ -271,11 +354,19 @@ public abstract sealed class UnboundAttribute<T extends Attribute<T>>
public List<MethodParameterInfo> parameters() {
return parameters;
}
@Override
public Utf8Entry attributeName() {
return NAME;
}
}
public static final class UnboundModuleTargetAttribute
extends UnboundAttribute<ModuleTargetAttribute>
implements ModuleTargetAttribute {
private static final Utf8Entry NAME = TemporaryConstantPool.INSTANCE.utf8Entry(Attributes.NAME_MODULE_TARGET);
final Utf8Entry moduleTarget;
public UnboundModuleTargetAttribute(Utf8Entry moduleTarget) {
@ -287,11 +378,19 @@ public abstract sealed class UnboundAttribute<T extends Attribute<T>>
public Utf8Entry targetPlatform() {
return moduleTarget;
}
@Override
public Utf8Entry attributeName() {
return NAME;
}
}
public static final class UnboundModuleMainClassAttribute
extends UnboundAttribute<ModuleMainClassAttribute>
implements ModuleMainClassAttribute {
private static final Utf8Entry NAME = TemporaryConstantPool.INSTANCE.utf8Entry(Attributes.NAME_MODULE_MAIN_CLASS);
final ClassEntry mainClass;
public UnboundModuleMainClassAttribute(ClassEntry mainClass) {
@ -303,11 +402,19 @@ public abstract sealed class UnboundAttribute<T extends Attribute<T>>
public ClassEntry mainClass() {
return mainClass;
}
@Override
public Utf8Entry attributeName() {
return NAME;
}
}
public static final class UnboundModuleHashesAttribute
extends UnboundAttribute<ModuleHashesAttribute>
implements ModuleHashesAttribute {
private static final Utf8Entry NAME = TemporaryConstantPool.INSTANCE.utf8Entry(Attributes.NAME_MODULE_HASHES);
private final Utf8Entry algorithm;
private final List<ModuleHashInfo> hashes;
@ -326,11 +433,19 @@ public abstract sealed class UnboundAttribute<T extends Attribute<T>>
public List<ModuleHashInfo> hashes() {
return hashes;
}
@Override
public Utf8Entry attributeName() {
return NAME;
}
}
public static final class UnboundModulePackagesAttribute
extends UnboundAttribute<ModulePackagesAttribute>
implements ModulePackagesAttribute {
private static final Utf8Entry NAME = TemporaryConstantPool.INSTANCE.utf8Entry(Attributes.NAME_MODULE_PACKAGES);
private final Collection<PackageEntry> packages;
public UnboundModulePackagesAttribute(Collection<PackageEntry> packages) {
@ -342,11 +457,19 @@ public abstract sealed class UnboundAttribute<T extends Attribute<T>>
public List<PackageEntry> packages() {
return List.copyOf(packages);
}
@Override
public Utf8Entry attributeName() {
return NAME;
}
}
public static final class UnboundModuleResolutionAttribute
extends UnboundAttribute<ModuleResolutionAttribute>
implements ModuleResolutionAttribute {
private static final Utf8Entry NAME = TemporaryConstantPool.INSTANCE.utf8Entry(Attributes.NAME_MODULE_RESOLUTION);
private final int resolutionFlags;
public UnboundModuleResolutionAttribute(int flags) {
@ -358,11 +481,19 @@ public abstract sealed class UnboundAttribute<T extends Attribute<T>>
public int resolutionFlags() {
return resolutionFlags;
}
@Override
public Utf8Entry attributeName() {
return NAME;
}
}
public static final class UnboundPermittedSubclassesAttribute
extends UnboundAttribute<PermittedSubclassesAttribute>
implements PermittedSubclassesAttribute {
private static final Utf8Entry NAME = TemporaryConstantPool.INSTANCE.utf8Entry(Attributes.NAME_PERMITTED_SUBCLASSES);
private final List<ClassEntry> permittedSubclasses;
public UnboundPermittedSubclassesAttribute(List<ClassEntry> permittedSubclasses) {
@ -374,11 +505,19 @@ public abstract sealed class UnboundAttribute<T extends Attribute<T>>
public List<ClassEntry> permittedSubclasses() {
return permittedSubclasses;
}
@Override
public Utf8Entry attributeName() {
return NAME;
}
}
public static final class UnboundNestMembersAttribute
extends UnboundAttribute<NestMembersAttribute>
implements NestMembersAttribute {
private static final Utf8Entry NAME = TemporaryConstantPool.INSTANCE.utf8Entry(Attributes.NAME_NEST_MEMBERS);
private final List<ClassEntry> memberEntries;
public UnboundNestMembersAttribute(List<ClassEntry> memberEntries) {
@ -390,11 +529,19 @@ public abstract sealed class UnboundAttribute<T extends Attribute<T>>
public List<ClassEntry> nestMembers() {
return memberEntries;
}
@Override
public Utf8Entry attributeName() {
return NAME;
}
}
public static final class UnboundNestHostAttribute
extends UnboundAttribute<NestHostAttribute>
implements NestHostAttribute {
private static final Utf8Entry NAME = TemporaryConstantPool.INSTANCE.utf8Entry(Attributes.NAME_NEST_HOST);
private final ClassEntry hostEntry;
public UnboundNestHostAttribute(ClassEntry hostEntry) {
@ -406,11 +553,19 @@ public abstract sealed class UnboundAttribute<T extends Attribute<T>>
public ClassEntry nestHost() {
return hostEntry;
}
@Override
public Utf8Entry attributeName() {
return NAME;
}
}
public static final class UnboundCompilationIDAttribute
extends UnboundAttribute<CompilationIDAttribute>
implements CompilationIDAttribute {
private static final Utf8Entry NAME = TemporaryConstantPool.INSTANCE.utf8Entry(Attributes.NAME_COMPILATION_ID);
private final Utf8Entry idEntry;
public UnboundCompilationIDAttribute(Utf8Entry idEntry) {
@ -422,11 +577,19 @@ public abstract sealed class UnboundAttribute<T extends Attribute<T>>
public Utf8Entry compilationId() {
return idEntry;
}
@Override
public Utf8Entry attributeName() {
return NAME;
}
}
public static final class UnboundSourceIDAttribute
extends UnboundAttribute<SourceIDAttribute>
implements SourceIDAttribute {
private static final Utf8Entry NAME = TemporaryConstantPool.INSTANCE.utf8Entry(Attributes.NAME_SOURCE_ID);
private final Utf8Entry idEntry;
public UnboundSourceIDAttribute(Utf8Entry idEntry) {
@ -438,11 +601,19 @@ public abstract sealed class UnboundAttribute<T extends Attribute<T>>
public Utf8Entry sourceId() {
return idEntry;
}
@Override
public Utf8Entry attributeName() {
return NAME;
}
}
public static final class UnboundSourceDebugExtensionAttribute
extends UnboundAttribute<SourceDebugExtensionAttribute>
implements SourceDebugExtensionAttribute {
private static final Utf8Entry NAME = TemporaryConstantPool.INSTANCE.utf8Entry(Attributes.NAME_SOURCE_DEBUG_EXTENSION);
private final byte[] contents;
public UnboundSourceDebugExtensionAttribute(byte[] contents) {
@ -454,11 +625,19 @@ public abstract sealed class UnboundAttribute<T extends Attribute<T>>
public byte[] contents() {
return contents;
}
@Override
public Utf8Entry attributeName() {
return NAME;
}
}
public static final class UnboundCharacterRangeTableAttribute
extends UnboundAttribute<CharacterRangeTableAttribute>
implements CharacterRangeTableAttribute {
private static final Utf8Entry NAME = TemporaryConstantPool.INSTANCE.utf8Entry(Attributes.NAME_CHARACTER_RANGE_TABLE);
private final List<CharacterRangeInfo> ranges;
public UnboundCharacterRangeTableAttribute(List<CharacterRangeInfo> ranges) {
@ -470,11 +649,19 @@ public abstract sealed class UnboundAttribute<T extends Attribute<T>>
public List<CharacterRangeInfo> characterRangeTable() {
return ranges;
}
@Override
public Utf8Entry attributeName() {
return NAME;
}
}
public static final class UnboundLineNumberTableAttribute
extends UnboundAttribute<LineNumberTableAttribute>
implements LineNumberTableAttribute {
private static final Utf8Entry NAME = TemporaryConstantPool.INSTANCE.utf8Entry(Attributes.NAME_LINE_NUMBER_TABLE);
private final List<LineNumberInfo> lines;
public UnboundLineNumberTableAttribute(List<LineNumberInfo> lines) {
@ -486,11 +673,19 @@ public abstract sealed class UnboundAttribute<T extends Attribute<T>>
public List<LineNumberInfo> lineNumbers() {
return lines;
}
@Override
public Utf8Entry attributeName() {
return NAME;
}
}
public static final class UnboundLocalVariableTableAttribute
extends UnboundAttribute<LocalVariableTableAttribute>
implements LocalVariableTableAttribute {
private static final Utf8Entry NAME = TemporaryConstantPool.INSTANCE.utf8Entry(Attributes.NAME_LOCAL_VARIABLE_TABLE);
private final List<LocalVariableInfo> locals;
public UnboundLocalVariableTableAttribute(List<LocalVariableInfo> locals) {
@ -502,11 +697,19 @@ public abstract sealed class UnboundAttribute<T extends Attribute<T>>
public List<LocalVariableInfo> localVariables() {
return locals;
}
@Override
public Utf8Entry attributeName() {
return NAME;
}
}
public static final class UnboundLocalVariableTypeTableAttribute
extends UnboundAttribute<LocalVariableTypeTableAttribute>
implements LocalVariableTypeTableAttribute {
private static final Utf8Entry NAME = TemporaryConstantPool.INSTANCE.utf8Entry(Attributes.NAME_LOCAL_VARIABLE_TYPE_TABLE);
private final List<LocalVariableTypeInfo> locals;
public UnboundLocalVariableTypeTableAttribute(List<LocalVariableTypeInfo> locals) {
@ -518,11 +721,19 @@ public abstract sealed class UnboundAttribute<T extends Attribute<T>>
public List<LocalVariableTypeInfo> localVariableTypes() {
return locals;
}
@Override
public Utf8Entry attributeName() {
return NAME;
}
}
public static final class UnboundRuntimeVisibleAnnotationsAttribute
extends UnboundAttribute<RuntimeVisibleAnnotationsAttribute>
implements RuntimeVisibleAnnotationsAttribute {
private static final Utf8Entry NAME = TemporaryConstantPool.INSTANCE.utf8Entry(Attributes.NAME_RUNTIME_VISIBLE_ANNOTATIONS);
private final List<Annotation> elements;
public UnboundRuntimeVisibleAnnotationsAttribute(List<Annotation> elements) {
@ -534,11 +745,19 @@ public abstract sealed class UnboundAttribute<T extends Attribute<T>>
public List<Annotation> annotations() {
return elements;
}
@Override
public Utf8Entry attributeName() {
return NAME;
}
}
public static final class UnboundRuntimeInvisibleAnnotationsAttribute
extends UnboundAttribute<RuntimeInvisibleAnnotationsAttribute>
implements RuntimeInvisibleAnnotationsAttribute {
private static final Utf8Entry NAME = TemporaryConstantPool.INSTANCE.utf8Entry(Attributes.NAME_RUNTIME_INVISIBLE_ANNOTATIONS);
private final List<Annotation> elements;
public UnboundRuntimeInvisibleAnnotationsAttribute(List<Annotation> elements) {
@ -550,11 +769,19 @@ public abstract sealed class UnboundAttribute<T extends Attribute<T>>
public List<Annotation> annotations() {
return elements;
}
@Override
public Utf8Entry attributeName() {
return NAME;
}
}
public static final class UnboundRuntimeVisibleParameterAnnotationsAttribute
extends UnboundAttribute<RuntimeVisibleParameterAnnotationsAttribute>
implements RuntimeVisibleParameterAnnotationsAttribute {
private static final Utf8Entry NAME = TemporaryConstantPool.INSTANCE.utf8Entry(Attributes.NAME_RUNTIME_VISIBLE_PARAMETER_ANNOTATIONS);
private final List<List<Annotation>> elements;
public UnboundRuntimeVisibleParameterAnnotationsAttribute(List<List<Annotation>> elements) {
@ -572,11 +799,19 @@ public abstract sealed class UnboundAttribute<T extends Attribute<T>>
public List<List<Annotation>> parameterAnnotations() {
return elements;
}
@Override
public Utf8Entry attributeName() {
return NAME;
}
}
public static final class UnboundRuntimeInvisibleParameterAnnotationsAttribute
extends UnboundAttribute<RuntimeInvisibleParameterAnnotationsAttribute>
implements RuntimeInvisibleParameterAnnotationsAttribute {
private static final Utf8Entry NAME = TemporaryConstantPool.INSTANCE.utf8Entry(Attributes.NAME_RUNTIME_INVISIBLE_PARAMETER_ANNOTATIONS);
private final List<List<Annotation>> elements;
public UnboundRuntimeInvisibleParameterAnnotationsAttribute(List<List<Annotation>> elements) {
@ -594,11 +829,19 @@ public abstract sealed class UnboundAttribute<T extends Attribute<T>>
public List<List<Annotation>> parameterAnnotations() {
return elements;
}
@Override
public Utf8Entry attributeName() {
return NAME;
}
}
public static final class UnboundRuntimeVisibleTypeAnnotationsAttribute
extends UnboundAttribute<RuntimeVisibleTypeAnnotationsAttribute>
implements RuntimeVisibleTypeAnnotationsAttribute {
private static final Utf8Entry NAME = TemporaryConstantPool.INSTANCE.utf8Entry(Attributes.NAME_RUNTIME_VISIBLE_TYPE_ANNOTATIONS);
private final List<TypeAnnotation> elements;
public UnboundRuntimeVisibleTypeAnnotationsAttribute(List<TypeAnnotation> elements) {
@ -610,11 +853,19 @@ public abstract sealed class UnboundAttribute<T extends Attribute<T>>
public List<TypeAnnotation> annotations() {
return elements;
}
@Override
public Utf8Entry attributeName() {
return NAME;
}
}
public static final class UnboundRuntimeInvisibleTypeAnnotationsAttribute
extends UnboundAttribute<RuntimeInvisibleTypeAnnotationsAttribute>
implements RuntimeInvisibleTypeAnnotationsAttribute {
private static final Utf8Entry NAME = TemporaryConstantPool.INSTANCE.utf8Entry(Attributes.NAME_RUNTIME_INVISIBLE_TYPE_ANNOTATIONS);
private final List<TypeAnnotation> elements;
public UnboundRuntimeInvisibleTypeAnnotationsAttribute(List<TypeAnnotation> elements) {
@ -626,6 +877,11 @@ public abstract sealed class UnboundAttribute<T extends Attribute<T>>
public List<TypeAnnotation> annotations() {
return elements;
}
@Override
public Utf8Entry attributeName() {
return NAME;
}
}
public record UnboundCharacterRangeInfo(int startPc, int endPc,
@ -749,6 +1005,9 @@ public abstract sealed class UnboundAttribute<T extends Attribute<T>>
implements TypeAnnotation.TypePathComponent {}
public static final class UnboundModuleAttribute extends UnboundAttribute<ModuleAttribute> implements ModuleAttribute {
private static final Utf8Entry NAME = TemporaryConstantPool.INSTANCE.utf8Entry(Attributes.NAME_MODULE);
private final ModuleEntry moduleName;
private final int moduleFlags;
private final Utf8Entry moduleVersion;
@ -817,6 +1076,11 @@ public abstract sealed class UnboundAttribute<T extends Attribute<T>>
public List<ModuleProvideInfo> provides() {
return provides;
}
@Override
public Utf8Entry attributeName() {
return NAME;
}
}
public abstract static non-sealed class AdHocAttribute<T extends Attribute<T>>
@ -841,6 +1105,9 @@ public abstract sealed class UnboundAttribute<T extends Attribute<T>>
public static final class EmptyBootstrapAttribute
extends UnboundAttribute<BootstrapMethodsAttribute>
implements BootstrapMethodsAttribute {
private static final Utf8Entry NAME = TemporaryConstantPool.INSTANCE.utf8Entry(Attributes.NAME_BOOTSTRAP_METHODS);
public EmptyBootstrapAttribute() {
super(Attributes.bootstrapMethods());
}
@ -854,5 +1121,10 @@ public abstract sealed class UnboundAttribute<T extends Attribute<T>>
public List<BootstrapMethodEntry> bootstrapMethods() {
return List.of();
}
@Override
public Utf8Entry attributeName() {
return NAME;
}
}
}

View file

@ -281,6 +281,11 @@ public class Util {
b.writeBytes(bytecode.array(), 0, bytecode.length());
b.writeU2U2(0, 0);//exception handlers & attributes
}
@Override
public Utf8Entry attributeName() {
return cp.utf8Entry(Attributes.NAME_CODE);
}
}))));
ClassPrinter.toYaml(clm.methods().get(0).code().get(), ClassPrinter.Verbosity.TRACE_ALL, dump);
} catch (Error | Exception _) {

View file

@ -176,8 +176,8 @@ public record ParserVerifier(ClassModel classModel) {
if (cfe instanceof AttributedElement ae) {
var attrNames = new HashSet<String>();
for (var a : ae.attributes()) {
if (!a.attributeMapper().allowMultiple() && !attrNames.add(a.attributeName())) {
errors.add(new VerifyError("Multiple %s attributes in %s".formatted(a.attributeName(), toString(ae))));
if (!a.attributeMapper().allowMultiple() && !attrNames.add(a.attributeName().stringValue())) {
errors.add(new VerifyError("Multiple %s attributes in %s".formatted(a.attributeName().stringValue(), toString(ae))));
}
verifyAttribute(ae, a, errors);
}
@ -331,7 +331,7 @@ public record ParserVerifier(ClassModel classModel) {
throw new AssertionError(a);
};
if (size >= 0 && size != ((BoundAttribute)a).payloadLen()) {
errors.add(new VerifyError("Wrong %s attribute length in %s".formatted(a.attributeName(), toString(ae))));
errors.add(new VerifyError("Wrong %s attribute length in %s".formatted(a.attributeName().stringValue(), toString(ae))));
}
}