mirror of
https://github.com/openjdk/jdk.git
synced 2025-08-28 07:14:30 +02:00
8309838: Classfile API Util.toBinaryName and other cleanup
Reviewed-by: asotona
This commit is contained in:
parent
f7de726bd3
commit
1a9edb8df9
4 changed files with 15 additions and 76 deletions
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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) {
|
||||||
|
|
|
@ -46,19 +46,12 @@ 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() {
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue