< prev index next >

src/java.base/share/classes/java/lang/Class.java

Print this page
rev 16182 : 8170595: Optimize Class.isAnonymousClass
Reviewed-by: mchung
Contributed-by: claes.redestad@oracle.com, christoph.dreis@freenet.de


1255 
1256                         if (matches) { // finally, check return type
1257                             if (m.getReturnType().equals(returnType) )
1258                                 return m;
1259                         }
1260                     }
1261                 }
1262             }
1263 
1264             throw new InternalError("Enclosing method not found");
1265         }
1266     }
1267 
1268     private native Object[] getEnclosingMethod0();
1269 
1270     private EnclosingMethodInfo getEnclosingMethodInfo() {
1271         Object[] enclosingInfo = getEnclosingMethod0();
1272         if (enclosingInfo == null)
1273             return null;
1274         else {
1275             return new EnclosingMethodInfo(enclosingInfo);
1276         }
1277     }
1278 
1279     private static final class EnclosingMethodInfo {
1280         private Class<?> enclosingClass;
1281         private String name;
1282         private String descriptor;
1283 
1284         private EnclosingMethodInfo(Object[] enclosingInfo) {
1285             if (enclosingInfo.length != 3)
1286                 throw new InternalError("Malformed enclosing method information");
1287             try {
1288                 // The array is expected to have three elements:
1289 
1290                 // the immediately enclosing class
1291                 enclosingClass = (Class<?>) enclosingInfo[0];
1292                 assert(enclosingClass != null);
1293 
1294                 // the immediately enclosing method or constructor's
1295                 // name (can be null).
1296                 name            = (String)   enclosingInfo[1];
1297 
1298                 // the immediately enclosing method or constructor's
1299                 // descriptor (null iff name is).
1300                 descriptor      = (String)   enclosingInfo[2];
1301                 assert((name != null && descriptor != null) || name == descriptor);
1302             } catch (ClassCastException cce) {
1303                 throw new InternalError("Invalid type in enclosing method information", cce);
1304             }
1305         }
1306 














1307         boolean isPartial() {
1308             return enclosingClass == null || name == null || descriptor == null;
1309         }
1310 
1311         boolean isConstructor() { return !isPartial() && "<init>".equals(name); }
1312 
1313         boolean isMethod() { return !isPartial() && !isConstructor() && !"<clinit>".equals(name); }
1314 
1315         Class<?> getEnclosingClass() { return enclosingClass; }
1316 
1317         String getName() { return name; }
1318 
1319         String getDescriptor() { return descriptor; }
1320 
1321     }
1322 
1323     private static Class<?> toClass(Type o) {
1324         if (o instanceof GenericArrayType)
1325             return Array.newInstance(toClass(((GenericArrayType)o).getGenericComponentType()),
1326                                      0)


1464      * @since 1.5
1465      */
1466     @CallerSensitive
1467     public Class<?> getEnclosingClass() throws SecurityException {
1468         // There are five kinds of classes (or interfaces):
1469         // a) Top level classes
1470         // b) Nested classes (static member classes)
1471         // c) Inner classes (non-static member classes)
1472         // d) Local classes (named classes declared within a method)
1473         // e) Anonymous classes
1474 
1475 
1476         // JVM Spec 4.7.7: A class must have an EnclosingMethod
1477         // attribute if and only if it is a local class or an
1478         // anonymous class.
1479         EnclosingMethodInfo enclosingInfo = getEnclosingMethodInfo();
1480         Class<?> enclosingCandidate;
1481 
1482         if (enclosingInfo == null) {
1483             // This is a top level or a nested class or an inner class (a, b, or c)
1484             enclosingCandidate = getDeclaringClass();
1485         } else {
1486             Class<?> enclosingClass = enclosingInfo.getEnclosingClass();
1487             // This is a local class or an anonymous class (d or e)
1488             if (enclosingClass == this || enclosingClass == null)
1489                 throw new InternalError("Malformed enclosing method information");
1490             else
1491                 enclosingCandidate = enclosingClass;
1492         }
1493 
1494         if (enclosingCandidate != null)
1495             enclosingCandidate.checkPackageAccess(
1496                     ClassLoader.getClassLoader(Reflection.getCallerClass()), true);
1497         return enclosingCandidate;
1498     }
1499 
1500     /**
1501      * Returns the simple name of the underlying class as given in the
1502      * source code. Returns an empty string if the underlying class is
1503      * anonymous.
1504      *


1531         if (isArray()) {
1532             try {
1533                 Class<?> cl = this;
1534                 int dimensions = 0;
1535                 while (cl.isArray()) {
1536                     dimensions++;
1537                     cl = cl.getComponentType();
1538                 }
1539                 StringBuilder sb = new StringBuilder();
1540                 sb.append(cl.getName());
1541                 for (int i = 0; i < dimensions; i++) {
1542                     sb.append("[]");
1543                 }
1544                 return sb.toString();
1545             } catch (Throwable e) { /*FALLTHRU*/ }
1546         }
1547         return getName();
1548     }
1549 
1550     /**
1551      * Character.isDigit answers {@code true} to some non-ascii
1552      * digits.  This one does not.
1553      */
1554     private static boolean isAsciiDigit(char c) {
1555         return '0' <= c && c <= '9';
1556     }
1557 
1558     /**
1559      * Returns the canonical name of the underlying class as
1560      * defined by the Java Language Specification.  Returns null if
1561      * the underlying class does not have a canonical name (i.e., if
1562      * it is a local or anonymous class or an array whose component
1563      * type does not have a canonical name).
1564      * @return the canonical name of the underlying class if it exists, and
1565      * {@code null} otherwise.
1566      * @since 1.5
1567      */
1568     public String getCanonicalName() {
1569         if (isArray()) {
1570             String canonicalName = getComponentType().getCanonicalName();
1571             if (canonicalName != null)
1572                 return canonicalName + "[]";
1573             else
1574                 return null;
1575         }
1576         if (isLocalOrAnonymousClass())
1577             return null;
1578         Class<?> enclosingClass = getEnclosingClass();
1579         if (enclosingClass == null) { // top level class
1580             return getName();
1581         } else {
1582             String enclosingName = enclosingClass.getCanonicalName();
1583             if (enclosingName == null)
1584                 return null;
1585             return enclosingName + "." + getSimpleName();
1586         }
1587     }
1588 
1589     /**
1590      * Returns {@code true} if and only if the underlying class
1591      * is an anonymous class.
1592      *
1593      * @return {@code true} if and only if this class is an anonymous class.
1594      * @since 1.5
1595      */
1596     public boolean isAnonymousClass() {
1597         return "".equals(getSimpleName());

1598     }
1599 
1600     /**
1601      * Returns {@code true} if and only if the underlying class
1602      * is a local class.
1603      *
1604      * @return {@code true} if and only if this class is a local class.
1605      * @since 1.5
1606      */
1607     public boolean isLocalClass() {
1608         return isLocalOrAnonymousClass() && !isAnonymousClass();

1609     }
1610 
1611     /**
1612      * Returns {@code true} if and only if the underlying class
1613      * is a member class.
1614      *
1615      * @return {@code true} if and only if this class is a member class.
1616      * @since 1.5
1617      */
1618     public boolean isMemberClass() {
1619         return getSimpleBinaryName() != null && !isLocalOrAnonymousClass();
1620     }
1621 
1622     /**
1623      * Returns the "simple binary name" of the underlying class, i.e.,
1624      * the binary name without the leading enclosing class name.
1625      * Returns {@code null} if the underlying class is a top level
1626      * class.
1627      */
1628     private String getSimpleBinaryName() {
1629         Class<?> enclosingClass = getEnclosingClass();
1630         if (enclosingClass == null) // top level class
1631             return null;
1632         String name = getSimpleBinaryName0();
1633         if (name == null) // anonymous class
1634             return "";
1635         return name;
1636     }
1637 
1638     private native String getSimpleBinaryName0();
1639 
1640     /**








1641      * Returns {@code true} if this is a local class or an anonymous
1642      * class.  Returns {@code false} otherwise.
1643      */
1644     private boolean isLocalOrAnonymousClass() {
1645         // JVM Spec 4.7.7: A class must have an EnclosingMethod
1646         // attribute if and only if it is a local class or an
1647         // anonymous class.
1648         return getEnclosingMethodInfo() != null;






1649     }
1650 
1651     /**
1652      * Returns an array containing {@code Class} objects representing all
1653      * the public classes and interfaces that are members of the class
1654      * represented by this {@code Class} object.  This includes public
1655      * class and interface members inherited from superclasses and public class
1656      * and interface members declared by the class.  This method returns an
1657      * array of length 0 if this {@code Class} object has no public member
1658      * classes or interfaces.  This method also returns an array of length 0 if
1659      * this {@code Class} object represents a primitive type, an array
1660      * class, or void.
1661      *
1662      * @return the array of {@code Class} objects representing the public
1663      *         members of this class
1664      * @throws SecurityException
1665      *         If a security manager, <i>s</i>, is present and
1666      *         the caller's class loader is not the same as or an
1667      *         ancestor of the class loader for the current class and
1668      *         invocation of {@link SecurityManager#checkPackageAccess




1255 
1256                         if (matches) { // finally, check return type
1257                             if (m.getReturnType().equals(returnType) )
1258                                 return m;
1259                         }
1260                     }
1261                 }
1262             }
1263 
1264             throw new InternalError("Enclosing method not found");
1265         }
1266     }
1267 
1268     private native Object[] getEnclosingMethod0();
1269 
1270     private EnclosingMethodInfo getEnclosingMethodInfo() {
1271         Object[] enclosingInfo = getEnclosingMethod0();
1272         if (enclosingInfo == null)
1273             return null;
1274         else {
1275             return EnclosingMethodInfo.createEnclosingInfo(enclosingInfo);
1276         }
1277     }
1278 
1279     private static final class EnclosingMethodInfo {
1280         private final Class<?> enclosingClass;
1281         private final String name;
1282         private final String descriptor;
1283 
1284         static void checkEnclosingInfo(Object[] enclosingInfo) {
1285             if (enclosingInfo.length != 3)
1286                 throw new InternalError("Malformed enclosing method information");
1287             try {
1288                 // The array is expected to have three elements:
1289 
1290                 // the immediately enclosing class
1291                 Class<?> enclosingClass = (Class<?>) enclosingInfo[0];
1292                 assert(enclosingClass != null);
1293 
1294                 // the immediately enclosing method or constructor's
1295                 // name (can be null).
1296                 String name            = (String)   enclosingInfo[1];
1297 
1298                 // the immediately enclosing method or constructor's
1299                 // descriptor (null iff name is).
1300                 String descriptor      = (String)   enclosingInfo[2];
1301                 assert((name != null && descriptor != null) || name == descriptor);
1302             } catch (ClassCastException cce) {
1303                 throw new InternalError("Invalid type in enclosing method information", cce);
1304             }
1305         }
1306 
1307         static EnclosingMethodInfo createEnclosingInfo(Object[] enclosingInfo) {
1308             checkEnclosingInfo(enclosingInfo);
1309             return new EnclosingMethodInfo((Class<?>)enclosingInfo[0],
1310                                            (String)enclosingInfo[1],
1311                                            (String)enclosingInfo[2]);
1312         }
1313 
1314         private EnclosingMethodInfo(Class<?> enclosingClass, String name,
1315                 String descriptor) {
1316             this.enclosingClass = enclosingClass;
1317             this.name = name;
1318             this.descriptor = descriptor;
1319         }
1320 
1321         boolean isPartial() {
1322             return enclosingClass == null || name == null || descriptor == null;
1323         }
1324 
1325         boolean isConstructor() { return !isPartial() && "<init>".equals(name); }
1326 
1327         boolean isMethod() { return !isPartial() && !isConstructor() && !"<clinit>".equals(name); }
1328 
1329         Class<?> getEnclosingClass() { return enclosingClass; }
1330 
1331         String getName() { return name; }
1332 
1333         String getDescriptor() { return descriptor; }
1334 
1335     }
1336 
1337     private static Class<?> toClass(Type o) {
1338         if (o instanceof GenericArrayType)
1339             return Array.newInstance(toClass(((GenericArrayType)o).getGenericComponentType()),
1340                                      0)


1478      * @since 1.5
1479      */
1480     @CallerSensitive
1481     public Class<?> getEnclosingClass() throws SecurityException {
1482         // There are five kinds of classes (or interfaces):
1483         // a) Top level classes
1484         // b) Nested classes (static member classes)
1485         // c) Inner classes (non-static member classes)
1486         // d) Local classes (named classes declared within a method)
1487         // e) Anonymous classes
1488 
1489 
1490         // JVM Spec 4.7.7: A class must have an EnclosingMethod
1491         // attribute if and only if it is a local class or an
1492         // anonymous class.
1493         EnclosingMethodInfo enclosingInfo = getEnclosingMethodInfo();
1494         Class<?> enclosingCandidate;
1495 
1496         if (enclosingInfo == null) {
1497             // This is a top level or a nested class or an inner class (a, b, or c)
1498             enclosingCandidate = getDeclaringClass0();
1499         } else {
1500             Class<?> enclosingClass = enclosingInfo.getEnclosingClass();
1501             // This is a local class or an anonymous class (d or e)
1502             if (enclosingClass == this || enclosingClass == null)
1503                 throw new InternalError("Malformed enclosing method information");
1504             else
1505                 enclosingCandidate = enclosingClass;
1506         }
1507 
1508         if (enclosingCandidate != null)
1509             enclosingCandidate.checkPackageAccess(
1510                     ClassLoader.getClassLoader(Reflection.getCallerClass()), true);
1511         return enclosingCandidate;
1512     }
1513 
1514     /**
1515      * Returns the simple name of the underlying class as given in the
1516      * source code. Returns an empty string if the underlying class is
1517      * anonymous.
1518      *


1545         if (isArray()) {
1546             try {
1547                 Class<?> cl = this;
1548                 int dimensions = 0;
1549                 while (cl.isArray()) {
1550                     dimensions++;
1551                     cl = cl.getComponentType();
1552                 }
1553                 StringBuilder sb = new StringBuilder();
1554                 sb.append(cl.getName());
1555                 for (int i = 0; i < dimensions; i++) {
1556                     sb.append("[]");
1557                 }
1558                 return sb.toString();
1559             } catch (Throwable e) { /*FALLTHRU*/ }
1560         }
1561         return getName();
1562     }
1563 
1564     /**








1565      * Returns the canonical name of the underlying class as
1566      * defined by the Java Language Specification.  Returns null if
1567      * the underlying class does not have a canonical name (i.e., if
1568      * it is a local or anonymous class or an array whose component
1569      * type does not have a canonical name).
1570      * @return the canonical name of the underlying class if it exists, and
1571      * {@code null} otherwise.
1572      * @since 1.5
1573      */
1574     public String getCanonicalName() {
1575         if (isArray()) {
1576             String canonicalName = getComponentType().getCanonicalName();
1577             if (canonicalName != null)
1578                 return canonicalName + "[]";
1579             else
1580                 return null;
1581         }
1582         if (isLocalOrAnonymousClass())
1583             return null;
1584         Class<?> enclosingClass = getEnclosingClass();
1585         if (enclosingClass == null) { // top level class
1586             return getName();
1587         } else {
1588             String enclosingName = enclosingClass.getCanonicalName();
1589             if (enclosingName == null)
1590                 return null;
1591             return enclosingName + "." + getSimpleName();
1592         }
1593     }
1594 
1595     /**
1596      * Returns {@code true} if and only if the underlying class
1597      * is an anonymous class.
1598      *
1599      * @return {@code true} if and only if this class is an anonymous class.
1600      * @since 1.5
1601      */
1602     public boolean isAnonymousClass() {
1603         return !isArray() && isLocalOrAnonymousClass() &&
1604                 getSimpleBinaryName0() == null;
1605     }
1606 
1607     /**
1608      * Returns {@code true} if and only if the underlying class
1609      * is a local class.
1610      *
1611      * @return {@code true} if and only if this class is a local class.
1612      * @since 1.5
1613      */
1614     public boolean isLocalClass() {
1615         return isLocalOrAnonymousClass() &&
1616                 (isArray() || getSimpleBinaryName0() != null);
1617     }
1618 
1619     /**
1620      * Returns {@code true} if and only if the underlying class
1621      * is a member class.
1622      *
1623      * @return {@code true} if and only if this class is a member class.
1624      * @since 1.5
1625      */
1626     public boolean isMemberClass() {
1627         return !isLocalOrAnonymousClass() && getDeclaringClass0() != null;
1628     }
1629 
1630     /**
1631      * Returns the "simple binary name" of the underlying class, i.e.,
1632      * the binary name without the leading enclosing class name.
1633      * Returns {@code null} if the underlying class is a top level
1634      * class.
1635      */
1636     private String getSimpleBinaryName() {
1637         if (isTopLevelClass())

1638             return null;
1639         String name = getSimpleBinaryName0();
1640         if (name == null) // anonymous class
1641             return "";
1642         return name;
1643     }
1644 
1645     private native String getSimpleBinaryName0();
1646 
1647     /**
1648      * Returns {@code true} if this is a top level class.  Returns {@code false}
1649      * otherwise.
1650      */
1651     private boolean isTopLevelClass() {
1652         return !isLocalOrAnonymousClass() && getDeclaringClass0() == null;
1653     }
1654 
1655     /**
1656      * Returns {@code true} if this is a local class or an anonymous
1657      * class.  Returns {@code false} otherwise.
1658      */
1659     private boolean isLocalOrAnonymousClass() {
1660         // JVM Spec 4.7.7: A class must have an EnclosingMethod
1661         // attribute if and only if it is a local class or an
1662         // anonymous class.
1663         Object[] enclosingInfo = getEnclosingMethod0();
1664         if (enclosingInfo == null) {
1665             return false;
1666         } else {
1667             EnclosingMethodInfo.checkEnclosingInfo(enclosingInfo);
1668             return true;
1669         }
1670     }
1671 
1672     /**
1673      * Returns an array containing {@code Class} objects representing all
1674      * the public classes and interfaces that are members of the class
1675      * represented by this {@code Class} object.  This includes public
1676      * class and interface members inherited from superclasses and public class
1677      * and interface members declared by the class.  This method returns an
1678      * array of length 0 if this {@code Class} object has no public member
1679      * classes or interfaces.  This method also returns an array of length 0 if
1680      * this {@code Class} object represents a primitive type, an array
1681      * class, or void.
1682      *
1683      * @return the array of {@code Class} objects representing the public
1684      *         members of this class
1685      * @throws SecurityException
1686      *         If a security manager, <i>s</i>, is present and
1687      *         the caller's class loader is not the same as or an
1688      *         ancestor of the class loader for the current class and
1689      *         invocation of {@link SecurityManager#checkPackageAccess


< prev index next >