< prev index next >

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

Print this page

        

*** 26,35 **** --- 26,36 ---- package java.lang; 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; import java.io.InputStream; import java.io.ObjectStreamField;
*** 60,71 **** import java.util.LinkedHashSet; import java.util.List; 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; import jdk.internal.loader.BootLoader; import jdk.internal.loader.BuiltinClassLoader; --- 61,70 ----
*** 126,135 **** --- 125,139 ---- * {@code class} files are generated, for example, a Java compiler * will typically record a top-level class as the host of a nest where the * other members are the classes and interfaces whose declarations are * enclosed within the top-level class declaration. * + * <p> Some methods of class {@code Class} expose some characteristics of + * <em>hidden classes</em>. Hidden classes are created by calling + * {@link java.lang.invoke.MethodHandles.Lookup#defineHiddenClass(byte[], boolean, MethodHandles.Lookup.ClassOption...) + * Lookup::defineHiddenClass}. + * * <p> The following example uses a {@code Class} object to print the * class name of an object: * * <blockquote><pre> * void printClassName(Object obj) {
*** 455,465 **** * * @param module A module * @param name The <a href="ClassLoader.html#binary-name">binary name</a> * of the class * @return {@code Class} object of the given name defined in the given module; ! * {@code null} if not found. * * @throws NullPointerException if the given module or name is {@code null} * * @throws LinkageError if the linkage fails * --- 459,469 ---- * * @param module A module * @param name The <a href="ClassLoader.html#binary-name">binary name</a> * of the class * @return {@code Class} object of the given name defined in the given module; ! * {@code null} if not found * * @throws NullPointerException if the given module or name is {@code null} * * @throws LinkageError if the linkage fails *
*** 784,793 **** --- 788,807 ---- * <tr><th scope="row"> long <td style="text-align:center"> J * <tr><th scope="row"> short <td style="text-align:center"> S * </tbody> * </table></blockquote> * + * + * <p> If this class object represents a {@linkplain #isHiddenClass() hidden class}, + * then the name is defined by the JVM of the following format: + * <blockquote> + * {@code <fully-qualified binary name> + '/' + <suffix>} + * </blockquote> + * where the fully-qualified binary name is the class name in the {@code ClassFile} + * from which this {@code Class} object was derived and the suffix is an unique + * unqualified name as specified in JVMS 4.2.2. + * * <p> The class or interface name <i>classname</i> is the binary name of * the class specified above. * * <p> Examples: * <blockquote><pre>
*** 801,810 **** --- 815,826 ---- * returns "[[[[[[[I" * </pre></blockquote> * * @return the name of the class or interface * represented by this object. + * + * @jvms 4.2.2 Unqualified Names */ public String getName() { String name = this.name; return name != null ? name : initClassName(); }
*** 1629,1639 **** if (canonicalName != null) return canonicalName + "[]"; else return ReflectionData.NULL_SENTINEL; } ! if (isLocalOrAnonymousClass()) return ReflectionData.NULL_SENTINEL; Class<?> enclosingClass = getEnclosingClass(); if (enclosingClass == null) { // top level class return getName(); } else { --- 1645,1655 ---- if (canonicalName != null) return canonicalName + "[]"; else return ReflectionData.NULL_SENTINEL; } ! if (isHiddenClass() || isLocalOrAnonymousClass()) return ReflectionData.NULL_SENTINEL; Class<?> enclosingClass = getEnclosingClass(); if (enclosingClass == null) { // top level class return getName(); } else {
*** 1644,1654 **** } } /** * Returns {@code true} if and only if the underlying class ! * is an anonymous class. * * @return {@code true} if and only if this class is an anonymous class. * @since 1.5 */ public boolean isAnonymousClass() { --- 1660,1671 ---- } } /** * Returns {@code true} if and only if the underlying 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 */ public boolean isAnonymousClass() {
*** 2805,2814 **** --- 2822,2836 ---- public java.security.ProtectionDomain getProtectionDomain() { SecurityManager sm = System.getSecurityManager(); 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) { java.security.Permissions perms = new java.security.Permissions();
*** 2819,2829 **** pd = allPermDomain; } return pd; } - /** * Returns the ProtectionDomain of this class. */ private native java.security.ProtectionDomain getProtectionDomain0(); --- 2841,2850 ----
*** 3911,3920 **** --- 3932,3949 ---- * <p>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. * + * <p>If this class is a {@linkplain Class#isHiddenClass() hidden class} + * created by calling + * {@link MethodHandles.Lookup#defineHiddenClass(byte[], boolean, MethodHandles.Lookup.ClassOption...) + * Lookup::defineHiddenClass} with {@link MethodHandles.Lookup.ClassOption#NESTMATE + * NESTMATE} option, then the hidden class is added as a member to + * the nest of a {@linkplain MethodHandles.Lookup#lookupClass() lookup class} + * dynamically and it has the same nest host as the lookup class. + * * @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
*** 3939,3970 **** @CallerSensitive public Class<?> getNestHost() { 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) { ! return this; } // returning a different class requires a security check SecurityManager sm = System.getSecurityManager(); if (sm != null) { checkPackageAccess(sm, ClassLoader.getClassLoader(Reflection.getCallerClass()), true); } return host; } /** * Determines if the given {@code Class} is a nestmate of the * class or interface represented by this {@code Class} object. * Two classes or interfaces are nestmates * if they have the same {@linkplain #getNestHost() nest host}. --- 3968,4000 ---- @CallerSensitive public Class<?> getNestHost() { if (isPrimitive() || isArray()) { return this; } ! ! Class<?> host = this.nest; ! if (host == null) { host = getNestHost0(); // if null then nest membership validation failed, so we // act as-if we have no nest-host attribute if (host == null || host == this) { ! return this.nest = this; ! } ! this.nest = host; } // returning a different class requires a security check SecurityManager sm = System.getSecurityManager(); if (sm != null) { checkPackageAccess(sm, ClassLoader.getClassLoader(Reflection.getCallerClass()), true); } return host; } + // keep a strong reference to the nest host + private transient Class<?> nest; + /** * Determines if the given {@code Class} is a nestmate of the * class or interface represented by this {@code Class} object. * Two classes or interfaces are nestmates * if they have the same {@linkplain #getNestHost() nest host}.
*** 3981,3995 **** } if (isPrimitive() || isArray() || c.isPrimitive() || c.isArray()) { return false; } ! try { ! return getNestHost0() == c.getNestHost0(); ! } catch (LinkageError e) { ! return false; ! } } private native Class<?>[] getNestMembers0(); /** --- 4011,4022 ---- } if (isPrimitive() || isArray() || c.isPrimitive() || c.isArray()) { return false; } ! ! return getNestHost() == c.getNestHost(); } private native Class<?>[] getNestMembers0(); /**
*** 4011,4020 **** --- 4038,4054 ---- * <p>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 + * This method returns the nest members listed in the {@code NestMembers} + * attribute. The returned array does not include any hidden class that + * were added to the nest of this class 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
*** 4112,4117 **** --- 4146,4169 ---- */ @Override public Optional<ClassDesc> describeConstable() { return Optional.of(ClassDesc.ofDescriptor(descriptorString())); } + + /** + * Returns {@code true} if and only if the underlying class is a hidden class. + * + * <p> A <em>hidden class</em> 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 14 + * @see MethodHandles.Lookup#defineHiddenClass + */ + @HotSpotIntrinsicCandidate + public native boolean isHiddenClass(); + }
< prev index next >