8187123: (reflect) Class#getCanonicalName and Class#getSimpleName is a part of performance issue

Reviewed-by: psandoz, dholmes, mchung
This commit is contained in:
Claes Redestad 2018-05-04 09:29:14 +02:00
parent d9b3c3203e
commit d1cf230fc1

View File

@ -1524,13 +1524,22 @@ public final class Class<T> implements java.io.Serializable,
* @since 1.5 * @since 1.5
*/ */
public String getSimpleName() { public String getSimpleName() {
if (isArray()) ReflectionData<T> rd = reflectionData();
return getComponentType().getSimpleName()+"[]"; String simpleName = rd.simpleName;
if (simpleName == null) {
rd.simpleName = simpleName = getSimpleName0();
}
return simpleName;
}
private String getSimpleName0() {
if (isArray()) {
return getComponentType().getSimpleName() + "[]";
}
String simpleName = getSimpleBinaryName(); String simpleName = getSimpleBinaryName();
if (simpleName == null) { // top level class if (simpleName == null) { // top level class
simpleName = getName(); simpleName = getName();
return simpleName.substring(simpleName.lastIndexOf('.')+1); // strip the package name simpleName = simpleName.substring(simpleName.lastIndexOf('.') + 1); // strip the package name
} }
return simpleName; return simpleName;
} }
@ -1546,10 +1555,10 @@ public final class Class<T> implements java.io.Serializable,
try { try {
Class<?> cl = this; Class<?> cl = this;
int dimensions = 0; int dimensions = 0;
while (cl.isArray()) { do {
dimensions++; dimensions++;
cl = cl.getComponentType(); cl = cl.getComponentType();
} } while (cl.isArray());
StringBuilder sb = new StringBuilder(); StringBuilder sb = new StringBuilder();
sb.append(cl.getName()); sb.append(cl.getName());
for (int i = 0; i < dimensions; i++) { for (int i = 0; i < dimensions; i++) {
@ -1572,22 +1581,31 @@ public final class Class<T> implements java.io.Serializable,
* @since 1.5 * @since 1.5
*/ */
public String getCanonicalName() { public String getCanonicalName() {
ReflectionData<T> rd = reflectionData();
String canonicalName = rd.canonicalName;
if (canonicalName == null) {
rd.canonicalName = canonicalName = getCanonicalName0();
}
return canonicalName == ReflectionData.NULL_SENTINEL? null : canonicalName;
}
private String getCanonicalName0() {
if (isArray()) { if (isArray()) {
String canonicalName = getComponentType().getCanonicalName(); String canonicalName = getComponentType().getCanonicalName();
if (canonicalName != null) if (canonicalName != null)
return canonicalName + "[]"; return canonicalName + "[]";
else else
return null; return ReflectionData.NULL_SENTINEL;
} }
if (isLocalOrAnonymousClass()) if (isLocalOrAnonymousClass())
return null; return ReflectionData.NULL_SENTINEL;
Class<?> enclosingClass = getEnclosingClass(); Class<?> enclosingClass = getEnclosingClass();
if (enclosingClass == null) { // top level class if (enclosingClass == null) { // top level class
return getName(); return getName();
} else { } else {
String enclosingName = enclosingClass.getCanonicalName(); String enclosingName = enclosingClass.getCanonicalName();
if (enclosingName == null) if (enclosingName == null)
return null; return ReflectionData.NULL_SENTINEL;
return enclosingName + "." + getSimpleName(); return enclosingName + "." + getSimpleName();
} }
} }
@ -2895,7 +2913,8 @@ public final class Class<T> implements java.io.Serializable,
* Reflection support. * Reflection support.
*/ */
// reflection data that might get invalidated when JVM TI RedefineClasses() is called // Reflection data caches various derived names and reflective members. Cached
// values may be invalidated when JVM TI RedefineClasses() is called
private static class ReflectionData<T> { private static class ReflectionData<T> {
volatile Field[] declaredFields; volatile Field[] declaredFields;
volatile Field[] publicFields; volatile Field[] publicFields;
@ -2908,6 +2927,11 @@ public final class Class<T> implements java.io.Serializable,
volatile Method[] declaredPublicMethods; volatile Method[] declaredPublicMethods;
volatile Class<?>[] interfaces; volatile Class<?>[] interfaces;
// Cached names
String simpleName;
String canonicalName;
static final String NULL_SENTINEL = new String();
// Value of classRedefinedCount when we created this ReflectionData instance // Value of classRedefinedCount when we created this ReflectionData instance
final int redefinedCount; final int redefinedCount;