# HG changeset patch # User redestad # Date 1480687857 -3600 # Fri Dec 02 15:10:57 2016 +0100 # Node ID 1773062cedaa819bdd4576d236558da0ae9af66b # Parent fdc2a054d9473b72dfb0f527102e04bc8297fc68 8170595: Optimize Class.isAnonymousClass Reviewed-by: mchung Contributed-by: claes.redestad@oracle.com, christoph.dreis@freenet.de diff --git a/src/java.base/share/classes/java/lang/Class.java b/src/java.base/share/classes/java/lang/Class.java --- a/src/java.base/share/classes/java/lang/Class.java +++ b/src/java.base/share/classes/java/lang/Class.java @@ -1272,38 +1272,52 @@ if (enclosingInfo == null) return null; else { - return new EnclosingMethodInfo(enclosingInfo); + return EnclosingMethodInfo.createEnclosingInfo(enclosingInfo); } } private static final class EnclosingMethodInfo { - private Class enclosingClass; - private String name; - private String descriptor; - - private EnclosingMethodInfo(Object[] enclosingInfo) { + private final Class enclosingClass; + private final String name; + private final String descriptor; + + static void checkEnclosingInfo(Object[] enclosingInfo) { if (enclosingInfo.length != 3) throw new InternalError("Malformed enclosing method information"); try { // The array is expected to have three elements: // the immediately enclosing class - enclosingClass = (Class) enclosingInfo[0]; + Class enclosingClass = (Class) enclosingInfo[0]; assert(enclosingClass != null); // the immediately enclosing method or constructor's // name (can be null). - name = (String) enclosingInfo[1]; + String name = (String) enclosingInfo[1]; // the immediately enclosing method or constructor's // descriptor (null iff name is). - descriptor = (String) enclosingInfo[2]; + String descriptor = (String) enclosingInfo[2]; assert((name != null && descriptor != null) || name == descriptor); } catch (ClassCastException cce) { throw new InternalError("Invalid type in enclosing method information", cce); } } + static EnclosingMethodInfo createEnclosingInfo(Object[] enclosingInfo) { + checkEnclosingInfo(enclosingInfo); + return new EnclosingMethodInfo((Class)enclosingInfo[0], + (String)enclosingInfo[1], + (String)enclosingInfo[2]); + } + + private EnclosingMethodInfo(Class enclosingClass, String name, + String descriptor) { + this.enclosingClass = enclosingClass; + this.name = name; + this.descriptor = descriptor; + } + boolean isPartial() { return enclosingClass == null || name == null || descriptor == null; } @@ -1481,7 +1495,7 @@ if (enclosingInfo == null) { // This is a top level or a nested class or an inner class (a, b, or c) - enclosingCandidate = getDeclaringClass(); + enclosingCandidate = getDeclaringClass0(); } else { Class enclosingClass = enclosingInfo.getEnclosingClass(); // This is a local class or an anonymous class (d or e) @@ -1548,14 +1562,6 @@ } /** - * Character.isDigit answers {@code true} to some non-ascii - * digits. This one does not. - */ - private static boolean isAsciiDigit(char c) { - return '0' <= c && c <= '9'; - } - - /** * Returns the canonical name of the underlying class as * defined by the Java Language Specification. Returns null if * the underlying class does not have a canonical name (i.e., if @@ -1594,7 +1600,8 @@ * @since 1.5 */ public boolean isAnonymousClass() { - return "".equals(getSimpleName()); + return !isArray() && isLocalOrAnonymousClass() && + getSimpleBinaryName0() == null; } /** @@ -1605,7 +1612,8 @@ * @since 1.5 */ public boolean isLocalClass() { - return isLocalOrAnonymousClass() && !isAnonymousClass(); + return isLocalOrAnonymousClass() && + (isArray() || getSimpleBinaryName0() != null); } /** @@ -1616,7 +1624,7 @@ * @since 1.5 */ public boolean isMemberClass() { - return getSimpleBinaryName() != null && !isLocalOrAnonymousClass(); + return !isLocalOrAnonymousClass() && getDeclaringClass0() != null; } /** @@ -1626,8 +1634,7 @@ * class. */ private String getSimpleBinaryName() { - Class enclosingClass = getEnclosingClass(); - if (enclosingClass == null) // top level class + if (isTopLevelClass()) return null; String name = getSimpleBinaryName0(); if (name == null) // anonymous class @@ -1638,6 +1645,14 @@ private native String getSimpleBinaryName0(); /** + * Returns {@code true} if this is a top level class. Returns {@code false} + * otherwise. + */ + private boolean isTopLevelClass() { + return !isLocalOrAnonymousClass() && getDeclaringClass0() == null; + } + + /** * Returns {@code true} if this is a local class or an anonymous * class. Returns {@code false} otherwise. */ @@ -1645,7 +1660,13 @@ // JVM Spec 4.7.7: A class must have an EnclosingMethod // attribute if and only if it is a local class or an // anonymous class. - return getEnclosingMethodInfo() != null; + Object[] enclosingInfo = getEnclosingMethod0(); + if (enclosingInfo == null) { + return false; + } else { + EnclosingMethodInfo.checkEnclosingInfo(enclosingInfo); + return true; + } } /**