8315678: Classfile API ConstantPool::entryCount and ConstantPool::entryByIndex methods are confusing

Reviewed-by: briangoetz
This commit is contained in:
Adam Sotona 2023-09-14 18:30:39 +00:00
parent 6d47fc6d5b
commit ca747f09b6
40 changed files with 120 additions and 70 deletions

View File

@ -31,6 +31,7 @@ import jdk.internal.classfile.impl.AbstractPoolEntry;
/** /**
* Models a {@code CONSTANT_Class_info} constant in the constant pool of a * Models a {@code CONSTANT_Class_info} constant in the constant pool of a
* classfile. * classfile.
* @jvms 4.4.1 The CONSTANT_Class_info Structure
*/ */
public sealed interface ClassEntry public sealed interface ClassEntry
extends LoadableConstantEntry extends LoadableConstantEntry

View File

@ -34,6 +34,7 @@ import jdk.internal.classfile.impl.AbstractPoolEntry;
/** /**
* Models a {@code CONSTANT_Dynamic_info} constant in the constant pool of a * Models a {@code CONSTANT_Dynamic_info} constant in the constant pool of a
* classfile. * classfile.
* @jvms 4.4.10 The CONSTANT_Dynamic_info and CONSTANT_InvokeDynamic_info Structures
*/ */
public sealed interface ConstantDynamicEntry public sealed interface ConstantDynamicEntry
extends DynamicConstantPoolEntry, LoadableConstantEntry extends DynamicConstantPoolEntry, LoadableConstantEntry

View File

