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