Questions regarding JDK-8350938 (ResourceParsingClassHierarchyResolver)

Chen Liang chen.l.liang at oracle.com
Thu Nov 6 05:01:25 UTC 2025


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 <core-libs-dev-retn at openjdk.org> on behalf of Trevor Bond <trevorkbond at gmail.com>
Sent: Wednesday, November 5, 2025 9:56 PM
To: core-libs-dev at openjdk.org <core-libs-dev at openjdk.org>
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);
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://mail.openjdk.org/pipermail/core-libs-dev/attachments/20251106/770accea/attachment.htm>


More information about the core-libs-dev mailing list