@ -25,27 +25,56 @@
package jdk.internal.classfile.constantpool; package jdk.internal.classfile.constantpool;
import java.util.Iterator;
import java.util.NoSuchElementException;
import jdk.internal.classfile.BootstrapMethodEntry; import jdk.internal.classfile.BootstrapMethodEntry;
import jdk.internal.classfile.ClassReader; import jdk.internal.classfile.ClassReader;
/** /**
* Provides read access to the constant pool and bootstrap method table of a * Provides read access to the constant pool and bootstrap method table of a
* classfile. * classfile.
* @jvms 4.4 The Constant Pool
*/ */
public sealed interface ConstantPool public sealed interface ConstantPool extends Iterable<PoolEntry>
permits ClassReader, ConstantPoolBuilder { permits ClassReader, ConstantPoolBuilder {
/** /**
* {@return the entry at the specified index} * {@return the entry at the specified index}
* *
* @param index the index within the pool of the desired entry * @param index the index within the pool of the desired entry
* @throws ConstantPoolException if the index is out of range of the
* constant pool, or is considered unusable
*/ */
PoolEntry entryByIndex(int index); PoolEntry entryByIndex(int index);
/** /**
* {@return the number of entries in the constant pool} * {@return the size of the constant pool}
*/ */
int entryCount(); int size();
/**
* @{return an iterator over pool entries}
*/
@Override
default Iterator<PoolEntry> iterator() {
return new Iterator<>() {
int index = 1;
@Override
public boolean hasNext() {
return index < size();
}
@Override
public PoolEntry next() {
if (!hasNext()) throw new NoSuchElementException();
var e = entryByIndex(index);
index += e.width();
return e;
}
};
}
/** /**
* {@return the {@link BootstrapMethodEntry} at the specified index within * {@return the {@link BootstrapMethodEntry} at the specified index within
@ -53,6 +82,8 @@ public sealed interface ConstantPool
* *
* @param index the index within the bootstrap method table of the desired * @param index the index within the bootstrap method table of the desired
* entry * entry
* @throws ConstantPoolException if the index is out of range of the
* bootstrap methods
*/ */
BootstrapMethodEntry bootstrapMethodEntry(int index); BootstrapMethodEntry bootstrapMethodEntry(int index);

View File

@ -30,6 +30,7 @@ import jdk.internal.classfile.impl.AbstractPoolEntry;
/** /**
* Models a {@code CONSTANT_Double_info} constant in the constant pool of a * Models a {@code CONSTANT_Double_info} constant in the constant pool of a
* classfile. * classfile.
* @jvms 4.4.5 The CONSTANT_Long_info and CONSTANT_Double_info Structures
*/ */
public sealed interface DoubleEntry public sealed interface DoubleEntry
extends AnnotationConstantValueEntry, ConstantValueEntry extends AnnotationConstantValueEntry, ConstantValueEntry

View File

@ -29,6 +29,7 @@ import jdk.internal.classfile.impl.AbstractPoolEntry;
/** /**
* Models a {@code CONSTANT_Fieldref_info} constant in the constant pool of a * Models a {@code CONSTANT_Fieldref_info} constant in the constant pool of a
* classfile. * classfile.
* @jvms 4.4.2 The CONSTANT_Fieldref_info, CONSTANT_Methodref_info, and CONSTANT_InterfaceMethodref_info Structures
*/ */
public sealed interface FieldRefEntry extends MemberRefEntry public sealed interface FieldRefEntry extends MemberRefEntry
permits AbstractPoolEntry.FieldRefEntryImpl { permits AbstractPoolEntry.FieldRefEntryImpl {

View File

@ -30,6 +30,7 @@ import jdk.internal.classfile.impl.AbstractPoolEntry;
/** /**
* Models a {@code CONSTANT_Float_info} constant in the constant pool of a * Models a {@code CONSTANT_Float_info} constant in the constant pool of a
* classfile. * classfile.
* @jvms 4.4.4 The CONSTANT_Integer_info and CONSTANT_Float_info Structures
*/ */
public sealed interface FloatEntry public sealed interface FloatEntry
extends AnnotationConstantValueEntry, ConstantValueEntry extends AnnotationConstantValueEntry, ConstantValueEntry

View File

@ -30,6 +30,7 @@ import jdk.internal.classfile.impl.AbstractPoolEntry;
/** /**
* Models a {@code CONSTANT_Integer_info} constant in the constant pool of a * Models a {@code CONSTANT_Integer_info} constant in the constant pool of a
* classfile. * classfile.
* @jvms 4.4.4 The CONSTANT_Integer_info and CONSTANT_Float_info Structures
*/ */
public sealed interface IntegerEntry public sealed interface IntegerEntry
extends AnnotationConstantValueEntry, ConstantValueEntry extends AnnotationConstantValueEntry, ConstantValueEntry

View File

@ -29,6 +29,7 @@ import jdk.internal.classfile.impl.AbstractPoolEntry;
/** /**
* Models a {@code CONSTANT_InterfaceMethodRef_info} constant in the constant pool of a * Models a {@code CONSTANT_InterfaceMethodRef_info} constant in the constant pool of a
* classfile. * classfile.
* @jvms 4.4.2 The CONSTANT_Fieldref_info, CONSTANT_Methodref_info, and CONSTANT_InterfaceMethodref_info Structures
*/ */
public sealed interface InterfaceMethodRefEntry public sealed interface InterfaceMethodRefEntry
extends MemberRefEntry extends MemberRefEntry

View File

@ -32,6 +32,7 @@ import jdk.internal.classfile.impl.Util;
/** /**
* Models a constant pool entry for a dynamic call site. * Models a constant pool entry for a dynamic call site.
* @jvms 4.4.10 The CONSTANT_Dynamic_info and CONSTANT_InvokeDynamic_info Structures
*/ */
public sealed interface InvokeDynamicEntry public sealed interface InvokeDynamicEntry
extends DynamicConstantPoolEntry extends DynamicConstantPoolEntry

View File

@ -30,6 +30,7 @@ import jdk.internal.classfile.impl.AbstractPoolEntry;
/** /**
* Models a {@code CONSTANT_Long_info} constant in the constant pool of a * Models a {@code CONSTANT_Long_info} constant in the constant pool of a
* classfile. * classfile.
* @jvms 4.4.5 The CONSTANT_Long_info and CONSTANT_Double_info Structures
*/ */
public sealed interface LongEntry public sealed interface LongEntry
extends AnnotationConstantValueEntry, ConstantValueEntry extends AnnotationConstantValueEntry, ConstantValueEntry

View File

@ -32,6 +32,7 @@ import jdk.internal.classfile.impl.AbstractPoolEntry;
/** /**
* Models a {@code CONSTANT_MethodHandle_info} constant in the constant pool of a * Models a {@code CONSTANT_MethodHandle_info} constant in the constant pool of a
* classfile. * classfile.
* @jvms 4.4.8 The CONSTANT_MethodHandle_info Structure
*/ */
public sealed interface MethodHandleEntry public sealed interface MethodHandleEntry
extends LoadableConstantEntry extends LoadableConstantEntry

View File

@ -29,6 +29,7 @@ import jdk.internal.classfile.impl.AbstractPoolEntry;
/** /**
* Models a {@code CONSTANT_MethodRef_info} constant in the constant pool of a * Models a {@code CONSTANT_MethodRef_info} constant in the constant pool of a
* classfile. * classfile.
* @jvms 4.4.2 The CONSTANT_Fieldref_info, CONSTANT_Methodref_info, and CONSTANT_InterfaceMethodref_info Structures
*/ */
public sealed interface MethodRefEntry extends MemberRefEntry public sealed interface MethodRefEntry extends MemberRefEntry
permits AbstractPoolEntry.MethodRefEntryImpl { permits AbstractPoolEntry.MethodRefEntryImpl {

View File

@ -32,6 +32,7 @@ import jdk.internal.classfile.impl.AbstractPoolEntry;
/** /**
* Models a {@code CONSTANT_MethodType_info} constant in the constant pool of a * Models a {@code CONSTANT_MethodType_info} constant in the constant pool of a
* classfile. * classfile.
* @jvms 4.4.9 The CONSTANT_MethodType_info Structure
*/ */
public sealed interface MethodTypeEntry public sealed interface MethodTypeEntry
extends LoadableConstantEntry extends LoadableConstantEntry

View File

@ -30,6 +30,7 @@ import java.lang.constant.ModuleDesc;
/** /**
* Models a {@code CONSTANT_Module_info} constant in the constant pool of a * Models a {@code CONSTANT_Module_info} constant in the constant pool of a
* classfile. * classfile.
* @jvms 4.4.11 The CONSTANT_Module_info Structure
*/ */
public sealed interface ModuleEntry extends PoolEntry public sealed interface ModuleEntry extends PoolEntry
permits AbstractPoolEntry.ModuleEntryImpl { permits AbstractPoolEntry.ModuleEntryImpl {

View File

@ -29,6 +29,7 @@ import jdk.internal.classfile.impl.AbstractPoolEntry;
/** /**
* Models a {@code CONSTANT_NameAndType_info} constant in the constant pool of a * Models a {@code CONSTANT_NameAndType_info} constant in the constant pool of a
* classfile. * classfile.
* @jvms 4.4.6 The CONSTANT_NameAndType_info Structure
*/ */
public sealed interface NameAndTypeEntry extends PoolEntry public sealed interface NameAndTypeEntry extends PoolEntry
permits AbstractPoolEntry.NameAndTypeEntryImpl { permits AbstractPoolEntry.NameAndTypeEntryImpl {

View File

@ -30,6 +30,7 @@ import java.lang.constant.PackageDesc;
/** /**
* Models a {@code CONSTANT_Package_info} constant in the constant pool of a * Models a {@code CONSTANT_Package_info} constant in the constant pool of a
* classfile. * classfile.
* @jvms 4.4.12 The CONSTANT_Package_info Structure
*/ */
public sealed interface PackageEntry extends PoolEntry public sealed interface PackageEntry extends PoolEntry
permits AbstractPoolEntry.PackageEntryImpl { permits AbstractPoolEntry.PackageEntryImpl {

View File

@ -29,6 +29,7 @@ import jdk.internal.classfile.impl.AbstractPoolEntry;
/** /**
* Models a {@code CONSTANT_String_info} constant in the constant pool of a * Models a {@code CONSTANT_String_info} constant in the constant pool of a
* classfile. * classfile.
* @jvms 4.4.3 The CONSTANT_String_info Structure
*/ */
public sealed interface StringEntry public sealed interface StringEntry
extends ConstantValueEntry extends ConstantValueEntry

View File

@ -29,6 +29,7 @@ import jdk.internal.classfile.impl.AbstractPoolEntry;
/** /**
* Models a {@code CONSTANT_UTF8_info} constant in the constant pool of a * Models a {@code CONSTANT_UTF8_info} constant in the constant pool of a
* classfile. * classfile.
* @jvms 4.4.7 The CONSTANT_Utf8_info Structure
*/ */
public sealed interface Utf8Entry public sealed interface Utf8Entry
extends CharSequence, AnnotationConstantValueEntry extends CharSequence, AnnotationConstantValueEntry

View File

@ -570,9 +570,8 @@ public final class ClassPrinterImpl {
private static Node[] constantPoolToTree(ConstantPool cp, Verbosity verbosity) { private static Node[] constantPoolToTree(ConstantPool cp, Verbosity verbosity) {
if (verbosity == Verbosity.TRACE_ALL) { if (verbosity == Verbosity.TRACE_ALL) {
var cpNode = new MapNodeImpl(BLOCK, "constant pool"); var cpNode = new MapNodeImpl(BLOCK, "constant pool");
for (int i = 1; i < cp.entryCount();) { for (PoolEntry e : cp) {
var e = cp.entryByIndex(i); cpNode.with(new MapNodeImpl(FLOW, e.index())
cpNode.with(new MapNodeImpl(FLOW, i)
.with(leaf("tag", switch (e.tag()) { .with(leaf("tag", switch (e.tag()) {
case TAG_UTF8 -> "Utf8"; case TAG_UTF8 -> "Utf8";
case TAG_INTEGER -> "Integer"; case TAG_INTEGER -> "Integer";
@ -637,7 +636,6 @@ public final class ClassPrinterImpl {
"value", String.valueOf(ve.constantValue()) "value", String.valueOf(ve.constantValue())
); );
})); }));
i += e.width();
} }
return new Node[]{cpNode}; return new Node[]{cpNode};
} else { } else {

View File

@ -144,7 +144,7 @@ public final class ClassReaderImpl
} }
@Override @Override
public int entryCount() { public int size() {
return constantPoolCount; return constantPoolCount;
} }
@ -189,6 +189,9 @@ public final class ClassReaderImpl
@Override @Override
public BootstrapMethodEntryImpl bootstrapMethodEntry(int index) { public BootstrapMethodEntryImpl bootstrapMethodEntry(int index) {
if (index < 0 || index >= bootstrapMethodCount()) {
throw new ConstantPoolException("Bad BSM index: " + index);
}
return bsmEntries().get(index); return bsmEntries().get(index);
} }
@ -312,6 +315,9 @@ public final class ClassReaderImpl
PoolEntry info = cp[index]; PoolEntry info = cp[index];
if (info == null) { if (info == null) {
int offset = cpOffset[index]; int offset = cpOffset[index];
if (offset == 0) {
throw new ConstantPoolException("Unusable CP index: " + index);
}
int tag = readU1(offset); int tag = readU1(offset);
final int q = offset + 1; final int q = offset + 1;
info = switch (tag) { info = switch (tag) {

View File

@ -28,6 +28,7 @@ import java.lang.constant.ConstantDesc;
import java.lang.constant.MethodTypeDesc; import java.lang.constant.MethodTypeDesc;
import java.util.Arrays; import java.util.Arrays;
import java.util.List; import java.util.List;
import java.util.Objects;
import jdk.internal.classfile.Attribute; import jdk.internal.classfile.Attribute;
import jdk.internal.classfile.Attributes; import jdk.internal.classfile.Attributes;
@ -75,6 +76,7 @@ import static jdk.internal.classfile.Classfile.TAG_MODULE;
import static jdk.internal.classfile.Classfile.TAG_NAMEANDTYPE; import static jdk.internal.classfile.Classfile.TAG_NAMEANDTYPE;
import static jdk.internal.classfile.Classfile.TAG_PACKAGE; import static jdk.internal.classfile.Classfile.TAG_PACKAGE;
import static jdk.internal.classfile.Classfile.TAG_STRING; import static jdk.internal.classfile.Classfile.TAG_STRING;
import jdk.internal.classfile.constantpool.ConstantPoolException;
public final class SplitConstantPool implements ConstantPoolBuilder { public final class SplitConstantPool implements ConstantPoolBuilder {
@ -101,7 +103,7 @@ public final class SplitConstantPool implements ConstantPoolBuilder {
public SplitConstantPool(ClassReader parent) { public SplitConstantPool(ClassReader parent) {
this.parent = (ClassReaderImpl) parent; this.parent = (ClassReaderImpl) parent;
this.parentSize = parent.entryCount(); this.parentSize = parent.size();
this.parentBsmSize = parent.bootstrapMethodCount(); this.parentBsmSize = parent.bootstrapMethodCount();
this.size = parentSize; this.size = parentSize;
this.bsmSize = parentBsmSize; this.bsmSize = parentBsmSize;
@ -110,7 +112,7 @@ public final class SplitConstantPool implements ConstantPoolBuilder {
} }
@Override @Override
public int entryCount() { public int size() {
return size; return size;
} }
@ -121,13 +123,23 @@ public final class SplitConstantPool implements ConstantPoolBuilder {
@Override @Override
public PoolEntry entryByIndex(int index) { public PoolEntry entryByIndex(int index) {
return (index < parentSize) if (index <= 0 || index >= size()) {
throw new ConstantPoolException("Bad CP index: " + index);
}
PoolEntry pe = (index < parentSize)
? parent.entryByIndex(index) ? parent.entryByIndex(index)
: myEntries[index - parentSize]; : myEntries[index - parentSize];
if (pe == null) {
throw new ConstantPoolException("Unusable CP index: " + index);
}
return pe;
} }
@Override @Override
public BootstrapMethodEntryImpl bootstrapMethodEntry(int index) { public BootstrapMethodEntryImpl bootstrapMethodEntry(int index) {
if (index < 0 || index >= bootstrapMethodCount()) {
throw new ConstantPoolException("Bad BSM index: " + index);
}
return (index < parentBsmSize) return (index < parentBsmSize)
? parent.bootstrapMethodEntry(index) ? parent.bootstrapMethodEntry(index)
: myBsmEntries[index - parentBsmSize]; : myBsmEntries[index - parentBsmSize];
@ -170,15 +182,15 @@ public final class SplitConstantPool implements ConstantPoolBuilder {
@Override @Override
public void writeTo(BufWriter buf) { public void writeTo(BufWriter buf) {
int writeFrom = 1; int writeFrom = 1;
if (entryCount() >= 65536) { if (size() >= 65536) {
throw new IllegalArgumentException(String.format("Constant pool is too large %d", entryCount())); throw new IllegalArgumentException(String.format("Constant pool is too large %d", size()));
} }
buf.writeU2(entryCount()); buf.writeU2(size());
if (parent != null && buf.constantPool().canWriteDirect(this)) { if (parent != null && buf.constantPool().canWriteDirect(this)) {
parent.writeConstantPoolEntries(buf); parent.writeConstantPoolEntries(buf);
writeFrom = parent.entryCount(); writeFrom = parent.size();
} }
for (int i = writeFrom; i < entryCount(); ) { for (int i = writeFrom; i < size(); ) {
PoolEntry info = entryByIndex(i); PoolEntry info = entryByIndex(i);
info.writeTo(buf); info.writeTo(buf);
i += info.width(); i += info.width();

View File

@ -166,7 +166,7 @@ public final class TemporaryConstantPool implements ConstantPoolBuilder {
} }
@Override @Override
public int entryCount() { public int size() {
throw new UnsupportedOperationException(); throw new UnsupportedOperationException();
} }

View File

@ -162,7 +162,7 @@ public final class VerificationWrapper {
} }
int entryCount() { int entryCount() {
return cp.entryCount(); return cp.size();
} }
String classNameAt(int index) { String classNameAt(int index) {

View File

@ -175,9 +175,8 @@ public class StringSharingPlugin extends AbstractPlugin implements ResourcePrevi
private void scanConstantPool(Set<Integer> utf8Descriptors) private void scanConstantPool(Set<Integer> utf8Descriptors)
throws Exception { throws Exception {
for (int i = 1; i < cm.constantPool().entryCount(); i += cm.constantPool().entryByIndex(i).width()) { try {
try { for (PoolEntry info : cm.constantPool()) {
PoolEntry info = cm.constantPool().entryByIndex(i);
switch (info) { switch (info) {
case NameAndTypeEntry nameAndType -> case NameAndTypeEntry nameAndType ->
utf8Descriptors.add(nameAndType.type().index()); utf8Descriptors.add(nameAndType.type().index());
@ -185,9 +184,9 @@ public class StringSharingPlugin extends AbstractPlugin implements ResourcePrevi
utf8Descriptors.add(mt.descriptor().index()); utf8Descriptors.add(mt.descriptor().index());
default -> {} default -> {}
} }
} catch (ConstantPoolException ex) {
throw new IOException(ex);
} }
} catch (ConstantPoolException ex) {
throw new IOException(ex);
} }
} }
} }

View File

@ -102,9 +102,9 @@ class ConstantPoolCopyTest {
ConstantPool cp = c.constantPool(); ConstantPool cp = c.constantPool();
ConstantPoolBuilder cp2 = new SplitConstantPool((ClassReader) cp); ConstantPoolBuilder cp2 = new SplitConstantPool((ClassReader) cp);
assertEquals(cp2.entryCount(), cp.entryCount(), "Cloned constant pool must be same size"); assertEquals(cp2.size(), cp.size(), "Cloned constant pool must be same size");
for (int i = 1; i < cp.entryCount();) { for (int i = 1; i < cp.size();) {
PoolEntry cp1i = cp.entryByIndex(i); PoolEntry cp1i = cp.entryByIndex(i);
PoolEntry cp2i = cp2.entryByIndex(i); PoolEntry cp2i = cp2.entryByIndex(i);
assertTrue(representsTheSame(cp1i, cp2i), cp2i + " does not represent the same constant pool entry as " + cp1i); assertTrue(representsTheSame(cp1i, cp2i), cp2i + " does not represent the same constant pool entry as " + cp1i);

View File

@ -248,13 +248,13 @@ class CorpusTest {
var cp1 = cc.parse(orig).constantPool(); var cp1 = cc.parse(orig).constantPool();
var cp2 = cc.parse(transformed).constantPool(); var cp2 = cc.parse(transformed).constantPool();
for (int i = 1; i < cp1.entryCount(); i += cp1.entryByIndex(i).width()) { for (int i = 1; i < cp1.size(); i += cp1.entryByIndex(i).width()) {
assertEquals(cpiToString(cp1.entryByIndex(i)), cpiToString(cp2.entryByIndex(i))); assertEquals(cpiToString(cp1.entryByIndex(i)), cpiToString(cp2.entryByIndex(i)));
} }
if (cp1.entryCount() != cp2.entryCount()) { if (cp1.size() != cp2.size()) {
StringBuilder failMsg = new StringBuilder("Extra entries in constant pool (" + (cp2.entryCount() - cp1.entryCount()) + "): "); StringBuilder failMsg = new StringBuilder("Extra entries in constant pool (" + (cp2.size() - cp1.size()) + "): ");
for (int i = cp1.entryCount(); i < cp2.entryCount(); i += cp2.entryByIndex(i).width()) for (int i = cp1.size(); i < cp2.size(); i += cp2.entryByIndex(i).width())
failMsg.append("\n").append(cp2.entryByIndex(i)); failMsg.append("\n").append(cp2.entryByIndex(i));
fail(failMsg.toString()); fail(failMsg.toString());
} }
@ -272,7 +272,7 @@ class CorpusTest {
var cf = Classfile.of().parse(bytes); var cf = Classfile.of().parse(bytes);
var pool = cf.constantPool(); var pool = cf.constantPool();
Set<String> entryStrings = new HashSet<>(); Set<String> entryStrings = new HashSet<>();
for (int i = 1; i < pool.entryCount(); i += pool.entryByIndex(i).width()) { for (int i = 1; i < pool.size(); i += pool.entryByIndex(i).width()) {
String s = cpiToString(pool.entryByIndex(i)); String s = cpiToString(pool.entryByIndex(i));
if (entryStrings.contains(s)) { if (entryStrings.contains(s)) {
for (int j=1; j<i; j += pool.entryByIndex(j).width()) { for (int j=1; j<i; j += pool.entryByIndex(j).width()) {

View File

@ -185,8 +185,7 @@ class Utf8EntryTest {
} }
static StringEntry obtainStringEntry(ConstantPool cp) { static StringEntry obtainStringEntry(ConstantPool cp) {
for (int i = 1; i < cp.entryCount(); i++) { for (PoolEntry entry : cp) {
PoolEntry entry = cp.entryByIndex(i);
if (entry instanceof StringEntry se) { if (entry instanceof StringEntry se) {
return se; return se;
} }

View File

@ -75,14 +75,10 @@ public class CPoolRefClassContainingInlinedCts {
File file = new File(testClasses, File file = new File(testClasses,
CPoolRefClassContainingInlinedCts.class.getName() + ".class"); CPoolRefClassContainingInlinedCts.class.getName() + ".class");
ClassModel classFile = Classfile.of().parse(file.toPath()); ClassModel classFile = Classfile.of().parse(file.toPath());
int i = 1; for (PoolEntry cpInfo : classFile.constantPool()) {
PoolEntry cpInfo;
while (i < classFile.constantPool().entryCount()) {
cpInfo = classFile.constantPool().entryByIndex(i);
if (cpInfo instanceof ClassEntry classEntry) { if (cpInfo instanceof ClassEntry classEntry) {
checkClassName(classEntry.asInternalName()); checkClassName(classEntry.asInternalName());
} }
i += cpInfo.width();
} }
if (numberOfReferencedClassesToBeChecked != 16) { if (numberOfReferencedClassesToBeChecked != 16) {
throw new AssertionError("Class reference missing in the constant pool"); throw new AssertionError("Class reference missing in the constant pool");

View File

@ -47,6 +47,7 @@ import javax.tools.JavaCompiler;
import javax.tools.JavaFileObject; import javax.tools.JavaFileObject;
import javax.tools.SimpleJavaFileObject; import javax.tools.SimpleJavaFileObject;
import javax.tools.ToolProvider; import javax.tools.ToolProvider;
import jdk.internal.classfile.constantpool.PoolEntry;
/* /*
* This bug was reproduced having two classes B and C referenced from a class A * This bug was reproduced having two classes B and C referenced from a class A
@ -96,17 +97,12 @@ public class DuplicateConstantPoolEntry {
File file = new File("A.class"); File file = new File("A.class");
ClassModel classFile = Classfile.of().parse(file.toPath()); ClassModel classFile = Classfile.of().parse(file.toPath());
ConstantPool constantPool = classFile.constantPool(); ConstantPool constantPool = classFile.constantPool();
for (int i = 1; for (PoolEntry pe1 : constantPool) {
i < constantPool.entryCount() - 1; for (PoolEntry pe2 : constantPool) {
i += constantPool.entryByIndex(i).width()) { if (pe2.index() > pe1.index() && pe1.equals(pe2)) {
for (int j = i + constantPool.entryByIndex(i).width();
j < constantPool.entryCount();
j += constantPool.entryByIndex(j).width()) {
if (constantPool.entryByIndex(i).toString().
equals(constantPool.entryByIndex(j).toString())) {
throw new AssertionError( throw new AssertionError(
"Duplicate entries in the constant pool at positions " + "Duplicate entries in the constant pool at positions " +
i + " and " + j); pe1.index() + " and " + pe2.index());
} }
} }
} }

View File

@ -109,9 +109,8 @@ public class NoStringToLower {
void scan(JavaFileObject fo) throws IOException { void scan(JavaFileObject fo) throws IOException {
try (InputStream in = fo.openInputStream()) { try (InputStream in = fo.openInputStream()) {
ClassModel cf = Classfile.of().parse(in.readAllBytes()); ClassModel cf = Classfile.of().parse(in.readAllBytes());
ConstantPool cp = cf.constantPool(); for (PoolEntry pe : cf.constantPool()) {
for (int i = 1; i < cp.entryCount(); i += cp.entryByIndex(i).width()) { if (pe instanceof MethodRefEntry ref) {
if (cp.entryByIndex(i) instanceof MethodRefEntry ref) {
String methodDesc = ref.owner().name().stringValue() + "." + ref.name().stringValue() + ":" + ref.type().stringValue(); String methodDesc = ref.owner().name().stringValue() + "." + ref.name().stringValue() + ":" + ref.type().stringValue();
if ("java/lang/String.toLowerCase:()Ljava/lang/String;".equals(methodDesc)) { if ("java/lang/String.toLowerCase:()Ljava/lang/String;".equals(methodDesc)) {

View File

@ -58,8 +58,7 @@ public class EmptyUTF8ForInnerClassNameTest {
void checkClassFile(final Path path) throws Exception { void checkClassFile(final Path path) throws Exception {
ClassModel classFile = Classfile.of().parse( ClassModel classFile = Classfile.of().parse(
new BufferedInputStream(Files.newInputStream(path)).readAllBytes()); new BufferedInputStream(Files.newInputStream(path)).readAllBytes());
for (int i = 1; i < classFile.constantPool().entryCount(); ++i) { for (PoolEntry pe : classFile.constantPool()) {
PoolEntry pe = classFile.constantPool().entryByIndex(i);
if (pe instanceof Utf8Entry utf8Info) { if (pe instanceof Utf8Entry utf8Info) {
Assert.check(utf8Info.stringValue().length() > 0, Assert.check(utf8Info.stringValue().length() > 0,
"UTF8 with length 0 found at class " + classFile.thisClass().name()); "UTF8 with length 0 found at class " + classFile.thisClass().name());

View File

@ -80,10 +80,9 @@ public class T8255757 extends TestRunner {
.run(); .run();
ClassModel cf = Classfile.of().parse(curPath.resolve("Test.class")); ClassModel cf = Classfile.of().parse(curPath.resolve("Test.class"));
ConstantPool cp = cf.constantPool();
int num = 0; int num = 0;
for (int i = 1; i < cp.entryCount(); i += cp.entryByIndex(i).width()) { for (PoolEntry pe : cf.constantPool()) {
if (cp.entryByIndex(i) instanceof MethodRefEntry methodRefEntry) { if (pe instanceof MethodRefEntry methodRefEntry) {
String class_name = methodRefEntry.owner().asInternalName(); String class_name = methodRefEntry.owner().asInternalName();
String method_name = methodRefEntry.name().stringValue(); String method_name = methodRefEntry.name().stringValue();
String method_type = methodRefEntry.type().stringValue(); String method_type = methodRefEntry.type().stringValue();

View File

@ -63,8 +63,8 @@ public class InnerClassesHierarchyTest extends TestResult {
for (File file : Arrays.asList(classDir.listFiles(filter))) { for (File file : Arrays.asList(classDir.listFiles(filter))) {
ClassModel classFile = readClassFile(file); ClassModel classFile = readClassFile(file);
String className = classFile.thisClass().name().stringValue(); String className = classFile.thisClass().name().stringValue();
for (int i = 1; i < classFile.constantPool().entryCount(); ++i) { for (PoolEntry pe : classFile.constantPool()) {
if (classFile.constantPool().entryByIndex(i) instanceof ClassEntry classInfo if (pe instanceof ClassEntry classInfo
&& classInfo.asSymbol().isClassOrInterface()) { && classInfo.asSymbol().isClassOrInterface()) {
String cpClassName = classInfo.asInternalName(); String cpClassName = classInfo.asInternalName();
if (isInnerClass(cpClassName)) { if (isInnerClass(cpClassName)) {

View File

@ -497,8 +497,8 @@ public class CheckResourceKeys {
void scan(JavaFileObject fo, Set<String> results) throws IOException { void scan(JavaFileObject fo, Set<String> results) throws IOException {
try (InputStream in = fo.openInputStream()) { try (InputStream in = fo.openInputStream()) {
ClassModel cm = Classfile.of().parse(in.readAllBytes()); ClassModel cm = Classfile.of().parse(in.readAllBytes());
for (int i = 1; i < cm.constantPool().entryCount(); ++i) { for (PoolEntry pe : cm.constantPool()) {
if (cm.constantPool().entryByIndex(i) instanceof Utf8Entry entry) { if (pe instanceof Utf8Entry entry) {
String v = entry.stringValue(); String v = entry.stringValue();
if (v.matches("[A-Za-z0-9-_.]+")) if (v.matches("[A-Za-z0-9-_.]+"))
results.add(v); results.add(v);

View File

@ -47,8 +47,8 @@ public class ClassRefDupInConstantPoolTest {
int duplicates = 0; int duplicates = 0;
TreeSet<String> set = new TreeSet<>(); TreeSet<String> set = new TreeSet<>();
for (int i = 1; i < pool.entryCount(); i += pool.entryByIndex(i).width()) { for (PoolEntry pe : pool) {
if (pool.entryByIndex(i) instanceof ClassEntry ce) { if (pe instanceof ClassEntry ce) {
if (!set.add(ce.asInternalName())) { if (!set.add(ce.asInternalName())) {
duplicates++; duplicates++;
System.out.println("DUPLICATE CLASS REF " + ce.asInternalName()); System.out.println("DUPLICATE CLASS REF " + ce.asInternalName());

View File

@ -83,7 +83,7 @@ public class ByteCodeTest {
e.printStackTrace(); e.printStackTrace();
} }
assert c != null; assert c != null;
ConstantPoolVisitor cpv = new ConstantPoolVisitor(c, c.constantPool().entryCount()); ConstantPoolVisitor cpv = new ConstantPoolVisitor(c, c.constantPool().size());
Map<Integer, String> hm = cpv.getBSMMap(); Map<Integer, String> hm = cpv.getBSMMap();
List<String> expectedValList = tc.getExpectedArgValues(); List<String> expectedValList = tc.getExpectedArgValues();

View File

@ -44,6 +44,7 @@ import jdk.internal.classfile.*;
import jdk.internal.classfile.constantpool.ClassEntry; import jdk.internal.classfile.constantpool.ClassEntry;
import jdk.internal.classfile.constantpool.ConstantPool; import jdk.internal.classfile.constantpool.ConstantPool;
import java.util.Arrays; import java.util.Arrays;
import jdk.internal.classfile.constantpool.PoolEntry;
import toolbox.JavacTask; import toolbox.JavacTask;
import toolbox.TestRunner; import toolbox.TestRunner;
@ -118,9 +119,8 @@ public class MatchExceptionTest extends TestRunner {
cf = Classfile.of().parse(curPath.resolve("Test.class")); cf = Classfile.of().parse(curPath.resolve("Test.class"));
boolean incompatibleClassChangeErrror = false; boolean incompatibleClassChangeErrror = false;
boolean matchException = false; boolean matchException = false;
ConstantPool cp = cf.constantPool(); for (PoolEntry pe : cf.constantPool()) {
for (int i = 1; i < cp.entryCount(); i += cp.entryByIndex(i).width()) { if (pe instanceof ClassEntry clazz) {
if (cp.entryByIndex(i) instanceof ClassEntry clazz) {
incompatibleClassChangeErrror |= clazz.name().equalsString( incompatibleClassChangeErrror |= clazz.name().equalsString(
"java/lang/IncompatibleClassChangeError"); "java/lang/IncompatibleClassChangeError");
matchException |= clazz.name().equalsString("java/lang/MatchException"); matchException |= clazz.name().equalsString("java/lang/MatchException");

View File

@ -1276,8 +1276,8 @@ public class RecordCompilationTests extends CompilationTestCase {
for (final File fileEntry : Objects.requireNonNull(dir.listFiles())) { for (final File fileEntry : Objects.requireNonNull(dir.listFiles())) {
if (fileEntry.getName().endsWith("R.class")) { if (fileEntry.getName().endsWith("R.class")) {
ClassModel classFile = Classfile.of().parse(fileEntry.toPath()); ClassModel classFile = Classfile.of().parse(fileEntry.toPath());
for (int i = 1; i < classFile.constantPool().entryCount(); ++i) { for (PoolEntry pe : classFile.constantPool()) {
if (classFile.constantPool().entryByIndex(i) instanceof FieldRefEntry fieldRefEntry) { if (pe instanceof FieldRefEntry fieldRefEntry) {
numberOfFieldRefs++; numberOfFieldRefs++;
NameAndTypeEntry nameAndType = (NameAndTypeEntry) classFile.constantPool() NameAndTypeEntry nameAndType = (NameAndTypeEntry) classFile.constantPool()
.entryByIndex(fieldRefEntry.nameAndType().index()); .entryByIndex(fieldRefEntry.nameAndType().index());

View File

@ -49,8 +49,7 @@ public class NoObjectToString {
try (InputStream in = NoObjectToString.class.getResourceAsStream("NoObjectToString$Test.class")) { try (InputStream in = NoObjectToString.class.getResourceAsStream("NoObjectToString$Test.class")) {
assert in != null; assert in != null;
ClassModel cm = Classfile.of().parse(in.readAllBytes()); ClassModel cm = Classfile.of().parse(in.readAllBytes());
for (int i = 1; i < cm.constantPool().entryCount(); ++i) { for (PoolEntry pe : cm.constantPool()) {
PoolEntry pe = cm.constantPool().entryByIndex(i);
if (pe instanceof MethodRefEntry ref) { if (pe instanceof MethodRefEntry ref) {
String methodDesc = ref.owner().name() + "." + ref.nameAndType().name() + ":" + ref.nameAndType().type(); String methodDesc = ref.owner().name() + "." + ref.nameAndType().name() + ":" + ref.nameAndType().type();

View File

@ -49,8 +49,8 @@ public class T6887895 {
ClassModel cm = getClassFile("T6887895$Test.class"); ClassModel cm = getClassFile("T6887895$Test.class");
ConstantPool cp = cm.constantPool(); ConstantPool cp = cm.constantPool();
for (int i = 1; i < cp.entryCount(); ++i) { for (PoolEntry pe : cp) {
if (cp.entryByIndex(i) instanceof ClassEntry ce) { if (pe instanceof ClassEntry ce) {
String name = ce.asInternalName(); String name = ce.asInternalName();
System.out.println("found: " + name); System.out.println("found: " + name);
if (ce.asSymbol().isClassOrInterface()) if (ce.asSymbol().isClassOrInterface())