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))));
}
}

View File

@ -84,7 +84,7 @@ public class AttributeWriter extends BasicWriter {
int i = 0;
int j = 0;
print(" ");
print(attr.attributeName());
print(attr.attributeName().stringValue());
print(": ");
print("length = 0x" + toHex(data.length));
print(" (unknown attribute)");

View File

@ -41,6 +41,7 @@ import java.lang.classfile.CodeBuilder;
import java.lang.classfile.attribute.MethodParameterInfo;
import java.lang.classfile.attribute.MethodParametersAttribute;
import java.lang.classfile.constantpool.ConstantPoolException;
import java.lang.classfile.constantpool.Utf8Entry;
import java.lang.constant.ClassDesc;
import java.lang.constant.ConstantDescs;
import java.lang.constant.MethodTypeDesc;
@ -89,6 +90,11 @@ class BoundAttributeTest {
b.writeIndex(oneClass);
b.writeIndex(oneClassString);
}
@Override
public Utf8Entry attributeName() {
return cp.utf8Entry(Attributes.NAME_NEST_MEMBERS);
}
});
});

View File

@ -93,6 +93,11 @@ class CorpusTest {
b.writeU2(curPc);
b.writeU2(ln.line());
}
@Override
public Utf8Entry attributeName() {
return cob.constantPool().utf8Entry(Attributes.NAME_LINE_NUMBER_TABLE);
}
});
case LocalVariable lv -> dcob.writeAttribute(new UnboundAttribute.AdHocAttribute<>(Attributes.localVariableTable()) {
@Override
@ -100,6 +105,11 @@ class CorpusTest {
b.writeU2(1);
Util.writeLocalVariable(b, lv);
}
@Override
public Utf8Entry attributeName() {
return cob.constantPool().utf8Entry(Attributes.NAME_LOCAL_VARIABLE_TABLE);
}
});
case LocalVariableType lvt -> dcob.writeAttribute(new UnboundAttribute.AdHocAttribute<>(Attributes.localVariableTypeTable()) {
@Override
@ -107,6 +117,11 @@ class CorpusTest {
b.writeU2(1);
Util.writeLocalVariable(b, lvt);
}
@Override
public Utf8Entry attributeName() {
return cob.constantPool().utf8Entry(Attributes.NAME_LOCAL_VARIABLE_TYPE_TABLE);
}
});
default -> cob.with(coe);
}

View File

@ -41,6 +41,7 @@ import java.lang.classfile.attribute.LocalVariableTableAttribute;
import java.lang.classfile.constantpool.ConstantPoolBuilder;
import java.lang.classfile.constantpool.ConstantPoolException;
import java.lang.classfile.constantpool.IntegerEntry;
import java.lang.classfile.constantpool.Utf8Entry;
import java.util.List;
import jdk.internal.classfile.impl.BufWriterImpl;
@ -49,6 +50,7 @@ import jdk.internal.classfile.impl.DirectMethodBuilder;
import jdk.internal.classfile.impl.LabelContext;
import jdk.internal.classfile.impl.UnboundAttribute;
import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.*;
class LimitsTest {
@ -145,7 +147,13 @@ class LimitsTest {
b.writeInt(-2); //npairs to jump back and cause OOME if not checked
b.writeU2(0);//exception handlers
b.writeU2(0);//attributes
}})))).methods().get(0).code().get().elementList());
}
@Override
public Utf8Entry attributeName() {
return mb.constantPool().utf8Entry(Attributes.NAME_CODE);
}
})))).methods().get(0).code().get().elementList());
}
@Test
@ -167,7 +175,13 @@ class LimitsTest {
b.writeInt(-5); //high to jump back and cause OOME if not checked
b.writeU2(0);//exception handlers
b.writeU2(0);//attributes
}})))).methods().get(0).code().get().elementList());
}
@Override
public Utf8Entry attributeName() {
return mb.constantPool().utf8Entry(Attributes.NAME_CODE);
}
})))).methods().get(0).code().get().elementList());
assertThrows(IllegalArgumentException.class, () ->
ClassFile.of().parse(ClassFile.of().build(ClassDesc.of("TableSwitchClass"), cb -> cb.withMethod(
"tableSwitchMethod", MethodTypeDesc.of(ConstantDescs.CD_void), 0, mb ->
@ -189,7 +203,13 @@ class LimitsTest {
b.writeInt(Integer.MAX_VALUE - 4); //high to jump back and cause infinite loop
b.writeU2(0);//exception handlers
b.writeU2(0);//attributes
}})))).methods().get(0).code().get().elementList());
}
@Override
public Utf8Entry attributeName() {
return mb.constantPool().utf8Entry(Attributes.NAME_CODE);
}
})))).methods().get(0).code().get().elementList());
}
@Test

