Skip to content

Commit 0cbc4b8

Browse files
zakkakjerboaa
authored andcommittedMar 8, 2022
8281266: [JVMCI] MetaUtil.toInternalName() doesn't handle hidden classes correctly
Reviewed-by: sgehwolf, dnsimon
1 parent 0f88fc1 commit 0cbc4b8

File tree

2 files changed

+41
-26
lines changed
  • src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.meta/src/jdk/vm/ci/meta
  • test/hotspot/jtreg/compiler/jvmci/jdk.vm.ci.runtime.test/src/jdk/vm/ci/runtime/test

2 files changed

+41
-26
lines changed
 

‎src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.meta/src/jdk/vm/ci/meta/MetaUtil.java

+33-19
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2012, 2019, Oracle and/or its affiliates. All rights reserved.
2+
* Copyright (c) 2012, 2022, Oracle and/or its affiliates. All rights reserved.
33
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
44
*
55
* This code is free software; you can redistribute it and/or modify it
@@ -27,6 +27,11 @@
2727
*/
2828
public class MetaUtil {
2929

30+
public static final char PACKAGE_SEPARATOR_INTERNAL = '/';
31+
public static final char HIDDEN_SEPARATOR_INTERNAL = '.';
32+
public static final char PACKAGE_SEPARATOR_JAVA = HIDDEN_SEPARATOR_INTERNAL;
33+
public static final char HIDDEN_SEPARATOR_JAVA = PACKAGE_SEPARATOR_INTERNAL;
34+
3035
/**
3136
* Extends the functionality of {@link Class#getSimpleName()} to include a non-empty string for
3237
* anonymous and local classes.
@@ -87,25 +92,27 @@ private static String safeSimpleName(Class<?> clazz) {
8792
}
8893

8994
/**
90-
* Classes for lambdas can have {@code /} characters that are not package separators. These are
91-
* distinguished by being followed by a character that is not a
95+
* Hidden classes have {@code /} characters in their internal names and {@code .} characters in their names returned
96+
* by {@link Class#getName()} that are not package separators.
97+
* These are distinguished by being followed by a character that is not a
9298
* {@link Character#isJavaIdentifierStart(char)} (e.g.,
9399
* "jdk.vm.ci.runtime.test.TypeUniverse$$Lambda$1/869601985").
100+
*
101+
* @param name the name to perform the replacements on
102+
* @param packageSeparator the {@link Character} used as the package separator, e.g. {@code /} in internal form
103+
* @param hiddenSeparator the {@link Character} used as the hidden class separator, e.g. {@code .} in internal form
94104
*/
95-
private static String replacePackageSeparatorsWithDot(String name) {
105+
private static String replacePackageAndHiddenSeparators(String name, Character packageSeparator, Character hiddenSeparator) {
106+
int index = name.indexOf(hiddenSeparator); // check if it's a hidden class
96107
int length = name.length();
97-
int i = 0;
98108
StringBuilder buf = new StringBuilder(length);
99-
while (i < length - 1) {
100-
char ch = name.charAt(i);
101-
if (ch == '/' && Character.isJavaIdentifierStart(name.charAt(i + 1))) {
102-
buf.append('.');
103-
} else {
104-
buf.append(ch);
105-
}
106-
i++;
109+
if (index < 0) {
110+
buf.append(name.replace(packageSeparator, hiddenSeparator));
111+
} else {
112+
buf.append(name.substring(0, index).replace(packageSeparator, hiddenSeparator));
113+
buf.append(packageSeparator);
114+
buf.append(name.substring(index + 1));
107115
}
108-
buf.append(name.charAt(length - 1));
109116
return buf.toString();
110117
}
111118

@@ -122,17 +129,22 @@ private static String replacePackageSeparatorsWithDot(String name) {
122129
public static String internalNameToJava(String name, boolean qualified, boolean classForNameCompatible) {
123130
switch (name.charAt(0)) {
124131
case 'L': {
125-
String result = replacePackageSeparatorsWithDot(name.substring(1, name.length() - 1));
132+
String type = name.substring(1, name.length() - 1);
133+
String result = replacePackageAndHiddenSeparators(type, PACKAGE_SEPARATOR_INTERNAL, HIDDEN_SEPARATOR_INTERNAL);
126134
if (!qualified) {
127-
final int lastDot = result.lastIndexOf('.');
135+
final int lastDot = result.lastIndexOf(HIDDEN_SEPARATOR_INTERNAL);
128136
if (lastDot != -1) {
129137
result = result.substring(lastDot + 1);
130138
}
131139
}
132140
return result;
133141
}
134142
case '[':
135-
return classForNameCompatible ? replacePackageSeparatorsWithDot(name) : internalNameToJava(name.substring(1), qualified, classForNameCompatible) + "[]";
143+
if (classForNameCompatible) {
144+
return replacePackageAndHiddenSeparators(name, PACKAGE_SEPARATOR_INTERNAL, HIDDEN_SEPARATOR_INTERNAL);
145+
} else {
146+
return internalNameToJava(name.substring(1), qualified, false) + "[]";
147+
}
136148
default:
137149
if (name.length() != 1) {
138150
throw new IllegalArgumentException("Illegal internal name: " + name);
@@ -213,7 +225,7 @@ static void appendProfile(StringBuilder buf, AbstractJavaProfile<?, ?> profile,
213225
public static String toInternalName(String className) {
214226
if (className.startsWith("[")) {
215227
/* Already in the correct array style. */
216-
return className.replace('.', '/');
228+
return replacePackageAndHiddenSeparators(className, PACKAGE_SEPARATOR_JAVA, HIDDEN_SEPARATOR_JAVA);
217229
}
218230

219231
StringBuilder result = new StringBuilder();
@@ -252,7 +264,9 @@ public static String toInternalName(String className) {
252264
result.append("V");
253265
break;
254266
default:
255-
result.append("L").append(base.replace('.', '/')).append(";");
267+
result.append("L")
268+
.append(replacePackageAndHiddenSeparators(base, PACKAGE_SEPARATOR_JAVA, HIDDEN_SEPARATOR_JAVA))
269+
.append(";");
256270
break;
257271
}
258272
return result.toString();

‎test/hotspot/jtreg/compiler/jvmci/jdk.vm.ci.runtime.test/src/jdk/vm/ci/runtime/test/TestResolvedJavaType.java

+8-7
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,8 @@
4242
import static java.lang.reflect.Modifier.isProtected;
4343
import static java.lang.reflect.Modifier.isPublic;
4444
import static java.lang.reflect.Modifier.isStatic;
45+
import static jdk.vm.ci.meta.MetaUtil.internalNameToJava;
46+
import static jdk.vm.ci.meta.MetaUtil.toInternalName;
4547
import static org.junit.Assert.assertArrayEquals;
4648
import static org.junit.Assert.assertEquals;
4749
import static org.junit.Assert.assertFalse;
@@ -163,16 +165,15 @@ public void isArrayTest() {
163165
}
164166

165167
@Test
166-
public void internalNameTest() {
167-
// Verify that the last slash in lambda types are not replaced with a '.' as they
168-
// are part of the type name.
168+
public void lambdaInternalNameTest() {
169+
// Verify that the last dot in lambda types is properly handled when transitioning from internal name to java
170+
// name and vice versa.
169171
Supplier<Runnable> lambda = () -> () -> System.out.println("run");
170172
ResolvedJavaType lambdaType = metaAccess.lookupJavaType(lambda.getClass());
171173
String typeName = lambdaType.getName();
172-
int typeNameLen = TestResolvedJavaType.class.getSimpleName().length();
173-
int index = typeName.indexOf(TestResolvedJavaType.class.getSimpleName());
174-
String suffix = typeName.substring(index + typeNameLen, typeName.length() - 1);
175-
assertEquals(TestResolvedJavaType.class.getName() + suffix, lambdaType.toJavaName());
174+
String javaName = lambda.getClass().getName();
175+
assertEquals(typeName, toInternalName(javaName));
176+
assertEquals(javaName, internalNameToJava(typeName, true, true));
176177
}
177178

178179
@Test

0 commit comments

Comments
 (0)
Please sign in to comment.