8309838: Classfile API Util.toBinaryName and other cleanup

Reviewed-by: asotona
This commit is contained in:
Chen Liang 2023-06-13 08:57:47 +00:00 committed by Adam Sotona
parent f7de726bd3
commit 1a9edb8df9
4 changed files with 15 additions and 76 deletions

View file

@ -196,7 +196,7 @@ public interface ClassHierarchyResolver {
@Override @Override
public Class<?> apply(ClassDesc cd) { public Class<?> apply(ClassDesc cd) {
try { try {
return Class.forName(Util.toBinaryName(cd.descriptorString()), false, loader); return Class.forName(Util.toBinaryName(cd), false, loader);
} catch (ClassNotFoundException ex) { } catch (ClassNotFoundException ex) {
return null; return null;
} }

View file

@ -120,7 +120,8 @@ public final class ClassHierarchyImpl {
} }
public static final class CachedClassHierarchyResolver implements ClassHierarchyResolver { public static final class CachedClassHierarchyResolver implements ClassHierarchyResolver {
//this instance should leak out, appears only in cache in order to utilize Map.computeIfAbsent // this instance should not leak out, appears only in cache in order to utilize Map.computeIfAbsent
// is already an invalid combination, so it can be compared with equals or as value class safely
private static final ClassHierarchyResolver.ClassHierarchyInfo NOPE = private static final ClassHierarchyResolver.ClassHierarchyInfo NOPE =
new ClassHierarchyInfoImpl(null, true); new ClassHierarchyInfoImpl(null, true);
@ -221,7 +222,7 @@ public final class ClassHierarchyImpl {
@Override @Override
public Class<?> apply(ClassDesc cd) { public Class<?> apply(ClassDesc cd) {
try { try {
return Class.forName(Util.toBinaryName(cd.descriptorString()), false, ClassLoader.getSystemClassLoader()); return Class.forName(Util.toBinaryName(cd), false, ClassLoader.getSystemClassLoader());
} catch (ClassNotFoundException ex) { } catch (ClassNotFoundException ex) {
return null; return null;
} }

View file

@ -54,10 +54,6 @@ public class Util {
private Util() { private Util() {
} }
public static String arrayOf(CharSequence s) {
return "[" + s;
}
public static int parameterSlots(MethodTypeDesc mDesc) { public static int parameterSlots(MethodTypeDesc mDesc) {
int count = 0; int count = 0;
for (int i = 0; i < mDesc.parameterCount(); i++) { for (int i = 0; i < mDesc.parameterCount(); i++) {
@ -85,70 +81,19 @@ public class Util {
} }
/** /**
* Convert a descriptor of classes or interfaces or arrays, or an internal * Converts a descriptor of classes or interfaces into
* name of a class or interface, into a fully qualified binary name, that can * a binary name. Rejects primitive types or arrays.
* be resolved by {@link Class#forName(String) Class::forName}. Primitive type * This is an inverse of {@link ClassDesc#of(String)}.
* descriptors should never be passed into this method.
*
* @param descOrInternalName a descriptor or internal name
* @return the fully qualified binary name
*/ */
public static String toBinaryName(String descOrInternalName) { public static String toBinaryName(ClassDesc cd) {
if (descOrInternalName.startsWith("L")) { return toInternalName(cd).replace('/', '.');
// descriptors of classes or interfaces
if (descOrInternalName.length() <= 2 || !descOrInternalName.endsWith(";")) {
throw new IllegalArgumentException(descOrInternalName);
}
return descOrInternalName.substring(1, descOrInternalName.length() - 1).replace('/', '.');
} else {
// arrays, classes or interfaces' internal names
return descOrInternalName.replace('/', '.');
}
}
public static Iterator<String> parameterTypes(String s) {
//TODO: gracefully non-method types
return new Iterator<>() {
int ch = 1;
@Override
public boolean hasNext() {
return s.charAt(ch) != ')';
}
@Override
public String next() {
char curr = s.charAt(ch);
switch (curr) {
case 'C', 'B', 'S', 'I', 'J', 'F', 'D', 'Z':
ch++;
return String.valueOf(curr);
case '[':
ch++;
return "[" + next();
case 'L': {
int start = ch;
while (s.charAt(++ch) != ';') { }
++ch;
return s.substring(start, ch);
}
default:
throw new AssertionError("cannot parse string: " + s);
}
}
};
}
public static String returnDescriptor(String s) {
return s.substring(s.indexOf(')') + 1);
} }
public static String toInternalName(ClassDesc cd) { public static String toInternalName(ClassDesc cd) {
var desc = cd.descriptorString(); var desc = cd.descriptorString();
return switch (desc.charAt(0)) { if (desc.charAt(0) == 'L')
case 'L' -> desc.substring(1, desc.length() - 1); return desc.substring(1, desc.length() - 1);
default -> throw new IllegalArgumentException(desc); throw new IllegalArgumentException(desc);
};
} }
public static ClassDesc toClassDesc(String classInternalNameOrArrayDesc) { public static ClassDesc toClassDesc(String classInternalNameOrArrayDesc) {

View file

@ -46,20 +46,13 @@ class UtilTest {
Object.class, Object.class,
Util.class, Util.class,
Test.class, Test.class,
int[][].class,
Object[].class,
}) })
void testDescToBinaryName(Class<?> type) throws ReflectiveOperationException { void testDescToBinaryName(Class<?> type) throws ReflectiveOperationException {
if (!type.isArray()) { var cd = type.describeConstable().orElseThrow();
// Test internal name assertEquals(type, Class.forName(Util.toBinaryName(cd)));
var internal = type.getName().replace('.', '/'); assertEquals(type.getName(), Util.toBinaryName(cd));
assertEquals(type, Class.forName(Util.toBinaryName(internal)));
}
// Test descriptor
assertEquals(type, Class.forName(Util.toBinaryName(type.descriptorString())));
} }
@Test @Test
void testParameterSlots() { void testParameterSlots() {
assertSlots("(IIII)V", 4); assertSlots("(IIII)V", 4);