View File

@ -76,7 +76,7 @@ class LowJCovAttributeTest {
private void testRead0() {
int[] mask = new int[1];
for (Attribute<?> attr : classLow.attributes()) {
switch (attr.attributeName()) {
switch (attr.attributeName().stringValue()) {
case Attributes.NAME_COMPILATION_ID: {
CompilationIDAttribute cid = (CompilationIDAttribute) attr;
Utf8Entry v = cid.compilationId();

View File

@ -77,7 +77,7 @@ class LowModuleTest {
private void testRead0(ClassModel classLow) {
for (Attribute<?> attr : classLow.attributes()) {
switch (attr.attributeName()) {
switch (attr.attributeName().stringValue()) {
case Attributes.NAME_SOURCE_FILE: {
SourceFileAttribute sfa = (SourceFileAttribute) attr;
Utf8Entry sf = sfa.sourceFile();

View File

@ -31,7 +31,9 @@
import java.io.IOException;
import java.lang.classfile.constantpool.PoolEntry;
import java.lang.constant.ClassDesc;
import static java.lang.constant.ConstantDescs.*;
import java.lang.invoke.MethodHandleInfo;
import java.net.URI;
import java.nio.file.FileSystem;
@ -47,12 +49,14 @@ import java.util.stream.Stream;
import java.lang.classfile.*;
import java.lang.classfile.attribute.*;
import java.lang.classfile.components.ClassPrinter;
import java.lang.classfile.constantpool.Utf8Entry;
import java.lang.constant.ModuleDesc;
import jdk.internal.classfile.impl.BufWriterImpl;
import jdk.internal.classfile.impl.DirectClassBuilder;
import jdk.internal.classfile.impl.UnboundAttribute;
import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.*;
class VerifierSelfTest {
@ -109,6 +113,11 @@ class VerifierSelfTest {
public void writeBody(BufWriterImpl b) {
b.writeU2(0);
}
@Override
public Utf8Entry attributeName() {
return cb.constantPool().utf8Entry(Attributes.NAME_LOCAL_VARIABLE_TABLE);
}
}));
assertTrue(cc.verify(bytes).stream().anyMatch(e -> e.getMessage().contains("Invalid LocalVariableTable attribute location")));
}
@ -366,7 +375,7 @@ class VerifierSelfTest {
super(new AttributeMapper<CloneAttribute>(){
@Override
public String name() {
return a.attributeName();
return a.attributeName().stringValue();
}
@Override

View File

@ -234,7 +234,7 @@ public record ClassRecord(
public static AttributesRecord ofStreamingElements(Supplier<Stream<? extends ClassFileElement>> elements, ConstantPool cp, CompatibilityFilter... cf) {
Map<String, Attribute<?>> attrs = elements.get().filter(e -> e instanceof Attribute<?>)
.map(e -> (Attribute<?>) e)
.collect(toMap(Attribute::attributeName, e -> e));
.collect(toMap(a -> a.attributeName().stringValue(), e -> e));
return new AttributesRecord(
mapAttr(attrs, annotationDefault(), a -> ElementValueRecord.ofElementValue(a.defaultValue())),
cp == null ? null : IntStream.range(0, cp.bootstrapMethodCount()).mapToObj(i -> BootstrapMethodRecord.ofBootstrapMethodEntry(cp.bootstrapMethodEntry(i))).collect(toSetOrNull()),

View File

@ -59,8 +59,8 @@ class RebuildingTransformation {
case RuntimeVisibleTypeAnnotationsAttribute a -> fb.with(RuntimeVisibleTypeAnnotationsAttribute.of(transformTypeAnnotations(a.annotations(), null, null)));
case SignatureAttribute a -> fb.with(SignatureAttribute.of(Signature.parseFrom(a.asTypeSignature().signatureString())));
case SyntheticAttribute a -> fb.with(SyntheticAttribute.of());
case CustomAttribute a -> throw new AssertionError("Unexpected custom attribute: " + a.attributeName());
case UnknownAttribute a -> throw new AssertionError("Unexpected unknown attribute: " + a.attributeName());
case CustomAttribute a -> throw new AssertionError("Unexpected custom attribute: " + a.attributeName().stringValue());
case UnknownAttribute a -> throw new AssertionError("Unexpected unknown attribute: " + a.attributeName().stringValue());
}
}
});
@ -91,8 +91,8 @@ class RebuildingTransformation {
case RuntimeVisibleTypeAnnotationsAttribute a -> mb.with(RuntimeVisibleTypeAnnotationsAttribute.of(transformTypeAnnotations(a.annotations(), null, null)));
case SignatureAttribute a -> mb.with(SignatureAttribute.of(MethodSignature.parseFrom(a.asMethodSignature().signatureString())));
case SyntheticAttribute a -> mb.with(SyntheticAttribute.of());
case CustomAttribute a -> throw new AssertionError("Unexpected custom attribute: " + a.attributeName());
case UnknownAttribute a -> throw new AssertionError("Unexpected unknown attribute: " + a.attributeName());
case CustomAttribute a -> throw new AssertionError("Unexpected custom attribute: " + a.attributeName().stringValue());
case UnknownAttribute a -> throw new AssertionError("Unexpected unknown attribute: " + a.attributeName().stringValue());
}
}
});
@ -131,7 +131,7 @@ class RebuildingTransformation {
case RuntimeVisibleAnnotationsAttribute rvaa -> rcac.accept(RuntimeVisibleAnnotationsAttribute.of(transformAnnotations(rvaa.annotations())));
case RuntimeVisibleTypeAnnotationsAttribute rvtaa -> rcac.accept(RuntimeVisibleTypeAnnotationsAttribute.of(transformTypeAnnotations(rvtaa.annotations(), null, null)));
case SignatureAttribute sa -> rcac.accept(SignatureAttribute.of(Signature.parseFrom(sa.asTypeSignature().signatureString())));
default -> throw new AssertionError("Unexpected record component attribute: " + rca.attributeName());
default -> throw new AssertionError("Unexpected record component attribute: " + rca.attributeName().stringValue());
}}).toArray(Attribute[]::new))).toArray(RecordComponentInfo[]::new)));
case RuntimeInvisibleAnnotationsAttribute a -> clb.with(RuntimeInvisibleAnnotationsAttribute.of(transformAnnotations(a.annotations())));
case RuntimeInvisibleTypeAnnotationsAttribute a -> clb.with(RuntimeInvisibleTypeAnnotationsAttribute.of(transformTypeAnnotations(a.annotations(), null, null)));
@ -142,8 +142,8 @@ class RebuildingTransformation {
case SourceFileAttribute a -> clb.with(SourceFileAttribute.of(a.sourceFile().stringValue()));
case SourceIDAttribute a -> clb.with(SourceIDAttribute.of(a.sourceId().stringValue()));
case SyntheticAttribute a -> clb.with(SyntheticAttribute.of());
case CustomAttribute a -> throw new AssertionError("Unexpected custom attribute: " + a.attributeName());
case UnknownAttribute a -> throw new AssertionError("Unexpected unknown attribute: " + a.attributeName());
case CustomAttribute a -> throw new AssertionError("Unexpected custom attribute: " + a.attributeName().stringValue());
case UnknownAttribute a -> throw new AssertionError("Unexpected unknown attribute: " + a.attributeName().stringValue());
}
}
});
@ -595,7 +595,7 @@ class RebuildingTransformation {
transformFrameTypeInfos(fr.locals(), cob, labels),
transformFrameTypeInfos(fr.stack(), cob, labels))).toList()));
case CustomAttribute a ->
throw new AssertionError("Unexpected custom attribute: " + a.attributeName());
throw new AssertionError("Unexpected custom attribute: " + a.attributeName().stringValue());
}
}
}

