Hi Trevor, I think ClassFile.of is good for this particular purpose. There is 
nothing in the header parsing that the default class file handling options is 
not suitable for.

-Chen
________________________________
From: core-libs-dev <[email protected]> on behalf of Trevor Bond 
<[email protected]>
Sent: Wednesday, November 5, 2025 9:56 PM
To: [email protected] <[email protected]>
Subject: Questions regarding JDK-8350938 (ResourceParsingClassHierarchyResolver)

Hi all,

I'm new to contributing to OpenJDK and have been working with Dan Smith as a 
mentor. I've been looking at JDK-8350938, which suggests refactoring 
ResourceParsingClassHierarchyResolver to avoid inflating all UTF8 constant pool 
entries by using ClassReaderImpl. ClassReaderImpl stores constant pool offsets 
and later lazily reads/inflates UTF8 entries as needed, so it seems to make 
sense to use here as a performance enhancement.

I have an initial prototype that removes manual parsing in getClassInfo() and 
instead constructs a ClassReaderImpl and uses its helper methods to return the 
needed class information.

One question before I try to move forward with contributing:
- ClassReaderImpl takes a ClassFile context. I used ClassFile.of() (a ClassFile 
context with default options). Is this the correct usage here, or should the 
resolver provide a more specific context?
I am also open to and would appreciate any other ideas or feedback on this 
implementation.

I’ve included the small patch below for reference.

Thanks for your help,
Trevor

diff --git 
a/src/java.base/share/classes/jdk/internal/classfile/impl/ClassHierarchyImpl.java
 
b/src/java.base/share/classes/jdk/internal/classfile/impl/ClassHierarchyImpl.java
index 5be14f42baa..463845ce612 100644
--- 
a/src/java.base/share/classes/jdk/internal/classfile/impl/ClassHierarchyImpl.java
+++ 
b/src/java.base/share/classes/jdk/internal/classfile/impl/ClassHierarchyImpl.java
@@ -30,7 +30,10 @@
 import java.io.IOException;
 import java.io.InputStream;
 import java.io.UncheckedIOException;
+import java.lang.classfile.ClassFile;
 import java.lang.classfile.ClassHierarchyResolver;
+import java.lang.classfile.ClassReader;
+import java.lang.classfile.constantpool.ClassEntry;
 import java.lang.constant.ClassDesc;
 import java.util.Collection;
 import java.util.HashMap;
@@ -164,31 +167,12 @@ public 
ResourceParsingClassHierarchyResolver(Function<ClassDesc, InputStream> cl
         public ClassHierarchyResolver.ClassHierarchyInfo 
getClassInfo(ClassDesc classDesc) {
             var ci = streamProvider.apply(classDesc);
             if (ci == null) return null;
-            try (var in = new DataInputStream(new BufferedInputStream(ci))) {
-                in.skipBytes(8);
-                int cpLength = in.readUnsignedShort();
-                String[] cpStrings = new String[cpLength];
-                int[] cpClasses = new int[cpLength];
-                for (int i = 1; i < cpLength; i++) {
-                    int tag;
-                    switch (tag = in.readUnsignedByte()) {
-                        case TAG_UTF8 -> cpStrings[i] = in.readUTF();
-                        case TAG_CLASS -> cpClasses[i] = 
in.readUnsignedShort();
-                        case TAG_STRING, TAG_METHOD_TYPE, TAG_MODULE, 
TAG_PACKAGE -> in.skipBytes(2);
-                        case TAG_METHOD_HANDLE -> in.skipBytes(3);
-                        case TAG_INTEGER, TAG_FLOAT, TAG_FIELDREF, 
TAG_METHODREF, TAG_INTERFACE_METHODREF,
-                             TAG_NAME_AND_TYPE, TAG_DYNAMIC, 
TAG_INVOKE_DYNAMIC -> in.skipBytes(4);
-                        case TAG_LONG, TAG_DOUBLE -> {
-                            in.skipBytes(8);
-                            i++;
-                        }
-                        default -> throw new IllegalStateException("Bad tag (" 
+ tag + ") at index (" + i + ")");
-                    }
-                }
-                boolean isInterface = (in.readUnsignedShort() & ACC_INTERFACE) 
!= 0;
-                in.skipBytes(2);
-                int superIndex = in.readUnsignedShort();
-                var superClass = superIndex > 0 ? 
ClassDesc.ofInternalName(cpStrings[cpClasses[superIndex]]) : null;
+            try (ci) {
+                ClassReader reader = new ClassReaderImpl(ci.readAllBytes(), 
(ClassFileImpl) ClassFile.of());
+                boolean isInterface = (reader.flags() & ACC_INTERFACE) != 0;
+                ClassDesc superClass = reader.superclassEntry()
+                        .map(ClassEntry::asSymbol)
+                        .orElse(null);
                 return new ClassHierarchyInfoImpl(superClass, isInterface);
             } catch (IOException ioe) {
                 throw new UncheckedIOException(ioe);

Reply via email to