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
2727 */
2828public 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 ();
0 commit comments