View File

@ -88,7 +88,7 @@ public class AnnotationDefaultTest extends TestResult {
checkEquals(countNumberOfAttributes(method.attributes()),
1L,
"Number of AnnotationDefault attribute");
checkEquals(attr.attributeName(),
checkEquals(attr.attributeName().stringValue(),
"AnnotationDefault", "attribute_name_index");
ExpectedValues expectedValue = expectedValues.get(methodName);

View File

@ -169,7 +169,7 @@ public class EnclosingMethodTest extends TestResult {
// stop checking, attr is null. test case failed
return;
}
checkEquals(attr.attributeName(),
checkEquals(attr.attributeName().stringValue(),
"EnclosingMethod",
"attribute_name_index of EnclosingMethod attribute in the class : " + className);
checkEquals(((BoundAttribute<?>)attr).payloadLen(), 4,

View File

@ -138,7 +138,7 @@ public class LineNumberTestBase extends TestBase {
private <T extends Attribute<T>> int countAttributes(AttributeMapper<T> attr, AttributedElement attributedElement) {
int i = 0;
for (Attribute<?> attribute : attributedElement.attributes()) {
if (attribute.attributeName().equals(attr.name())) {
if (attribute.attributeName().equalsString(attr.name())) {
i++;
}
}

View File

@ -219,7 +219,7 @@ public class Driver extends TestResult {
SignatureAttribute attribute = sup.get();
if (expectedSignature != null && checkNotNull(attribute, memberName + " must have attribute")) {
checkEquals(attribute.attributeName(),
checkEquals(attribute.attributeName().stringValue(),
"Signature", "Attribute's name : " + memberName);
checkEquals(((BoundAttribute<?>)attribute).payloadLen(), 2, "Attribute's length : " + memberName);
checkEquals(attribute.signature().stringValue(),

View File

@ -108,7 +108,7 @@ public class SourceFileTestBase extends TestBase {
SourceFileAttribute attribute = sourceFileAttributes.get(0);
assertEquals(attribute.attributeName(), Attributes.sourceFile().name(), "Incorrect attribute name");
assertEquals(attribute.attributeName().stringValue(), Attributes.sourceFile().name(), "Incorrect attribute name");
assertEquals(attribute.sourceFile().stringValue(), fileName,
"Incorrect source file name");
assertEquals(((BoundAttribute<?>)attribute).payloadLen(), 2, "Incorrect attribute length");

View File

@ -302,7 +302,7 @@ public class DeprecatedTest extends TestResult {
if (checkNotNull(attr, name + " must have deprecated attribute")) {
checkEquals(0, ((BoundAttribute<?>)attr).payloadLen(),
"attribute_length should equal to 0");
checkEquals("Deprecated", attr.attributeName(),
checkEquals("Deprecated", attr.attributeName().stringValue(),
name + " attribute_name_index");
}
}

View File

@ -206,7 +206,7 @@ public abstract class InnerClassesTestBase extends TestResult {
if (!checkNotNull(innerClasses, "InnerClasses attribute should not be null")) {
return;
}
checkEquals(innerClasses.attributeName(), "InnerClasses",
checkEquals(innerClasses.attributeName().stringValue(), "InnerClasses",
"innerClasses.attribute_name_index");
// Inner Classes attribute consists of length (2 bytes)
// and 8 bytes for each inner class's entry.

View File

@ -76,7 +76,7 @@ public class CheckSubtypesOfSealedTest extends TestBase {
void check(ClassModel classFile) throws Exception {
boolean found = false;
for (Attribute<?> attr: classFile.attributes()) {
if (attr.attributeName().equals("PermittedSubclasses")) {
if (attr.attributeName().equalsString("PermittedSubclasses")) {
PermittedSubclassesAttribute permittedSubclasses = (PermittedSubclassesAttribute)attr;
found = true;
if (permittedSubclasses.permittedSubclasses().isEmpty()) {
@ -99,7 +99,7 @@ public class CheckSubtypesOfSealedTest extends TestBase {
NOT_SEALED {
void check(ClassModel classFile) throws Exception {
for (Attribute<?> attr: classFile.attributes()) {
if (attr.attributeName().equals("PermittedSubclasses")) {
if (attr.attributeName().equalsString("PermittedSubclasses")) {
throw new AssertionError(classFile.thisClass().name() + " should not be sealed");
}
}

View File

@ -70,7 +70,7 @@ public class T6716452 {
if (!c.isAssignableFrom(mm.attributes().get(index).getClass())) {
error(mm + ": unexpected attribute found,"
+ " expected " + c.getName()
+ " found " + mm.attributes().get(index).attributeName());
+ " found " + mm.attributes().get(index).attributeName().stringValue());
}
} else {
error(mm + ": expected attribute " + attr.name() + " not found");