mirror of
https://github.com/openjdk/jdk.git
synced 2025-08-27 23:04:50 +02:00
8238358: Implementation of JEP 371: Hidden Classes
Co-authored-by: Lois Foltan <lois.foltan@oracle.com> Co-authored-by: David Holmes <david.holmes@oracle.com> Co-authored-by: Harold Seigel <harold.seigel@oracle.com> Co-authored-by: Serguei Spitsyn <serguei.spitsyn@oracle.com> Co-authored-by: Alex Buckley <alex.buckley@oracle.com> Co-authored-by: Jamsheed Mohammed C M <jamsheed.c.m@oracle.com> Co-authored-by: Jan Lahoda <jan.lahoda@oracle.com> Co-authored-by: Amy Lu <amy.lu@oracle.com> Reviewed-by: alanb, cjplummer, coleenp, dholmes, dlong, forax, jlahoda, psandoz, plevart, sspitsyn, vromero
This commit is contained in:
parent
642041adbc
commit
7cc1371059
198 changed files with 9526 additions and 1575 deletions
|
@ -28,6 +28,7 @@ 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;
|
||||
|
@ -63,8 +64,6 @@ 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;
|
||||
|
@ -100,16 +99,42 @@ import sun.reflect.misc.ReflectUtil;
|
|||
* 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.
|
||||
* 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. A few
|
||||
* characteristics are determined by the class loading environment at run time,
|
||||
* such as the module returned by {@link #getModule() getModule()}.
|
||||
* 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
|
||||
|
@ -128,24 +153,33 @@ import sun.reflect.misc.ReflectUtil;
|
|||
* 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:
|
||||
* <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.
|
||||
*
|
||||
* <blockquote><pre>
|
||||
* void printClassName(Object obj) {
|
||||
* System.out.println("The class of " + obj +
|
||||
* " is " + obj.getClass().getName());
|
||||
* }
|
||||
* </pre></blockquote>
|
||||
* 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>
|
||||
*
|
||||
* <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™ Language Specification</cite>.
|
||||
* For example:
|
||||
*
|
||||
* <blockquote>
|
||||
* {@code System.out.println("The name of class Foo is: " + Foo.class.getName());}
|
||||
* </blockquote>
|
||||
* 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
|
||||
|
@ -155,6 +189,7 @@ import sun.reflect.misc.ReflectUtil;
|
|||
* @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,
|
||||
|
@ -186,9 +221,9 @@ public final class Class<T> implements java.io.Serializable,
|
|||
/**
|
||||
* 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
|
||||
* 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}.
|
||||
|
@ -745,11 +780,12 @@ public final class Class<T> implements java.io.Serializable,
|
|||
}
|
||||
|
||||
/**
|
||||
* 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™ Language Specification</cite>.
|
||||
* 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() {
|
||||
|
@ -758,22 +794,26 @@ public final class Class<T> implements java.io.Serializable,
|
|||
|
||||
/**
|
||||
* Returns the name of the entity (class, interface, array class,
|
||||
* primitive type, or void) represented by this {@code Class} object,
|
||||
* as a {@code String}.
|
||||
* primitive type, or void) represented by this {@code Class} object.
|
||||
*
|
||||
* <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™ Language
|
||||
* Specification</cite>.
|
||||
* <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 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:
|
||||
* <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>
|
||||
|
@ -781,21 +821,22 @@ public final class Class<T> implements java.io.Serializable,
|
|||
* <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
|
||||
* <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> The class or interface name <i>classname</i> is the binary name of
|
||||
* the class specified above.
|
||||
* <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>
|
||||
|
@ -809,8 +850,9 @@ public final class Class<T> implements java.io.Serializable,
|
|||
* returns "[[[[[[[I"
|
||||
* </pre></blockquote>
|
||||
*
|
||||
* @return the name of the class or interface
|
||||
* @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;
|
||||
|
@ -888,6 +930,14 @@ public final class Class<T> implements java.io.Serializable,
|
|||
// 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
|
||||
|
@ -900,7 +950,7 @@ public final class Class<T> implements java.io.Serializable,
|
|||
* @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™ Virtual Machine Specification</cite>,
|
||||
* <cite>The Java™ Virtual Machine Specification</cite>
|
||||
* @since 1.5
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
|
@ -1023,10 +1073,7 @@ public final class Class<T> implements java.io.Serializable,
|
|||
public String getPackageName() {
|
||||
String pn = this.packageName;
|
||||
if (pn == null) {
|
||||
Class<?> c = this;
|
||||
while (c.isArray()) {
|
||||
c = c.getComponentType();
|
||||
}
|
||||
Class<?> c = isArray() ? elementType() : this;
|
||||
if (c.isPrimitive()) {
|
||||
pn = "java.lang";
|
||||
} else {
|
||||
|
@ -1184,6 +1231,20 @@ public final class Class<T> implements java.io.Serializable,
|
|||
|
||||
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
|
||||
|
@ -1614,11 +1675,17 @@ public final class Class<T> implements java.io.Serializable,
|
|||
}
|
||||
|
||||
/**
|
||||
* Returns the canonical name of the underlying class as defined
|
||||
* by <cite>The Java™ 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).
|
||||
* Returns the canonical name of the underlying class as
|
||||
* defined by <cite>The Java™ 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
|
||||
|
@ -1640,7 +1707,7 @@ public final class Class<T> implements java.io.Serializable,
|
|||
else
|
||||
return ReflectionData.NULL_SENTINEL;
|
||||
}
|
||||
if (isLocalOrAnonymousClass())
|
||||
if (isHidden() || isLocalOrAnonymousClass())
|
||||
return ReflectionData.NULL_SENTINEL;
|
||||
Class<?> enclosingClass = getEnclosingClass();
|
||||
if (enclosingClass == null) { // top level class
|
||||
|
@ -1657,6 +1724,9 @@ public final class Class<T> implements java.io.Serializable,
|
|||
* 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
|
||||
*/
|
||||
|
@ -2882,6 +2952,11 @@ public final class Class<T> implements java.io.Serializable,
|
|||
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) {
|
||||
|
@ -2896,7 +2971,6 @@ public final class Class<T> implements java.io.Serializable,
|
|||
return pd;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns the ProtectionDomain of this class.
|
||||
*/
|
||||
|
@ -2968,10 +3042,7 @@ public final class Class<T> implements java.io.Serializable,
|
|||
*/
|
||||
private String resolveName(String name) {
|
||||
if (!name.startsWith("/")) {
|
||||
Class<?> c = this;
|
||||
while (c.isArray()) {
|
||||
c = c.getComponentType();
|
||||
}
|
||||
Class<?> c = isArray() ? elementType() : this;
|
||||
String baseName = c.getPackageName();
|
||||
if (baseName != null && !baseName.isEmpty()) {
|
||||
name = baseName.replace('.', '/') + "/" + name;
|
||||
|
@ -4042,30 +4113,23 @@ public final class Class<T> implements java.io.Serializable,
|
|||
/**
|
||||
* 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.
|
||||
* Every class and interface belongs to exactly one nest.
|
||||
*
|
||||
* <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
|
||||
* 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.
|
||||
*
|
||||
* <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
|
||||
|
@ -4085,17 +4149,9 @@ public final class Class<T> implements java.io.Serializable,
|
|||
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
|
||||
|
@ -4127,11 +4183,8 @@ public final class Class<T> implements java.io.Serializable,
|
|||
c.isPrimitive() || c.isArray()) {
|
||||
return false;
|
||||
}
|
||||
try {
|
||||
return getNestHost0() == c.getNestHost0();
|
||||
} catch (LinkageError e) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return getNestHost() == c.getNestHost();
|
||||
}
|
||||
|
||||
private native Class<?>[] getNestMembers0();
|
||||
|
@ -4140,39 +4193,47 @@ public final class Class<T> implements java.io.Serializable,
|
|||
* 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
|
||||
* 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}.
|
||||
*
|
||||
* <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
|
||||
* 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
|
||||
* this class or interface
|
||||
*
|
||||
* @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
|
||||
* 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() {
|
||||
|
@ -4196,13 +4257,57 @@ public final class Class<T> implements java.io.Serializable,
|
|||
}
|
||||
|
||||
/**
|
||||
* Returns the type descriptor string for this class.
|
||||
* <p>
|
||||
* Note that this is not a strict inverse of {@link #forName};
|
||||
* 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 type descriptor representation
|
||||
* @return the descriptor string for this {@code Class} object
|
||||
* @jvms 4.3.2 Field Descriptors
|
||||
* @since 12
|
||||
*/
|
||||
|
@ -4210,10 +4315,15 @@ public final class Class<T> implements java.io.Serializable,
|
|||
public String descriptorString() {
|
||||
if (isPrimitive())
|
||||
return Wrapper.forPrimitiveType(this).basicTypeString();
|
||||
else if (isArray()) {
|
||||
|
||||
if (isArray()) {
|
||||
return "[" + componentType.descriptorString();
|
||||
}
|
||||
else {
|
||||
} 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('.', '/') + ";";
|
||||
}
|
||||
}
|
||||
|
@ -4256,6 +4366,20 @@ public final class Class<T> implements java.io.Serializable,
|
|||
*/
|
||||
@Override
|
||||
public Optional<ClassDesc> describeConstable() {
|
||||
return Optional.of(ClassDesc.ofDescriptor(descriptorString()));
|
||||
}
|
||||
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();
|
||||
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue