< prev index next >

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

Print this page
rev 58872 : 8238358: Implementation of JEP 371: Hidden Classes
Reviewed-by: alanb, cjplummer, coleenp, dholmes, dlong, forax, jlahoda, psandoz, plevart, sspitsyn, vromero
Contributed-by: mandy.chung@oracle.com, lois.foltan@oracle.com, david.holmes@oracle.com, harold.seigel@oracle.com, serguei.spitsyn@oracle.com, alex.buckley@oracle.com, jamsheed.c.m@oracle.com, jan.lahoda@oracle.com, amy.lu@oracle.com
rev 58873 : [mq]: type-descriptor-name

*** 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;
*** 61,72 **** 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; --- 62,71 ----
*** 98,117 **** * ({@code boolean}, {@code byte}, {@code char}, {@code short}, {@code * int}, {@code long}, {@code float}, and {@code double}), and the * keyword {@code void} are also represented as {@code Class} objects. * * <p> {@code Class} has no public constructor. Instead a {@code Class} ! * object is constructed automatically by the Java Virtual Machine ! * when a class loader invokes one of the ! * {@link ClassLoader#defineClass(String,byte[], int,int) defineClass} methods ! * and passes the bytes of a {@code class} file. * * <p> The methods of class {@code Class} expose many characteristics of a * class or interface. Most characteristics are derived from the {@code class} ! * file that the class loader passed to the Java Virtual Machine. A few ! * characteristics are determined by the class loading environment at run time, ! * such as the module returned by {@link #getModule() getModule()}. * * <p> Some methods of class {@code Class} expose whether the declaration of * a class or interface in Java source code was <em>enclosed</em> within * another declaration. Other methods describe how a class or interface * is situated in a <em>nest</em>. A <a id="nest">nest</a> is a set of --- 97,142 ---- * ({@code boolean}, {@code byte}, {@code char}, {@code short}, {@code * int}, {@code long}, {@code float}, and {@code double}), and the * keyword {@code void} are also represented as {@code Class} objects. * * <p> {@code Class} has no public constructor. Instead a {@code Class} ! * object is constructed automatically by the Java Virtual Machine when ! * a class is derived from the bytes of a {@code class} file through ! * the invocation of one of the following methods: ! * <ul> ! * <li> {@link ClassLoader#defineClass(String, byte[], int, int) ClassLoader::defineClass} ! * <li> {@link java.lang.invoke.MethodHandles.Lookup#defineClass(byte[]) ! * java.lang.invoke.MethodHandles.Lookup::defineClass} ! * <li> {@link java.lang.invoke.MethodHandles.Lookup#defineHiddenClass(byte[], boolean, MethodHandles.Lookup.ClassOption...) ! * java.lang.invoke.MethodHandles.Lookup::defineHiddenClass} ! * </ul> * * <p> The methods of class {@code Class} expose many characteristics of a * class or interface. Most characteristics are derived from the {@code class} ! * file that the class loader passed to the Java Virtual Machine or ! * from the {@code class} file passed to {@code Lookup::defineClass} ! * or {@code Lookup::defineHiddenClass}. ! * A few characteristics are determined by the class loading environment ! * at run time, such as the module returned by {@link #getModule() getModule()}. ! * ! * <p> The following example uses a {@code Class} object to print the ! * class name of an object: ! * ! * <blockquote><pre> ! * void printClassName(Object obj) { ! * System.out.println("The class of " + obj + ! * " is " + obj.getClass().getName()); ! * } ! * </pre></blockquote> ! * ! * It is also possible to get the {@code Class} object for a named ! * type (or for {@code void}) using a <i>class literal</i>. ! * For example: ! * ! * <blockquote> ! * {@code System.out.println("The name of class Foo is: "+Foo.class.getName());} ! * </blockquote> * * <p> Some methods of class {@code Class} expose whether the declaration of * a class or interface in Java source code was <em>enclosed</em> within * another declaration. Other methods describe how a class or interface * is situated in a <em>nest</em>. A <a id="nest">nest</a> is a set of
*** 126,162 **** * {@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> The following example uses a {@code Class} object to print the ! * class name of an object: ! * ! * <blockquote><pre> ! * void printClassName(Object obj) { ! * System.out.println("The class of " + obj + ! * " is " + obj.getClass().getName()); ! * } ! * </pre></blockquote> ! * ! * <p> It is also possible to get the {@code Class} object for a named ! * type (or for void) using a class literal. See Section {@jls ! * 15.8.2} of <cite>The Java&trade; Language Specification</cite>. ! * For example: * ! * <blockquote> ! * {@code System.out.println("The name of class Foo is: " + Foo.class.getName());} ! * </blockquote> * * @param <T> the type of the class modeled by this {@code Class} * object. For example, the type of {@code String.class} is {@code * Class<String>}. Use {@code Class<?>} if the class being modeled is * unknown. * * @author unascribed * @see java.lang.ClassLoader#defineClass(byte[], int, int) * @since 1.0 */ public final class Class<T> implements java.io.Serializable, GenericDeclaration, Type, AnnotatedElement, --- 151,197 ---- * {@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> A class or interface created by the invocation of ! * {@link java.lang.invoke.MethodHandles.Lookup#defineHiddenClass(byte[], boolean, MethodHandles.Lookup.ClassOption...) ! * Lookup::defineHiddenClass} is a {@linkplain Class#isHidden() <em>hidden</em>} ! * class or interface. ! * All kinds of class, including enum types and record types, may be ! * hidden classes; all kinds of interface, including annotation types, ! * may be hidden interfaces. ! * ! * The {@linkplain #getName() name of a hidden class or interface} is ! * not a <a href="ClassLoader.html#binary-name">binary name</a>, ! * which means the following: ! * <ul> ! * <li>A hidden class or interface cannot be referenced by the constant pools ! * of other classes and interfaces. ! * <li>A hidden class or interface cannot be described in ! * {@linkplain java.lang.constant.ConstantDesc <em>nominal form</em>} by ! * {@link #describeConstable() Class::describeConstable}, ! * {@link ClassDesc#of(String) ClassDesc::of}, or ! * {@link ClassDesc#ofDescriptor(String) ClassDesc::ofDescriptor}. ! * <li>A hidden class or interface cannot be discovered by {@link #forName Class::forName} ! * or {@link ClassLoader#loadClass(String, boolean) ClassLoader::loadClass}. ! * </ul> * ! * A hidden class or interface is never an array class, but may be ! * the element type of an array. In all other respects, the fact that ! * a class or interface is hidden has no bearing on the characteristics ! * exposed by the methods of class {@code Class}. * * @param <T> the type of the class modeled by this {@code Class} * object. For example, the type of {@code String.class} is {@code * Class<String>}. Use {@code Class<?>} if the class being modeled is * unknown. * * @author unascribed * @see java.lang.ClassLoader#defineClass(byte[], int, int) * @since 1.0 + * @jls 15.8.2 Class Literals */ public final class Class<T> implements java.io.Serializable, GenericDeclaration, Type, AnnotatedElement,
*** 184,196 **** } /** * Converts the object to a string. The string representation is the * string "class" or "interface", followed by a space, and then by the ! * fully qualified name of the class in the format returned by ! * {@code getName}. If this {@code Class} object represents a ! * primitive type, this method returns the name of the primitive type. If * this {@code Class} object represents void this method returns * "void". If this {@code Class} object represents an array type, * this method returns "class " followed by {@code getName}. * * @return a string representation of this {@code Class} object. --- 219,231 ---- } /** * Converts the object to a string. The string representation is the * string "class" or "interface", followed by a space, and then by the ! * name of the class in the format returned by {@code getName}. ! * If this {@code Class} object represents a primitive type, ! * this method returns the name of the primitive type. If * this {@code Class} object represents void this method returns * "void". If this {@code Class} object represents an array type, * this method returns "class " followed by {@code getName}. * * @return a string representation of this {@code Class} object.
*** 743,803 **** public boolean isAnnotation() { return (getModifiers() & ANNOTATION) != 0; } /** ! * Returns {@code true} if this class is a synthetic class; ! * returns {@code false} otherwise. ! * @return {@code true} if and only if this class is a synthetic class as ! * defined by <cite>The Java&trade; Language Specification</cite>. * @jls 13.1 The Form of a Binary * @since 1.5 */ public boolean isSynthetic() { return (getModifiers() & SYNTHETIC) != 0; } /** * Returns the name of the entity (class, interface, array class, ! * primitive type, or void) represented by this {@code Class} object, ! * as a {@code String}. * ! * <p> If this {@code Class} object represents a reference type that is ! * not an array type then the binary name of the class is ! * returned, as specified by <cite>The Java&trade; Language ! * Specification</cite>. * ! * <p> If this {@code Class} object represents a primitive type or void, then the ! * name returned is a {@code String} equal to the Java language ! * keyword corresponding to the primitive type or void. ! * ! * <p> If this {@code Class} object represents a class of arrays, then the internal ! * form of the name consists of the name of the element type preceded by ! * one or more '{@code [}' characters representing the depth of the array ! * nesting. The encoding of element type names is as follows: * * <blockquote><table class="striped"> * <caption style="display:none">Element types and encodings</caption> * <thead> * <tr><th scope="col"> Element Type <th scope="col"> Encoding * </thead> * <tbody style="text-align:left"> ! * <tr><th scope="row"> boolean <td style="text-align:center"> Z ! * <tr><th scope="row"> byte <td style="text-align:center"> B ! * <tr><th scope="row"> char <td style="text-align:center"> C ! * <tr><th scope="row"> class or interface ! * <td style="text-align:center"> L<i>classname</i>; ! * <tr><th scope="row"> double <td style="text-align:center"> D ! * <tr><th scope="row"> float <td style="text-align:center"> F ! * <tr><th scope="row"> int <td style="text-align:center"> I ! * <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> The class or interface name <i>classname</i> is the binary name of ! * the class specified above. * * <p> Examples: * <blockquote><pre> * String.class.getName() * returns "java.lang.String" --- 778,844 ---- public boolean isAnnotation() { return (getModifiers() & ANNOTATION) != 0; } /** ! * Returns {@code true} if and only if this class has the synthetic modifier ! * bit set. ! * ! * @return {@code true} if and only if this class has the synthetic modifier bit set * @jls 13.1 The Form of a Binary + * @jvms 4.1 The {@code ClassFile} Structure * @since 1.5 */ public boolean isSynthetic() { return (getModifiers() & SYNTHETIC) != 0; } /** * Returns the name of the entity (class, interface, array class, ! * primitive type, or void) represented by this {@code Class} object. * ! * <p> If this {@code Class} object represents a class or interface, ! * not an array class, then: ! * <ul> ! * <li> If the class or interface is not {@linkplain #isHidden() hidden}, ! * then the <a href="ClassLoader.html#binary-name">binary name</a> ! * of the class or interface is returned. ! * <li> If the class or interface is hidden, then the result is a string ! * of the form: {@code N + '/' + <suffix>} ! * where {@code N} is the <a href="ClassLoader.html#binary-name">binary name</a> ! * indicated by the {@code class} file passed to ! * {@link java.lang.invoke.MethodHandles.Lookup#defineHiddenClass(byte[], boolean, MethodHandles.Lookup.ClassOption...) ! * Lookup::defineHiddenClass}, and {@code <suffix>} is an unqualified name. ! * </ul> * ! * <p> If this {@code Class} object represents an array class, then ! * the result is a string consisting of one or more '{@code [}' characters ! * representing the depth of the array nesting, followed by the element ! * type as encoded using the following table: * * <blockquote><table class="striped"> * <caption style="display:none">Element types and encodings</caption> * <thead> * <tr><th scope="col"> Element Type <th scope="col"> Encoding * </thead> * <tbody style="text-align:left"> ! * <tr><th scope="row"> {@code boolean} <td style="text-align:center"> {@code Z} ! * <tr><th scope="row"> {@code byte} <td style="text-align:center"> {@code B} ! * <tr><th scope="row"> {@code char} <td style="text-align:center"> {@code C} ! * <tr><th scope="row"> class or interface with <a href="ClassLoader.html#binary-name">binary name</a> <i>N</i> ! * <td style="text-align:center"> {@code L}<em>N</em>{@code ;} ! * <tr><th scope="row"> {@code double} <td style="text-align:center"> {@code D} ! * <tr><th scope="row"> {@code float} <td style="text-align:center"> {@code F} ! * <tr><th scope="row"> {@code int} <td style="text-align:center"> {@code I} ! * <tr><th scope="row"> {@code long} <td style="text-align:center"> {@code J} ! * <tr><th scope="row"> {@code short} <td style="text-align:center"> {@code S} * </tbody> * </table></blockquote> * ! * <p> If this {@code Class} object represents a primitive type or {@code void}, ! * then the result is a string with the same spelling as the Java language ! * keyword which corresponds to the primitive type or {@code void}. * * <p> Examples: * <blockquote><pre> * String.class.getName() * returns "java.lang.String"
*** 807,818 **** * returns "[Ljava.lang.Object;" * (new int[3][4][5][6][7][8][9]).getClass().getName() * returns "[[[[[[[I" * </pre></blockquote> * ! * @return the name of the class or interface * represented by this {@code Class} object. */ public String getName() { String name = this.name; return name != null ? name : initClassName(); } --- 848,860 ---- * returns "[Ljava.lang.Object;" * (new int[3][4][5][6][7][8][9]).getClass().getName() * returns "[[[[[[[I" * </pre></blockquote> * ! * @return the name of the class, interface, or other entity * represented by this {@code Class} object. + * @jls 13.1 The Form of a Binary */ public String getName() { String name = this.name; return name != null ? name : initClassName(); }
*** 886,895 **** --- 928,945 ---- // Initialized in JVM not by private constructor // This field is filtered from reflection access, i.e. getDeclaredField // 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 * {@code GenericDeclaration} object, in declaration order. Returns an * array of length 0 if the underlying generic declaration declares no type
*** 898,908 **** * @return an array of {@code TypeVariable} objects that represent * the type variables declared by this generic declaration * @throws java.lang.reflect.GenericSignatureFormatError if the generic * signature of this generic declaration does not conform to * the format specified in section {@jvms 4.7.9} of ! * <cite>The Java&trade; Virtual Machine Specification</cite>, * @since 1.5 */ @SuppressWarnings("unchecked") public TypeVariable<Class<T>>[] getTypeParameters() { ClassRepository info = getGenericInfo(); --- 948,958 ---- * @return an array of {@code TypeVariable} objects that represent * the type variables declared by this generic declaration * @throws java.lang.reflect.GenericSignatureFormatError if the generic * signature of this generic declaration does not conform to * the format specified in section {@jvms 4.7.9} of ! * <cite>The Java&trade; Virtual Machine Specification</cite> * @since 1.5 */ @SuppressWarnings("unchecked") public TypeVariable<Class<T>>[] getTypeParameters() { ClassRepository info = getGenericInfo();
*** 1021,1034 **** * @jls 6.7 Fully Qualified Names */ public String getPackageName() { String pn = this.packageName; if (pn == null) { ! Class<?> c = this; ! while (c.isArray()) { ! c = c.getComponentType(); ! } if (c.isPrimitive()) { pn = "java.lang"; } else { String cn = c.getName(); int dot = cn.lastIndexOf('.'); --- 1071,1081 ---- * @jls 6.7 Fully Qualified Names */ public String getPackageName() { String pn = this.packageName; if (pn == null) { ! Class<?> c = isArray() ? elementType() : this; if (c.isPrimitive()) { pn = "java.lang"; } else { String cn = c.getName(); int dot = cn.lastIndexOf('.');
*** 1182,1191 **** --- 1229,1252 ---- } } private final Class<?> componentType; + /* + * Returns the {@code Class} representing the element type of an array class. + * If this class does not represent an array class, then this method returns + * {@code null}. + */ + private Class<?> elementType() { + if (!isArray()) return null; + + Class<?> c = this; + while (c.isArray()) { + c = c.getComponentType(); + } + return c; + } /** * Returns the Java language modifiers for this class or interface, encoded * in an integer. The modifiers consist of the Java Virtual Machine's * constants for {@code public}, {@code protected},
*** 1612,1626 **** } return getName(); } /** ! * Returns the canonical name of the underlying class as defined ! * by <cite>The Java&trade; Language Specification</cite>, section ! * {@jls 6.7}. Returns null if the underlying class does not have ! * a canonical name (i.e., if it is a local or anonymous class or ! * an array whose component type does not have a canonical name). * @return the canonical name of the underlying class if it exists, and * {@code null} otherwise. * @since 1.5 */ public String getCanonicalName() { --- 1673,1693 ---- } return getName(); } /** ! * Returns the canonical name of the underlying class as ! * defined by <cite>The Java&trade; Language Specification</cite>. ! * Returns {@code null} if the underlying class does not have a canonical ! * name. Classes without canonical names include: ! * <ul> ! * <li>a {@linkplain #isLocalClass() local class} ! * <li>a {@linkplain #isAnonymousClass() anonymous class} ! * <li>a {@linkplain #isHidden() hidden class} ! * <li>an array whose component type does not have a canonical name</li> ! * </ul> ! * * @return the canonical name of the underlying class if it exists, and * {@code null} otherwise. * @since 1.5 */ public String getCanonicalName() {
*** 1638,1648 **** 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 { --- 1705,1715 ---- if (canonicalName != null) return canonicalName + "[]"; else return ReflectionData.NULL_SENTINEL; } ! if (isHidden() || isLocalOrAnonymousClass()) return ReflectionData.NULL_SENTINEL; Class<?> enclosingClass = getEnclosingClass(); if (enclosingClass == null) { // top level class return getName(); } else {
*** 1655,1664 **** --- 1722,1734 ---- /** * Returns {@code true} if and only if the underlying class * is an anonymous class. * + * @apiNote + * An anonymous class is not a {@linkplain #isHidden() hidden class}. + * * @return {@code true} if and only if this class is an anonymous class. * @since 1.5 */ public boolean isAnonymousClass() { return !isArray() && isLocalOrAnonymousClass() &&
*** 2880,2889 **** --- 2950,2964 ---- 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();
*** 2894,2904 **** pd = allPermDomain; } return pd; } - /** * Returns the ProtectionDomain of this class. */ private native java.security.ProtectionDomain getProtectionDomain0(); --- 2969,2978 ----
*** 2966,2979 **** * Add a package name prefix if the name is not absolute Remove leading "/" * if name is absolute */ private String resolveName(String name) { if (!name.startsWith("/")) { ! Class<?> c = this; ! while (c.isArray()) { ! c = c.getComponentType(); ! } String baseName = c.getPackageName(); if (baseName != null && !baseName.isEmpty()) { name = baseName.replace('.', '/') + "/" + name; } } else { --- 3040,3050 ---- * Add a package name prefix if the name is not absolute Remove leading "/" * if name is absolute */ private String resolveName(String name) { if (!name.startsWith("/")) { ! Class<?> c = isArray() ? elementType() : this; String baseName = c.getPackageName(); if (baseName != null && !baseName.isEmpty()) { name = baseName.replace('.', '/') + "/" + name; } } else {
*** 4040,4072 **** private native Class<?> getNestHost0(); /** * Returns the nest host of the <a href=#nest>nest</a> 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. ! * ! * <p>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. * ! * <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. ! * ! * @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 {@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 {@jvms 4.7.29}). ! * A {@code class} file of version 54.0 or lower does not use these ! * attributes. * * @return the nest host of this class or interface * * @throws SecurityException * If the returned class is not the current class, and --- 4111,4136 ---- private native Class<?> getNestHost0(); /** * Returns the nest host of the <a href=#nest>nest</a> to which the class * or interface represented by this {@code Class} object belongs. ! * Every class and interface belongs to exactly one nest. * ! * 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. ! * ! * <p>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
*** 4083,4103 **** @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) { --- 4147,4159 ---- @CallerSensitive public Class<?> getNestHost() { if (isPrimitive() || isArray()) { return this; } ! ! Class<?> host = getNestHost0(); ! if (host == this) { return this; } // returning a different class requires a security check SecurityManager sm = System.getSecurityManager(); if (sm != null) {
*** 4125,4180 **** } if (isPrimitive() || isArray() || c.isPrimitive() || c.isArray()) { return false; } ! try { ! return getNestHost0() == c.getNestHost0(); ! } catch (LinkageError e) { ! return false; ! } } private native Class<?>[] getNestMembers0(); /** * 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}. * ! * <p>Each of the {@code Class} objects representing array types, ! * primitive types, and {@code void} returns an array containing only * {@code this}. * ! * <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. * * @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, <i>s</i>, 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() */ @CallerSensitive public Class<?>[] getNestMembers() { if (isPrimitive() || isArray()) { return new Class<?>[] { this }; --- 4181,4241 ---- } if (isPrimitive() || isArray() || c.isPrimitive() || c.isArray()) { return false; } ! ! return getNestHost() == c.getNestHost(); } private native Class<?>[] getNestMembers0(); /** * 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. * ! * 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. ! * ! * <p>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}. * ! * @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 or interface * * @throws SecurityException * If any returned class is not the current class, and * if a security manager, <i>s</i>, 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() { if (isPrimitive() || isArray()) { return new Class<?>[] { this };
*** 4194,4221 **** } return members; } /** ! * Returns the type descriptor string for this class. ! * <p> ! * Note that this is not a strict inverse of {@link #forName}; * distinct classes which share a common name but have different class loaders * will have identical descriptor strings. * ! * @return the type descriptor representation * @jvms 4.3.2 Field Descriptors * @since 12 */ @Override public String descriptorString() { if (isPrimitive()) return Wrapper.forPrimitiveType(this).basicTypeString(); ! else if (isArray()) { return "[" + componentType.descriptorString(); ! } ! else { return "L" + getName().replace('.', '/') + ";"; } } /** --- 4255,4331 ---- } return members; } /** ! * Returns the descriptor string of the entity (class, interface, array class, ! * primitive type, or {@code void}) represented by this {@code Class} object. ! * ! * <p> If this {@code Class} object represents a class or interface, ! * not an array class, then: ! * <ul> ! * <li> If the class or interface is not {@linkplain Class#isHidden() hidden}, ! * then the result is a field descriptor (JVMS {@jvms 4.3.2}) ! * for the class or interface. Calling ! * {@link ClassDesc#ofDescriptor(String) ClassDesc::ofDescriptor} ! * with the result descriptor string produces a {@link ClassDesc ClassDesc} ! * describing this class or interface. ! * <li> If the class or interface is {@linkplain Class#isHidden() hidden}, ! * then the result is a string of the form: ! * <blockquote> ! * {@code "L" +} <em>N</em> {@code + "." + <suffix> + ";"} ! * </blockquote> ! * where <em>N</em> is the <a href="ClassLoader.html#binary-name">binary name</a> ! * encoded in internal form indicated by the {@code class} file passed to ! * {@link MethodHandles.Lookup#defineHiddenClass(byte[], boolean, MethodHandles.Lookup.ClassOption...) ! * Lookup::defineHiddenClass}, and {@code <suffix>} is an unqualified name. ! * A hidden class or interface has no {@linkplain ClassDesc nominal descriptor}. ! * The result string is not a type descriptor. ! * </ul> ! * ! * <p> If this {@code Class} object represents an array class, then ! * the result is a string consisting of one or more '{@code [}' characters ! * representing the depth of the array nesting, followed by the ! * descriptor string of the element type. ! * <ul> ! * <li> If the element type is not a {@linkplain Class#isHidden() hidden} class ! * or interface, then this array class can be described nominally. ! * Calling {@link ClassDesc#ofDescriptor(String) ClassDesc::ofDescriptor} ! * with the result descriptor string produces a {@link ClassDesc ClassDesc} ! * describing this array class. ! * <li> If the element type is a {@linkplain Class#isHidden() hidden} class or ! * interface, then this array class cannot be described nominally. ! * The result string is not a type descriptor. ! * </ul> ! * ! * <p> If this {@code Class} object represents a primitive type or ! * {@code void}, then the result is a field descriptor string which ! * is a one-letter code corresponding to a primitive type or {@code void} ! * ({@code "B", "C", "D", "F", "I", "J", "S", "Z", "V"}) (JVMS {@jvms 4.3.2}). ! * ! * @apiNote ! * This is not a strict inverse of {@link #forName}; * distinct classes which share a common name but have different class loaders * will have identical descriptor strings. * ! * @return the descriptor string for this {@code Class} object * @jvms 4.3.2 Field Descriptors * @since 12 */ @Override public String descriptorString() { if (isPrimitive()) return Wrapper.forPrimitiveType(this).basicTypeString(); ! ! if (isArray()) { return "[" + componentType.descriptorString(); ! } else if (isHidden()) { ! String name = getName(); ! int index = name.indexOf('/'); ! return "L" + name.substring(0, index).replace('.', '/') ! + "." + name.substring(index+1) + ";"; ! } else { return "L" + getName().replace('.', '/') + ";"; } } /**
*** 4254,4261 **** * or an empty {@link Optional} if one cannot be constructed. * @since 12 */ @Override public Optional<ClassDesc> describeConstable() { ! return Optional.of(ClassDesc.ofDescriptor(descriptorString())); } } --- 4364,4385 ---- * or an empty {@link Optional} if one cannot be constructed. * @since 12 */ @Override public Optional<ClassDesc> describeConstable() { ! Class<?> c = isArray() ? elementType() : this; ! return c.isHidden() ? Optional.empty() ! : Optional.of(ClassDesc.ofDescriptor(descriptorString())); } + + /** + * Returns {@code true} if and only if the underlying class is a hidden class. + * + * @return {@code true} if and only if this class is a hidden class. + * + * @since 15 + * @see MethodHandles.Lookup#defineHiddenClass + */ + @HotSpotIntrinsicCandidate + public native boolean isHidden(); + }
< prev index next >