--- old/src/java.base/share/classes/java/lang/Class.java 2020-03-26 15:59:58.000000000 -0700 +++ new/src/java.base/share/classes/java/lang/Class.java 2020-03-26 15:59:57.000000000 -0700 @@ -28,6 +28,7 @@ import java.lang.annotation.Annotation; import java.lang.constant.ClassDesc; import java.lang.invoke.TypeDescriptor; +import java.lang.invoke.MethodHandles; import java.lang.module.ModuleReader; import java.lang.ref.SoftReference; import java.io.IOException; @@ -63,8 +64,6 @@ import java.util.Map; import java.util.Objects; import java.util.Optional; -import java.util.StringJoiner; -import java.util.stream.Stream; import java.util.stream.Collectors; import jdk.internal.HotSpotIntrinsicCandidate; @@ -128,6 +127,11 @@ * other members are the classes and interfaces whose declarations are * enclosed within the top-level class declaration. * + *

Some methods of class {@code Class} expose some characteristics of + * hidden classes. Hidden classes are created by calling + * {@link java.lang.invoke.MethodHandles.Lookup#defineHiddenClass(byte[], boolean, MethodHandles.Lookup.ClassOption...) + * Lookup::defineHiddenClass}. + * *

The following example uses a {@code Class} object to print the * class name of an object: * @@ -806,6 +810,10 @@ * returns "[[[[[[[I" * * + *

If this class object represents a {@linkplain #isHiddenClass() hidden class}, + * then the name of a hidden class is not a binary name and contains + * a ASCII {@code '/'} character. + * * @return the name of the class or interface * represented by this object. */ @@ -885,6 +893,14 @@ // will throw NoSuchFieldException private final ClassLoader classLoader; + // Set by VM + private transient Object classData; + + // package-private + Object getClassData() { + return classData; + } + /** * Returns an array of {@code TypeVariable} objects that represent the * type variables declared by the generic declaration represented by this @@ -1636,7 +1652,7 @@ else return ReflectionData.NULL_SENTINEL; } - if (isLocalOrAnonymousClass()) + if (isHiddenClass() || isLocalOrAnonymousClass()) return ReflectionData.NULL_SENTINEL; Class enclosingClass = getEnclosingClass(); if (enclosingClass == null) { // top level class @@ -1651,7 +1667,8 @@ /** * Returns {@code true} if and only if the underlying class - * is an anonymous class. + * is an anonymous class. An anonymous class is not a + * {@linkplain #isHiddenClass() hidden class}. * * @return {@code true} if and only if this class is an anonymous class. * @since 1.5 @@ -2876,6 +2893,11 @@ if (sm != null) { sm.checkPermission(SecurityConstants.GET_PD_PERMISSION); } + return protectionDomain(); + } + + // package-private + java.security.ProtectionDomain protectionDomain() { java.security.ProtectionDomain pd = getProtectionDomain0(); if (pd == null) { if (allPermDomain == null) { @@ -2890,7 +2912,6 @@ return pd; } - /** * Returns the ProtectionDomain of this class. */ @@ -4008,39 +4029,32 @@ /** * Returns the nest host of the nest to which the class * or interface represented by this {@code Class} object belongs. - * Every class and interface is a member of exactly one nest. - * A class or interface that is not recorded as belonging to a nest - * belongs to the nest consisting only of itself, and is the nest - * host. - * - *

Each of the {@code Class} objects representing array types, - * primitive types, and {@code void} returns {@code this} to indicate - * that the represented entity belongs to the nest consisting only of - * itself, and is the nest host. + * Every class and interface belongs to exactly one nest. * - *

If there is a {@linkplain LinkageError linkage error} accessing - * the nest host, or if this class or interface is not enumerated as - * a member of the nest by the nest host, then it is considered to belong - * to its own nest and {@code this} is returned as the host. - * - * @apiNote A {@code class} file of version 55.0 or greater may record the - * host of the nest to which it belongs by using the {@code NestHost} - * attribute (JVMS 4.7.28). Alternatively, a {@code class} file of - * version 55.0 or greater may act as a nest host by enumerating the nest's - * other members with the - * {@code NestMembers} attribute (JVMS 4.7.29). - * A {@code class} file of version 54.0 or lower does not use these - * attributes. + * If the nest host of this class or interface has previously + * been determined, then this method returns the nest host. + * If the nest host of this class or interface has + * not previously been determined, then this method determines the nest + * host using the algorithm of JVMS 5.4.4, and returns it. + * + * Often, a class or interface belongs to a nest consisting only of itself, + * in which case this method returns {@code this} to indicate that the class + * or interface is the nest host. + * + *

If this {@code Class} object represents a primitive type, an array type, + * or {@code void}, then this method returns {@code this}, + * indicating that the represented entity belongs to the nest consisting only of + * itself, and is the nest host. * * @return the nest host of this class or interface * * @throws SecurityException - * If the returned class is not the current class, and - * if a security manager, s, is present and the caller's - * class loader is not the same as or an ancestor of the class - * loader for the returned class and invocation of {@link - * SecurityManager#checkPackageAccess s.checkPackageAccess()} - * denies access to the package of the returned class + * If the returned class is not the current class, and + * if a security manager, s, is present and the caller's + * class loader is not the same as or an ancestor of the class + * loader for the returned class and invocation of {@link + * SecurityManager#checkPackageAccess s.checkPackageAccess()} + * denies access to the package of the returned class * @since 11 * @jvms 4.7.28 The {@code NestHost} Attribute * @jvms 4.7.29 The {@code NestMembers} Attribute @@ -4051,17 +4065,9 @@ if (isPrimitive() || isArray()) { return this; } - Class host; - try { - host = getNestHost0(); - } catch (LinkageError e) { - // if we couldn't load our nest-host then we - // act as-if we have no nest-host attribute - return this; - } - // if null then nest membership validation failed, so we - // act as-if we have no nest-host attribute - if (host == null || host == this) { + + Class host = getNestHost0(); + if (host == this) { return this; } // returning a different class requires a security check @@ -4093,11 +4099,8 @@ c.isPrimitive() || c.isArray()) { return false; } - try { - return getNestHost0() == c.getNestHost0(); - } catch (LinkageError e) { - return false; - } + + return getNestHost() == c.getNestHost(); } private native Class[] getNestMembers0(); @@ -4106,39 +4109,45 @@ * Returns an array containing {@code Class} objects representing all the * classes and interfaces that are members of the nest to which the class * or interface represented by this {@code Class} object belongs. - * The {@linkplain #getNestHost() nest host} of that nest is the zeroth - * element of the array. Subsequent elements represent any classes or - * interfaces that are recorded by the nest host as being members of - * the nest; the order of such elements is unspecified. Duplicates are - * permitted. - * If the nest host of that nest does not enumerate any members, then the - * array has a single element containing {@code this}. * - *

Each of the {@code Class} objects representing array types, - * primitive types, and {@code void} returns an array containing only + * First, this method obtains the {@linkplain #getNestHost() nest host}, {@code H}, of the nest + * to which the class or interface represented by this {@code Class} object belongs. + * The zeroth element of the returned array is {@code H}. + * + * Then, for each class or interface {@code C} which is recorded by {@code H} as being a member + * of its nest, this method attempts to obtain the {@code Class} object for {@code C} + * (using {@linkplain #getClassLoader() the defining class loader} of the current {@code Class} object), + * and then obtains the {@linkplain #getNestHost() nest host} of the nest to which {@code C} belongs. + * The classes and interfaces which are recorded by {@code H} as being members of its nest, + * and for which {@code H} can be determined as their nest host, are indicated by subsequent elements + * of the returned array. The order of such elements is unspecified. + * Duplicates are permitted. + * + *

If this {@code Class} object represents a primitive type, an array type, + * or {@code void}, then this method returns a single-element array containing * {@code this}. * - *

This method validates that, for each class or interface which is - * recorded as a member of the nest by the nest host, that class or - * interface records itself as a member of that same nest. Any exceptions - * that occur during this validation are rethrown by this method. + * @apiNote + * The returned array includes only the nest members recorded in the {@code NestMembers} + * attribute, and not any hidden classes that were added to the nest via + * {@link MethodHandles.Lookup#defineHiddenClass(byte[], boolean, MethodHandles.Lookup.ClassOption...) + * Lookup::defineHiddenClass}. * * @return an array of all classes and interfaces in the same nest as * this class * - * @throws LinkageError - * If there is any problem loading or validating a nest member or - * its nest host * @throws SecurityException - * If any returned class is not the current class, and - * if a security manager, s, is present and the caller's - * class loader is not the same as or an ancestor of the class - * loader for that returned class and invocation of {@link - * SecurityManager#checkPackageAccess s.checkPackageAccess()} - * denies access to the package of that returned class + * If any returned class is not the current class, and + * if a security manager, s, is present and the caller's + * class loader is not the same as or an ancestor of the class + * loader for that returned class and invocation of {@link + * SecurityManager#checkPackageAccess s.checkPackageAccess()} + * denies access to the package of that returned class * * @since 11 * @see #getNestHost() + * @jvms 4.7.28 The {@code NestHost} Attribute + * @jvms 4.7.29 The {@code NestMembers} Attribute */ @CallerSensitive public Class[] getNestMembers() { @@ -4223,5 +4232,23 @@ @Override public Optional describeConstable() { return Optional.of(ClassDesc.ofDescriptor(descriptorString())); - } + } + + /** + * Returns {@code true} if and only if the underlying class is a hidden class. + * + *

A hidden class is created by calling + * {@link MethodHandles.Lookup#defineHiddenClass(byte[], boolean, MethodHandles.Lookup.ClassOption...) + * Lookup::defineHiddenClass}. A hidden class is non-discoverable + * by name via {@link Class#forName(String) Class::forName}, + * {@link ClassLoader#loadClass(String) ClassLoader::loadClass}, and bytecode linkage. + * + * @return {@code true} if and only if this class is a hidden class. + * + * @since 15 + * @see MethodHandles.Lookup#defineHiddenClass + */ + @HotSpotIntrinsicCandidate + public native boolean isHiddenClass(); + }