Path: blob/master/jcl/src/java.base/share/classes/java/lang/Class.java
12513 views
/*[INCLUDE-IF JAVA_SPEC_VERSION >= 8]*/1/*******************************************************************************2* Copyright (c) 1998, 2022 IBM Corp. and others3*4* This program and the accompanying materials are made available under5* the terms of the Eclipse Public License 2.0 which accompanies this6* distribution and is available at https://www.eclipse.org/legal/epl-2.0/7* or the Apache License, Version 2.0 which accompanies this distribution and8* is available at https://www.apache.org/licenses/LICENSE-2.0.9*10* This Source Code may also be made available under the following11* Secondary Licenses when the conditions for such availability set12* forth in the Eclipse Public License, v. 2.0 are satisfied: GNU13* General Public License, version 2 with the GNU Classpath14* Exception [1] and GNU General Public License, version 2 with the15* OpenJDK Assembly Exception [2].16*17* [1] https://www.gnu.org/software/classpath/license.html18* [2] http://openjdk.java.net/legal/assembly-exception.html19*20* SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 OR LicenseRef-GPL-2.0 WITH Assembly-exception21*******************************************************************************/22package java.lang;2324import java.io.InputStream;25import java.security.AccessControlContext;26import java.security.ProtectionDomain;27import java.security.Permissions;28/*[IF JAVA_SPEC_VERSION >= 12]*/29import java.lang.constant.ClassDesc;30/*[ENDIF] JAVA_SPEC_VERSION >= 12*/31/*[IF JAVA_SPEC_VERSION >= 11]*/32import jdk.internal.reflect.ReflectionFactory;33/*[ENDIF] JAVA_SPEC_VERSION >= 11*/34import java.lang.reflect.*;35import java.net.URL;36import java.lang.annotation.*;37import java.util.Collection;38import java.util.HashMap;39/*[IF JAVA_SPEC_VERSION >= 16]*/40import java.util.HashSet;41/*[ENDIF] JAVA_SPEC_VERSION >= 16 */42import java.util.LinkedHashMap;43import java.util.List;44import java.util.Map;45import java.util.Set;46/*[IF JAVA_SPEC_VERSION >= 12]*/47import java.util.Optional;48/*[ENDIF] JAVA_SPEC_VERSION >= 12 */49import java.util.concurrent.ConcurrentHashMap;50import java.util.concurrent.atomic.AtomicInteger;51import java.security.AccessController;52import java.security.PrivilegedExceptionAction;53import java.security.PrivilegedAction;54import java.lang.ref.*;55/*[IF JAVA_SPEC_VERSION >= 12]*/56import java.lang.constant.ClassDesc;57import java.lang.constant.Constable;58/*[ENDIF] JAVA_SPEC_VERSION >= 12 */5960import sun.reflect.generics.repository.ClassRepository;61import sun.reflect.generics.factory.CoreReflectionFactory;62import sun.reflect.generics.scope.ClassScope;63import sun.reflect.annotation.AnnotationType;64import java.util.Arrays;65import com.ibm.oti.vm.VM;66/*[IF JAVA_SPEC_VERSION >= 11]*/67import static com.ibm.oti.util.Util.doesClassLoaderDescendFrom;68/*[ENDIF] JAVA_SPEC_VERSION >= 11*/6970/*[IF Sidecar19-SE]71import jdk.internal.misc.Unsafe;72/*[IF JAVA_SPEC_VERSION >= 15]*/73import jdk.internal.access.SharedSecrets;74/*[ELSE] JAVA_SPEC_VERSION >= 1575import jdk.internal.misc.SharedSecrets;76/*[ENDIF] JAVA_SPEC_VERSION >= 15 */77import java.io.IOException;78import jdk.internal.reflect.Reflection;79import jdk.internal.reflect.CallerSensitive;80import jdk.internal.reflect.ConstantPool;81/*[ELSE]*/82import sun.misc.Unsafe;83import sun.misc.SharedSecrets;84import sun.reflect.Reflection;85import sun.reflect.CallerSensitive;86import sun.reflect.ConstantPool;87/*[ENDIF]*/8889import java.util.ArrayList;90import java.lang.annotation.Repeatable;91import java.lang.invoke.*;92import com.ibm.oti.reflect.TypeAnnotationParser;93import java.security.PrivilegedActionException;94import sun.security.util.SecurityConstants;9596/*[IF JAVA_SPEC_VERSION >= 18]*/97import jdk.internal.reflect.CallerSensitiveAdapter;98/*[ENDIF] JAVA_SPEC_VERSION >= 18 */99100/**101* An instance of class Class is the in-image representation102* of a Java class. There are three basic types of Classes103* <dl>104* <dt><em>Classes representing object types (classes or interfaces)</em></dt>105* <dd>These are Classes which represent the class of a106* simple instance as found in the class hierarchy.107* The name of one of these Classes is simply the108* fully qualified class name of the class or interface109* that it represents. Its <em>signature</em> is110* the letter "L", followed by its name, followed111* by a semi-colon (";").</dd>112* <dt><em>Classes representing base types</em></dt>113* <dd>These Classes represent the standard Java base types.114* Although it is not possible to create new instances115* of these Classes, they are still useful for providing116* reflection information, and as the component type117* of array classes. There is one of these Classes for118* each base type, and their signatures are:119* <ul>120* <li><code>B</code> representing the <code>byte</code> base type</li>121* <li><code>S</code> representing the <code>short</code> base type</li>122* <li><code>I</code> representing the <code>int</code> base type</li>123* <li><code>J</code> representing the <code>long</code> base type</li>124* <li><code>F</code> representing the <code>float</code> base type</li>125* <li><code>D</code> representing the <code>double</code> base type</li>126* <li><code>C</code> representing the <code>char</code> base type</li>127* <li><code>Z</code> representing the <code>boolean</code> base type</li>128* <li><code>V</code> representing void function return values</li>129* </ul>130* The name of a Class representing a base type131* is the keyword which is used to represent the132* type in Java source code (i.e. "int" for the133* <code>int</code> base type.</dd>134* <dt><em>Classes representing array classes</em></dt>135* <dd>These are Classes which represent the classes of136* Java arrays. There is one such Class for all array137* instances of a given arity (number of dimensions)138* and leaf component type. In this case, the name of the139* class is one or more left square brackets (one per140* dimension in the array) followed by the signature ofP141* the class representing the leaf component type, which142* can be either an object type or a base type. The143* signature of a Class representing an array type144* is the same as its name.</dd>145* </dl>146*147* @author OTI148* @version initial149*/150public final class Class<T> implements java.io.Serializable, GenericDeclaration, Type151/*[IF JAVA_SPEC_VERSION >= 12]*/152, Constable, TypeDescriptor, TypeDescriptor.OfField<Class<?>>153/*[ENDIF] JAVA_SPEC_VERSION >= 12 */154{155private static final long serialVersionUID = 3206093459760846163L;156private static ProtectionDomain AllPermissionsPD;157private static final int SYNTHETIC = 0x1000;158private static final int ANNOTATION = 0x2000;159private static final int ENUM = 0x4000;160private static final int MEMBER_INVALID_TYPE = -1;161162/*[IF]*/163/**164* It is important that these remain static final165* because the VM peeks for them before running the <clinit>166*/167/*[ENDIF]*/168static final Class<?>[] EmptyParameters = new Class<?>[0];169170/*[PR VMDESIGN 485]*/171private transient long vmRef;172private transient ClassLoader classLoader;173174/*[IF Sidecar19-SE]*/175private transient Module module;176/*[ENDIF]*/177178/*[PR CMVC 125822] Move RAM class fields onto the heap to fix hotswap crash */179private transient ProtectionDomain protectionDomain;180private transient String classNameString;181182/* Cache filename on Class to avoid repeated lookups / allocations in stack traces */183private transient String fileNameString;184185/* Cache the packageName of the Class */186private transient String packageNameString;187188private static final class AnnotationVars {189AnnotationVars() {}190static long annotationTypeOffset = -1;191static long valueMethodOffset = -1;192193/*[PR 66931] annotationType should be volatile because we use compare and swap */194volatile AnnotationType annotationType;195MethodHandle valueMethod;196}197private transient AnnotationVars annotationVars;198private static long annotationVarsOffset = -1;199200/*[PR JAZZ 55717] add Java 8 new field: transient ClassValue.ClassValueMap classValueMap */201/*[PR CMVC 200702] New field to support changes for RI defect 7030453 */202transient ClassValue.ClassValueMap classValueMap;203204private static final class EnumVars<T> {205EnumVars() {}206static long enumDirOffset = -1;207static long enumConstantsOffset = -1;208209Map<String, T> cachedEnumConstantDirectory;210/*[PR CMVC 188840] Perf: Class.getEnumConstants() is slow */211T[] cachedEnumConstants;212}213private transient EnumVars<T> enumVars;214private static long enumVarsOffset = -1;215216transient J9VMInternals.ClassInitializationLock initializationLock;217218private transient Object methodHandleCache;219220/*[PR Jazz 85476] Address locking contention on classRepository in getGeneric*() methods */221private transient ClassRepositoryHolder classRepoHolder;222223/*[IF JAVA_SPEC_VERSION >= 11]*/224private static ReflectionFactory reflectionFactory;225/*[ENDIF] JAVA_SPEC_VERSION >= 11 */226227/* Helper class to hold the ClassRepository. We use a Class with a final228* field to ensure that we have both safe initialization and safe publication.229*/230private static final class ClassRepositoryHolder {231static final ClassRepositoryHolder NullSingleton = new ClassRepositoryHolder(null);232final ClassRepository classRepository;233234ClassRepositoryHolder(ClassRepository classRepo) {235classRepository = classRepo;236}237}238239private static final class AnnotationCache {240final LinkedHashMap<Class<? extends Annotation>, Annotation> directAnnotationMap;241final LinkedHashMap<Class<? extends Annotation>, Annotation> annotationMap;242AnnotationCache(243LinkedHashMap<Class<? extends Annotation>, Annotation> directMap,244LinkedHashMap<Class<? extends Annotation>, Annotation> annMap245) {246directAnnotationMap = directMap;247annotationMap = annMap;248}249}250private transient AnnotationCache annotationCache;251private static long annotationCacheOffset = -1;252private static boolean reflectCacheEnabled;253private static boolean reflectCacheDebug;254private static boolean reflectCacheAppOnly = true;255256/*257* This {@code ClassReflectNullPlaceHolder} class is created to indicate the cached class value is258* initialized to null rather than the default value null ;e.g. {@code cachedDeclaringClass}259* and {@code cachedEnclosingClass}. The reason default value has to be null is that260* j.l.Class instances are created by the VM only rather than Java, and261* any instance field with non-null default values have to be set by VM natives.262*/263private static final class ClassReflectNullPlaceHolder {}264265private static final class MetadataCache {266MetadataCache() {}267268static long cachedCanonicalNameOffset = -1;269static long cachedSimpleNameOffset = -1;270271SoftReference<String> cachedCanonicalName;272SoftReference<String> cachedSimpleName;273}274275private transient MetadataCache metadataCache;276private static long metadataCacheOffset = -1;277278private transient Class<?>[] cachedInterfaces;279private static long cachedInterfacesOffset = -1;280281private transient Class<?> cachedDeclaringClass;282private static long cachedDeclaringClassOffset = -1;283284private transient Class<?> cachedEnclosingClass;285private static long cachedEnclosingClassOffset = -1;286287private transient boolean cachedCheckInnerClassAttr;288289private static Annotation[] EMPTY_ANNOTATION_ARRAY = new Annotation[0];290291static MethodHandles.Lookup implLookup;292293private static final Unsafe unsafe = Unsafe.getUnsafe();294295static Unsafe getUnsafe() {296return unsafe;297}298299/*[IF JAVA_SPEC_VERSION >= 11]*/300private Class<?> nestHost;301/*[ENDIF] JAVA_SPEC_VERSION >= 11 */302303/*[IF JAVA_SPEC_VERSION >= 15]*/304private transient Object classData;305/*[ENDIF] JAVA_SPEC_VERSION >= 15*/306307/*[IF JAVA_SPEC_VERSION >= 16]*/308private transient Class<?>[] cachedPermittedSubclasses;309private static long cachedPermittedSubclassesOffset = -1;310/*[ENDIF] JAVA_SPEC_VERSION >= 16 */311312/**313* Prevents this class from being instantiated. Instances314* created by the virtual machine only.315*/316private Class() {}317318/*319* Ensure the caller has the requested type of access.320*321* @param security the current SecurityManager322* @param callerClassLoader the ClassLoader of the caller of the original protected API323* @param type type of access, PUBLIC, DECLARED or INVALID324*325*/326void checkMemberAccess(SecurityManager security, ClassLoader callerClassLoader, int type) {327if (callerClassLoader != ClassLoader.bootstrapClassLoader) {328ClassLoader loader = getClassLoaderImpl();329/*[PR CMVC 82311] Spec is incorrect before 1.5, RI has this behavior since 1.2 */330/*[PR CMVC 201490] To remove CheckPackageAccess call from more Class methods */331if (type == Member.DECLARED && callerClassLoader != loader) {332security.checkPermission(SecurityConstants.CHECK_MEMBER_ACCESS_PERMISSION);333}334/*[PR CMVC 195558, 197433, 198986] Various fixes. */335if (sun.reflect.misc.ReflectUtil.needsPackageAccessCheck(callerClassLoader, loader)) {336if (Proxy.isProxyClass(this)) {337sun.reflect.misc.ReflectUtil.checkProxyPackageAccess(callerClassLoader, this.getInterfaces());338} else {339String packageName = this.getPackageName();340if ((packageName != null) && (packageName != "")) { //$NON-NLS-1$341security.checkPackageAccess(packageName);342}343}344}345}346}347348/**349* Ensure the caller has the requested type of access.350*351* This helper method is only called by getClasses, and skip security.checkPackageAccess()352* when the class is a ProxyClass and the package name is sun.proxy.353*354* @param type type of access, PUBLIC or DECLARED355*356*/357private void checkNonSunProxyMemberAccess(SecurityManager security, ClassLoader callerClassLoader, int type) {358if (callerClassLoader != ClassLoader.bootstrapClassLoader) {359ClassLoader loader = getClassLoaderImpl();360if (type == Member.DECLARED && callerClassLoader != loader) {361security.checkPermission(SecurityConstants.CHECK_MEMBER_ACCESS_PERMISSION);362}363String packageName = this.getPackageName();364if (!(Proxy.isProxyClass(this) && packageName.equals(sun.reflect.misc.ReflectUtil.PROXY_PACKAGE)) &&365packageName != null && packageName != "" && sun.reflect.misc.ReflectUtil.needsPackageAccessCheck(callerClassLoader, loader)) //$NON-NLS-1$366{367security.checkPackageAccess(packageName);368}369}370}371372private static void forNameAccessCheck(final SecurityManager sm, final Class<?> callerClass, final Class<?> foundClass) {373if (null != callerClass) {374ProtectionDomain pd = callerClass.getPDImpl();375if (null != pd) {376AccessController.doPrivileged(new PrivilegedAction<Object>() {377@Override378public Object run() {379foundClass.checkMemberAccess(sm, callerClass.getClassLoaderImpl(), MEMBER_INVALID_TYPE);380return null;381}382}, new AccessControlContext(new ProtectionDomain[]{pd}));383}384}385}386387/**388* Answers a Class object which represents the class389* named by the argument. The name should be the name390* of a class as described in the class definition of391* java.lang.Class, however Classes representing base392* types can not be found using this method.393*394* @param className The name of the non-base type class to find395* @return the named Class396* @throws ClassNotFoundException If the class could not be found397*398* @see java.lang.Class399*/400@CallerSensitive401public static Class<?> forName(String className) throws ClassNotFoundException402{403/*[IF JAVA_SPEC_VERSION >= 18]*/404return forName(className, getStackClass(1));405/*[ELSE] JAVA_SPEC_VERSION >= 18406@SuppressWarnings("removal")407SecurityManager sm = null;408/**409* Get the SecurityManager from System. If the VM has not yet completed bootstrapping (i.e., J9VMInternals.initialized is still false)410* sm is kept as null without referencing System in order to avoid loading System earlier than necessary.411*/412if (J9VMInternals.initialized) {413sm = System.getSecurityManager();414}415if (null == sm) {416return forNameImpl(className, true, ClassLoader.callerClassLoader());417}418Class<?> caller = getStackClass(1);419ClassLoader callerClassLoader = null;420if (null != caller) {421callerClassLoader = caller.getClassLoaderImpl();422}423Class<?> c = forNameImpl(className, false, callerClassLoader);424forNameAccessCheck(sm, caller, c);425J9VMInternals.initialize(c);426return c;427/*[ENDIF] JAVA_SPEC_VERSION >= 18 */428}429430/*[IF JAVA_SPEC_VERSION >= 18]*/431@CallerSensitiveAdapter432private static Class<?> forName(String className, Class<?> caller) throws ClassNotFoundException433{434@SuppressWarnings("removal")435SecurityManager sm = null;436/**437* Get the SecurityManager from System. If the VM has not yet completed bootstrapping (i.e., J9VMInternals.initialized is still false)438* sm is kept as null without referencing System in order to avoid loading System earlier than necessary.439*/440if (J9VMInternals.initialized) {441sm = System.getSecurityManager();442}443ClassLoader callerClassLoader = null;444if (null == sm) {445if (null != caller) {446callerClassLoader = caller.internalGetClassLoader();447}448return forNameImpl(className, true, callerClassLoader);449}450if (null != caller) {451callerClassLoader = caller.getClassLoaderImpl();452}453Class<?> c = forNameImpl(className, false, callerClassLoader);454forNameAccessCheck(sm, caller, c);455J9VMInternals.initialize(c);456return c;457}458/*[ENDIF] JAVA_SPEC_VERSION >= 18 */459460AnnotationType getAnnotationType() {461AnnotationVars localAnnotationVars = getAnnotationVars();462return localAnnotationVars.annotationType;463}464void setAnnotationType(AnnotationType t) {465AnnotationVars localAnnotationVars = getAnnotationVars();466localAnnotationVars.annotationType = t;467}468/**469* Compare-And-Swap the AnnotationType instance corresponding to this class.470* (This method only applies to annotation types.)471*/472boolean casAnnotationType(AnnotationType oldType, AnnotationType newType) {473AnnotationVars localAnnotationVars = getAnnotationVars();474long localTypeOffset = AnnotationVars.annotationTypeOffset;475if (-1 == localTypeOffset) {476Field field = AccessController.doPrivileged(new PrivilegedAction<Field>() {477public Field run() {478try {479return AnnotationVars.class.getDeclaredField("annotationType"); //$NON-NLS-1$480} catch (Exception e) {481throw newInternalError(e);482}483}484});485localTypeOffset = getUnsafe().objectFieldOffset(field);486AnnotationVars.annotationTypeOffset = localTypeOffset;487}488/*[IF Sidecar19-SE]*/489return getUnsafe().compareAndSetObject(localAnnotationVars, localTypeOffset, oldType, newType);490/*[ELSE]491return getUnsafe().compareAndSwapObject(localAnnotationVars, localTypeOffset, oldType, newType);492/*[ENDIF]*/493}494495/**496* Answers a Class object which represents the class497* named by the argument. The name should be the name498* of a class as described in the class definition of499* java.lang.Class, however Classes representing base500* types can not be found using this method.501* Security rules will be obeyed.502*503* @param className The name of the non-base type class to find504* @param initializeBoolean A boolean indicating whether the class should be505* initialized506* @param classLoader The classloader to use to load the class507* @return the named class.508* @throws ClassNotFoundException If the class could not be found509*510* @see java.lang.Class511*/512@CallerSensitive513public static Class<?> forName(514String className, boolean initializeBoolean, ClassLoader classLoader) throws ClassNotFoundException515{516/*[IF JAVA_SPEC_VERSION >= 18]*/517return forNameHelper(className, initializeBoolean, classLoader, null, false);518/*[ELSE] JAVA_SPEC_VERSION >= 18519@SuppressWarnings("removal")520SecurityManager sm = null;521if (J9VMInternals.initialized) {522sm = System.getSecurityManager();523}524if (null == sm) {525return forNameImpl(className, initializeBoolean, classLoader);526}527Class<?> caller = getStackClass(1);528/* perform security checks */529if (null == classLoader) {530if (null != caller) {531ClassLoader callerClassLoader = caller.getClassLoaderImpl();532if (callerClassLoader != ClassLoader.bootstrapClassLoader) {533/* only allowed if caller has RuntimePermission("getClassLoader") permission */534sm.checkPermission(SecurityConstants.GET_CLASSLOADER_PERMISSION);535}536}537}538Class<?> c = forNameImpl(className, false, classLoader);539forNameAccessCheck(sm, caller, c);540if (initializeBoolean) {541J9VMInternals.initialize(c);542}543return c;544/*[ENDIF] JAVA_SPEC_VERSION >= 18 */545}546547/*[IF JAVA_SPEC_VERSION >= 18]*/548@CallerSensitiveAdapter549private static Class<?> forName(550String className, boolean initializeBoolean, ClassLoader classLoader,551Class<?> caller) throws ClassNotFoundException552{553return forNameHelper(className, initializeBoolean, classLoader, caller, true);554}555556@CallerSensitive557private static Class<?> forNameHelper(558String className, boolean initializeBoolean, ClassLoader classLoader,559Class<?> caller, boolean isAdapter) throws ClassNotFoundException560{561@SuppressWarnings("removal")562SecurityManager sm = null;563if (J9VMInternals.initialized) {564sm = System.getSecurityManager();565}566if (null == sm) {567return forNameImpl(className, initializeBoolean, classLoader);568}569if (!isAdapter) {570caller = getStackClass(2);571}572/* perform security checks */573if (null == classLoader) {574if (null != caller) {575ClassLoader callerClassLoader = caller.getClassLoaderImpl();576if (callerClassLoader != ClassLoader.bootstrapClassLoader) {577/* only allowed if caller has RuntimePermission("getClassLoader") permission */578sm.checkPermission(SecurityConstants.GET_CLASSLOADER_PERMISSION);579}580}581}582Class<?> c = forNameImpl(className, false, classLoader);583forNameAccessCheck(sm, caller, c);584if (initializeBoolean) {585J9VMInternals.initialize(c);586}587return c;588}589/*[ENDIF] JAVA_SPEC_VERSION >= 18 */590591/*[IF Sidecar19-SE]*/592/**593* Answers a Class object which represents the class594* with the given name in the given module.595* The name should be the name of a class as described596* in the class definition of java.lang.Class,597* however Classes representing base598* types can not be found using this method.599* It does not invoke the class initializer.600* Note that this method does not check whether the601* requested class is accessible to its caller.602* Security rules will be obeyed.603*604* @param module The name of the module605* @param name The name of the non-base type class to find606*607* @return The Class object representing the named class608*609* @see java.lang.Class610*/611@CallerSensitive612public static Class<?> forName(Module module, String name)613{614/*[IF JAVA_SPEC_VERSION >= 18]*/615return forNameHelper(module, name, null, false);616/*[ELSE] JAVA_SPEC_VERSION >= 18617@SuppressWarnings("removal")618SecurityManager sm = null;619ClassLoader classLoader;620Class<?> c;621622if ((null == module) || (null == name)) {623throw new NullPointerException();624}625if (J9VMInternals.initialized) {626sm = System.getSecurityManager();627}628if (null != sm) {629Class<?> caller = getStackClass(1);630/* If the caller is not the specified module and RuntimePermission("getClassLoader") permission is denied, throw SecurityException */631if ((null != caller) && (caller.getModule() != module)) {632sm.checkPermission(SecurityConstants.GET_CLASSLOADER_PERMISSION);633}634classLoader = AccessController.doPrivileged(new PrivilegedAction<ClassLoader>() {635public ClassLoader run() {636return module.getClassLoader();637}638});639} else {640classLoader = module.getClassLoader();641}642643try {644if (classLoader == null) {645c = ClassLoader.bootstrapClassLoader.loadClass(module, name);646} else {647c = classLoader.loadClassHelper(name, false, false, module);648}649} catch (ClassNotFoundException e) {650/* This method returns null on failure rather than throwing a ClassNotFoundException */651return null;652}653if (null != c) {654/* If the class loader of the given module defines other modules and655* the given name is a class defined in a different module,656* this method returns null after the class is loaded.657*/658if (c.getModule() != module) {659return null;660}661}662return c;663/*[ENDIF] JAVA_SPEC_VERSION >= 18 */664}665666/*[IF JAVA_SPEC_VERSION >= 18]*/667@CallerSensitiveAdapter668private static Class<?> forName(Module module, String name, Class<?> caller)669{670return forNameHelper(module, name, caller, true);671}672673@CallerSensitive674private static Class<?> forNameHelper(Module module, String name, Class<?> caller, boolean isAdapter)675{676@SuppressWarnings("removal")677SecurityManager sm = null;678ClassLoader classLoader;679Class<?> c;680681if ((null == module) || (null == name)) {682throw new NullPointerException();683}684if (J9VMInternals.initialized) {685sm = System.getSecurityManager();686}687if (null != sm) {688if (!isAdapter) {689caller = getStackClass(2);690}691/* If the caller is not the specified module and RuntimePermission("getClassLoader") permission is denied, throw SecurityException */692if ((null != caller) && (caller.getModule() != module)) {693sm.checkPermission(SecurityConstants.GET_CLASSLOADER_PERMISSION);694}695classLoader = AccessController.doPrivileged(new PrivilegedAction<ClassLoader>() {696public ClassLoader run() {697return module.getClassLoader();698}699});700} else {701classLoader = module.getClassLoader();702}703704try {705if (classLoader == null) {706c = ClassLoader.bootstrapClassLoader.loadClass(module, name);707} else {708c = classLoader.loadClassHelper(name, false, false, module);709}710} catch (ClassNotFoundException e) {711/* This method returns null on failure rather than throwing a ClassNotFoundException */712return null;713}714if (null != c) {715/* If the class loader of the given module defines other modules and716* the given name is a class defined in a different module,717* this method returns null after the class is loaded.718*/719if (c.getModule() != module) {720return null;721}722}723return c;724}725/*[ENDIF] JAVA_SPEC_VERSION >= 18 */726/*[ENDIF] Sidecar19-SE */727728/**729* Answers a Class object which represents the class730* named by the argument. The name should be the name731* of a class as described in the class definition of732* java.lang.Class, however Classes representing base733* types can not be found using this method.734*735* @param className The name of the non-base type class to find736* @param initializeBoolean A boolean indicating whether the class should be737* initialized738* @param classLoader The classloader to use to load the class739* @return the named class.740* @throws ClassNotFoundException If the class could not be found741*742* @see java.lang.Class743*/744private static native Class<?> forNameImpl(String className,745boolean initializeBoolean,746ClassLoader classLoader)747throws ClassNotFoundException;748749/**750* Answers an array containing all public class members751* of the class which the receiver represents and its752* superclasses and interfaces753*754* @return the class' public class members755* @throws SecurityException If member access is not allowed756*757* @see java.lang.Class758*/759@CallerSensitive760public Class<?>[] getClasses() {761/*[PR CMVC 82311] Spec is incorrect before 1.5, RI has this behavior since 1.2 */762@SuppressWarnings("removal")763SecurityManager security = System.getSecurityManager();764if (security != null) {765ClassLoader callerClassLoader = ClassLoader.getStackClassLoader(1);766checkNonSunProxyMemberAccess(security, callerClassLoader, Member.PUBLIC);767}768769java.util.Vector<Class<?>> publicClasses = new java.util.Vector<>();770Class<?> current = this;771Class<?>[] classes;772while(current != null) {773/*[PR 97353] Call the native directly, as the security check in getDeclaredClasses() does nothing but check the caller classloader */774classes = current.getDeclaredClassesImpl();775for (int i = 0; i < classes.length; i++)776if (Modifier.isPublic(classes[i].getModifiers()))777publicClasses.addElement(classes[i]);778current = current.getSuperclass();779}780classes = new Class<?>[publicClasses.size()];781publicClasses.copyInto(classes);782return classes;783}784785/**786* Answers the classloader which was used to load the787* class represented by the receiver. Answer null if the788* class was loaded by the system class loader.789*790* @return the receiver's class loader or nil791*792* @see java.lang.ClassLoader793*/794@CallerSensitive795public ClassLoader getClassLoader() {796if (null != classLoader) {797if (classLoader == ClassLoader.bootstrapClassLoader) {798return null;799}800@SuppressWarnings("removal")801SecurityManager security = System.getSecurityManager();802if (null != security) {803ClassLoader callersClassLoader = ClassLoader.callerClassLoader();804if (ClassLoader.needsClassLoaderPermissionCheck(callersClassLoader, classLoader)) {805security.checkPermission(SecurityConstants.GET_CLASSLOADER_PERMISSION);806}807}808}809return classLoader;810}811812/**813* Returns the classloader used to load the receiver's class.814* Returns null if the class was loaded by the bootstrap (system) class loader.815* This skips security checks.816* @return the receiver's class loader or null817* @see java.lang.ClassLoader818*/819ClassLoader internalGetClassLoader() {820return (classLoader == ClassLoader.bootstrapClassLoader)? null: classLoader;821}822823/**824* Answers the ClassLoader which was used to load the825* class represented by the receiver.826*827* @return the receiver's class loader828*829* @see java.lang.ClassLoader830*/831ClassLoader getClassLoader0() {832ClassLoader loader = getClassLoaderImpl();833return loader;834}835836837/**838* Return the ClassLoader for this Class without doing any security839* checks. The bootstrap ClassLoader is returned, unlike getClassLoader()840* which returns null in place of the bootstrap ClassLoader.841*842* @return the ClassLoader843*844* @see ClassLoader#isASystemClassLoader()845*/846ClassLoader getClassLoaderImpl()847{848return classLoader;849}850851/**852* Answers a Class object which represents the receiver's853* component type if the receiver represents an array type.854* Otherwise answers nil. The component type of an array855* type is the type of the elements of the array.856*857* @return the component type of the receiver.858*859* @see java.lang.Class860*/861public native Class<?> getComponentType();862863private NoSuchMethodException newNoSuchMethodException(String name, Class<?>[] types) {864StringBuilder error = new StringBuilder();865error.append(getName()).append('.').append(name).append('(');866/*[PR CMVC 80340] check for null types */867for (int i = 0; i < types.length; ++i) {868if (i != 0) error.append(", "); //$NON-NLS-1$869error.append(types[i] == null ? null : types[i].getName());870}871error.append(')');872return new NoSuchMethodException(error.toString());873}874875/**876* Answers a public Constructor object which represents the877* constructor described by the arguments.878*879* @param parameterTypes the types of the arguments.880* @return the constructor described by the arguments.881* @throws NoSuchMethodException if the constructor could not be found.882* @throws SecurityException if member access is not allowed883*884* @see #getConstructors885*/886@CallerSensitive887public Constructor<T> getConstructor(Class<?>... parameterTypes) throws NoSuchMethodException, SecurityException {888@SuppressWarnings("removal")889SecurityManager security = System.getSecurityManager();890if (security != null) {891ClassLoader callerClassLoader = ClassLoader.getStackClassLoader(1);892checkMemberAccess(security, callerClassLoader, Member.PUBLIC);893}894895/*[PR CMVC 114820, CMVC 115873, CMVC 116166] add reflection cache */896if (parameterTypes == null) parameterTypes = EmptyParameters;897Constructor<T> cachedConstructor = lookupCachedConstructor(parameterTypes);898if (cachedConstructor != null && Modifier.isPublic(cachedConstructor.getModifiers())) {899return cachedConstructor;900}901902/*[PR CMVC 192714,194493] prepare the class before attempting to access members */903J9VMInternals.prepare(this);904905Constructor<T> rc;906// Handle the default constructor case upfront907if (parameterTypes.length == 0) {908rc = getConstructorImpl(parameterTypes, "()V"); //$NON-NLS-1$909} else {910parameterTypes = parameterTypes.clone();911// Build a signature for the requested method.912String signature = getParameterTypesSignature(true, "<init>", parameterTypes, "V"); //$NON-NLS-1$ //$NON-NLS-2$913rc = getConstructorImpl(parameterTypes, signature);914if (rc != null)915rc = checkParameterTypes(rc, parameterTypes);916}917if (rc == null) throw newNoSuchMethodException("<init>", parameterTypes); //$NON-NLS-1$918return cacheConstructor(rc);919}920921/**922* Answers a public Constructor object which represents the923* constructor described by the arguments.924*925* @param parameterTypes the types of the arguments.926* @param signature the signature of the method.927* @return the constructor described by the arguments.928*929* @see #getConstructors930*/931private native Constructor<T> getConstructorImpl(Class<?> parameterTypes[], String signature);932933/**934* Answers an array containing Constructor objects describing935* all constructors which are visible from the current execution936* context.937*938* @return all visible constructors starting from the receiver.939* @throws SecurityException if member access is not allowed940*941* @see #getMethods942*/943@CallerSensitive944public Constructor<?>[] getConstructors() throws SecurityException {945@SuppressWarnings("removal")946SecurityManager security = System.getSecurityManager();947if (security != null) {948ClassLoader callerClassLoader = ClassLoader.getStackClassLoader(1);949checkMemberAccess(security, callerClassLoader, Member.PUBLIC);950}951952/*[PR CMVC 114820, CMVC 115873, CMVC 116166] add reflection cache */953Constructor<T>[] cachedConstructors = lookupCachedConstructors(CacheKey.PublicConstructorsKey);954if (cachedConstructors != null) {955return cachedConstructors;956}957958/*[PR CMVC 192714,194493] prepare the class before attempting to access members */959J9VMInternals.prepare(this);960961Constructor<T>[] ctors = getConstructorsImpl();962963return cacheConstructors(ctors, CacheKey.PublicConstructorsKey);964}965966/**967* Answers an array containing Constructor objects describing968* all constructors which are visible from the current execution969* context.970*971* @return all visible constructors starting from the receiver.972*973* @see #getMethods974*/975private native Constructor<T>[] getConstructorsImpl();976977/**978* Answers an array containing all class members of the class979* which the receiver represents. Note that some of the fields980* which are returned may not be visible in the current981* execution context.982*983* @return the class' class members984* @throws SecurityException if member access is not allowed985*986* @see java.lang.Class987*/988@CallerSensitive989public Class<?>[] getDeclaredClasses() throws SecurityException {990@SuppressWarnings("removal")991SecurityManager security = System.getSecurityManager();992if (security != null) {993ClassLoader callerClassLoader = ClassLoader.getStackClassLoader(1);994checkNonSunProxyMemberAccess(security, callerClassLoader, Member.DECLARED);995}996997/*[PR 97353] getClasses() calls this native directly */998return getDeclaredClassesImpl();999}10001001/**1002* Answers an array containing all class members of the class1003* which the receiver represents. Note that some of the fields1004* which are returned may not be visible in the current1005* execution context.1006*1007* @return the class' class members1008*1009* @see java.lang.Class1010*/1011private native Class<?>[] getDeclaredClassesImpl();10121013/**1014* Answers a Constructor object which represents the1015* constructor described by the arguments.1016*1017* @param parameterTypes the types of the arguments.1018* @return the constructor described by the arguments.1019* @throws NoSuchMethodException if the constructor could not be found.1020* @throws SecurityException if member access is not allowed1021*1022* @see #getConstructors1023*/1024@CallerSensitive1025public Constructor<T> getDeclaredConstructor(Class<?>... parameterTypes) throws NoSuchMethodException, SecurityException {1026@SuppressWarnings("removal")1027SecurityManager security = System.getSecurityManager();1028if (security != null) {1029ClassLoader callerClassLoader = ClassLoader.getStackClassLoader(1);1030checkMemberAccess(security, callerClassLoader, Member.DECLARED);1031}10321033/*[PR CMVC 114820, CMVC 115873, CMVC 116166] add reflection cache */1034if (parameterTypes == null) parameterTypes = EmptyParameters;1035Constructor<T> cachedConstructor = lookupCachedConstructor(parameterTypes);1036if (cachedConstructor != null) {1037return cachedConstructor;1038}10391040/*[PR CMVC 192714,194493] prepare the class before attempting to access members */1041J9VMInternals.prepare(this);10421043Constructor<T> rc;1044// Handle the default constructor case upfront1045if (parameterTypes.length == 0) {1046rc = getDeclaredConstructorImpl(parameterTypes, "()V"); //$NON-NLS-1$1047} else {1048parameterTypes = parameterTypes.clone();1049// Build a signature for the requested method.1050String signature = getParameterTypesSignature(true, "<init>", parameterTypes, "V"); //$NON-NLS-1$ //$NON-NLS-2$1051rc = getDeclaredConstructorImpl(parameterTypes, signature);1052if (rc != null)1053rc = checkParameterTypes(rc, parameterTypes);1054}1055if (rc == null) throw newNoSuchMethodException("<init>", parameterTypes); //$NON-NLS-1$1056return cacheConstructor(rc);1057}10581059/**1060* Answers a Constructor object which represents the1061* constructor described by the arguments.1062*1063* @param parameterTypes the types of the arguments.1064* @param signature the signature of the method.1065* @return the constructor described by the arguments.1066*1067* @see #getConstructors1068*/1069private native Constructor<T> getDeclaredConstructorImpl(Class<?>[] parameterTypes, String signature);10701071/**1072* Answers an array containing Constructor objects describing1073* all constructor which are defined by the receiver. Note that1074* some of the fields which are returned may not be visible1075* in the current execution context.1076*1077* @return the receiver's constructors.1078* @throws SecurityException if member access is not allowed1079*1080* @see #getMethods1081*/1082@CallerSensitive1083public Constructor<?>[] getDeclaredConstructors() throws SecurityException {1084@SuppressWarnings("removal")1085SecurityManager security = System.getSecurityManager();1086if (security != null) {1087ClassLoader callerClassLoader = ClassLoader.getStackClassLoader(1);1088checkMemberAccess(security, callerClassLoader, Member.DECLARED);1089}10901091/*[PR CMVC 114820, CMVC 115873, CMVC 116166] add reflection cache */1092Constructor<T>[] cachedConstructors = lookupCachedConstructors(CacheKey.DeclaredConstructorsKey);1093if (cachedConstructors != null) {1094return cachedConstructors;1095}10961097/*[PR CMVC 192714,194493] prepare the class before attempting to access members */1098J9VMInternals.prepare(this);10991100Constructor<T>[] ctors = getDeclaredConstructorsImpl();11011102return cacheConstructors(ctors, CacheKey.DeclaredConstructorsKey);1103}11041105/**1106* Answers an array containing Constructor objects describing1107* all constructor which are defined by the receiver. Note that1108* some of the fields which are returned may not be visible1109* in the current execution context.1110*1111* @return the receiver's constructors.1112*1113* @see #getMethods1114*/1115private native Constructor<T>[] getDeclaredConstructorsImpl();11161117/**1118* Answers a Field object describing the field in the receiver1119* named by the argument. Note that the Constructor may not be1120* visible from the current execution context.1121*1122* @param name The name of the field to look for.1123* @return the field in the receiver named by the argument.1124* @throws NoSuchFieldException if the requested field could not be found1125* @throws SecurityException if member access is not allowed1126*1127* @see #getDeclaredFields1128*/1129@CallerSensitive1130public Field getDeclaredField(String name) throws NoSuchFieldException, SecurityException {1131@SuppressWarnings("removal")1132SecurityManager security = System.getSecurityManager();1133if (security != null) {1134ClassLoader callerClassLoader = ClassLoader.getStackClassLoader(1);1135checkMemberAccess(security, callerClassLoader, Member.DECLARED);1136}1137return getDeclaredFieldInternal(name, true);1138}11391140/**1141* A private helper method for getDeclaredField().1142* This is for internal usage, no security check required,1143* and if doCache is false, the field is to be retrieved without caching1144* which can avoid circular dependency at JVM bootstrapping phase.1145*1146* @param name The name of the field to look for.1147* @param doCache The flag to determine if caching the field.1148* @return the field in the receiver named by the argument.1149* @throws NoSuchFieldException if the requested field could not be found1150*/1151@CallerSensitive1152private Field getDeclaredFieldInternal(String name, boolean doCache) throws NoSuchFieldException {1153if (doCache) {1154/*[PR CMVC 114820, CMVC 115873, CMVC 116166] add reflection cache */1155Field cachedField = lookupCachedField(name);1156if (cachedField != null && cachedField.getDeclaringClass() == this) {1157return cachedField;1158}1159}11601161/*[PR CMVC 192714,194493] prepare the class before attempting to access members */1162J9VMInternals.prepare(this);11631164Field field = getDeclaredFieldImpl(name);11651166/*[PR JAZZ 102876] IBM J9VM not using Reflection.filterFields API to hide the sensitive fields */1167Field[] fields = Reflection.filterFields(this, new Field[] {field});1168if (0 == fields.length) {1169throw new NoSuchFieldException(name);1170}11711172if (doCache) {1173return cacheField(fields[0]);1174} else {1175return fields[0];1176}1177}11781179/**1180* Answers a Field object describing the field in the receiver1181* named by the argument. Note that the Constructor may not be1182* visible from the current execution context.1183*1184* @param name The name of the field to look for.1185* @return the field in the receiver named by the argument.1186* @throws NoSuchFieldException If the given field does not exist1187*1188* @see #getDeclaredFields1189*/1190private native Field getDeclaredFieldImpl(String name) throws NoSuchFieldException;11911192/**1193* Answers an array containing Field objects describing1194* all fields which are defined by the receiver. Note that1195* some of the fields which are returned may not be visible1196* in the current execution context.1197*1198* @return the receiver's fields.1199* @throws SecurityException If member access is not allowed1200*1201* @see #getFields1202*/1203@CallerSensitive1204public Field[] getDeclaredFields() throws SecurityException {1205@SuppressWarnings("removal")1206SecurityManager security = System.getSecurityManager();1207if (security != null) {1208ClassLoader callerClassLoader = ClassLoader.getStackClassLoader(1);1209checkMemberAccess(security, callerClassLoader, Member.DECLARED);1210}12111212/*[PR CMVC 114820, CMVC 115873, CMVC 116166] add reflection cache */1213Field[] cachedFields = lookupCachedFields(CacheKey.DeclaredFieldsKey);1214if (cachedFields != null) {1215return cachedFields;1216}12171218/*[PR CMVC 192714,194493] prepare the class before attempting to access members */1219J9VMInternals.prepare(this);12201221Field[] fields = getDeclaredFieldsImpl();12221223return cacheFields(Reflection.filterFields(this, fields), CacheKey.DeclaredFieldsKey);1224}12251226/**1227* Answers an array containing Field objects describing1228* all fields which are defined by the receiver. Note that1229* some of the fields which are returned may not be visible1230* in the current execution context.1231*1232* @return the receiver's fields.1233*1234* @see #getFields1235*/1236private native Field[] getDeclaredFieldsImpl();12371238/*[IF JAVA_SPEC_VERSION >= 11]*/1239/**1240* Answers a list of method objects which represent the public methods1241* described by the arguments. Note that the associated method may not1242* be visible from the current execution context.1243* An empty list is returned if the method can't be found.1244*1245* @param name the name of the method1246* @param parameterTypes the types of the arguments.1247* @return a list of methods described by the arguments.1248*1249* @see #getMethods1250*/1251@CallerSensitive1252List<Method> getDeclaredPublicMethods(String name, Class<?>... parameterTypes) {1253CacheKey ck = CacheKey.newDeclaredPublicMethodsKey(name, parameterTypes);1254List<Method> methodList = lookupCachedDeclaredPublicMethods(ck);1255if (methodList != null) {1256return methodList;1257}1258try {1259methodList = new ArrayList<>();1260getMethodHelper(false, true, methodList, name, parameterTypes);1261} catch (NoSuchMethodException e) {1262// no NoSuchMethodException expected1263}1264return cacheDeclaredPublicMethods(methodList, ck);1265}12661267private List<Method> lookupCachedDeclaredPublicMethods(CacheKey cacheKey) {1268if (!reflectCacheEnabled) return null;1269if (reflectCacheDebug) {1270reflectCacheDebugHelper(null, 0, "lookup DeclaredPublicMethods in: ", getName()); //$NON-NLS-1$1271}1272ReflectCache cache = peekReflectCache();1273if (cache != null) {1274List<Method> methods = (List<Method>) cache.find(cacheKey);1275if (methods != null) {1276// assuming internal caller won't change this method list content1277return methods;1278}1279}1280return null;1281}1282@CallerSensitive1283private List<Method> cacheDeclaredPublicMethods(List<Method> methods, CacheKey cacheKey) {1284if (!reflectCacheEnabled1285|| (reflectCacheAppOnly && ClassLoader.getStackClassLoader(2) == ClassLoader.bootstrapClassLoader)1286) {1287return methods;1288}1289if (reflectCacheDebug) {1290reflectCacheDebugHelper(null, 0, "cache DeclaredPublicMethods in: ", getName()); //$NON-NLS-1$1291}1292ReflectCache cache = null;1293try {1294cache = acquireReflectCache();1295for (int i = 0; i < methods.size(); i++) {1296Method method = methods.get(i);1297CacheKey key = CacheKey.newMethodKey(method.getName(), getParameterTypes(method), method.getReturnType());1298Method methodPut = cache.insertIfAbsent(key, method);1299if (method != methodPut) {1300methods.set(i, methodPut);1301}1302}1303cache.insert(cacheKey, methods);1304} finally {1305if (cache != null) {1306cache.release();1307}1308}1309return methods;1310}1311/*[ENDIF] JAVA_SPEC_VERSION >= 11 */13121313/**1314* A helper method for reflection debugging1315*1316* @param parameters parameters[i].getName() to be appended1317* @param posInsert parameters to be appended AFTER msgs[posInsert]1318* @param msgs a message array1319*/1320static void reflectCacheDebugHelper(Class<?>[] parameters, int posInsert, String... msgs) {1321StringBuilder output = new StringBuilder(200);1322for (int i = 0; i < msgs.length; i++) {1323output.append(msgs[i]);1324if ((parameters != null) && (i == posInsert)) {1325output.append('(');1326for (int j = 0; j < parameters.length; j++) {1327if (j != 0) {1328output.append(", "); //$NON-NLS-1$1329}1330output.append(parameters[i].getName());1331}1332output.append(')');1333}1334}1335System.err.println(output);1336}13371338/**1339* Answers a Method object which represents the method1340* described by the arguments. Note that the associated1341* method may not be visible from the current execution1342* context.1343*1344* @param name the name of the method1345* @param parameterTypes the types of the arguments.1346* @return the method described by the arguments.1347* @throws NoSuchMethodException if the method could not be found.1348* @throws SecurityException If member access is not allowed1349*1350* @see #getMethods1351*/1352@CallerSensitive1353public Method getDeclaredMethod(String name, Class<?>... parameterTypes) throws NoSuchMethodException, SecurityException {1354@SuppressWarnings("removal")1355SecurityManager security = System.getSecurityManager();1356if (security != null) {1357ClassLoader callerClassLoader = ClassLoader.getStackClassLoader(1);1358checkMemberAccess(security, callerClassLoader, Member.DECLARED);1359}1360return getMethodHelper(true, true, null, name, parameterTypes);1361}13621363/**1364* This native iterates over methods matching the provided name and signature1365* in the receiver class. The startingPoint parameter is passed the last1366* method returned (or null on the first use), and the native returns the next1367* matching method or null if there are no more matches.1368* Note that the associated method may not be visible from the1369* current execution context.1370*1371* @param name the name of the method1372* @param parameterTypes the types of the arguments.1373* @param partialSignature the signature of the method, without return type.1374* @param startingPoint the method to start searching after, or null to start at the beginning1375* @return the next Method described by the arguments1376*1377* @see #getMethods1378*/1379private native Method getDeclaredMethodImpl(String name, Class<?>[] parameterTypes, String partialSignature, Method startingPoint);13801381/**1382* Answers an array containing Method objects describing1383* all methods which are defined by the receiver. Note that1384* some of the methods which are returned may not be visible1385* in the current execution context.1386*1387* @throws SecurityException if member access is not allowed1388* @return the receiver's methods.1389*1390* @see #getMethods1391*/1392@CallerSensitive1393public Method[] getDeclaredMethods() throws SecurityException {1394@SuppressWarnings("removal")1395SecurityManager security = System.getSecurityManager();1396if (security != null) {1397ClassLoader callerClassLoader = ClassLoader.getStackClassLoader(1);1398checkMemberAccess(security, callerClassLoader, Member.DECLARED);1399}14001401/*[PR CMVC 114820, CMVC 115873, CMVC 116166] add reflection cache */1402Method[] cachedMethods = lookupCachedMethods(CacheKey.DeclaredMethodsKey);1403if (cachedMethods != null) {1404return cachedMethods;1405}14061407/*[PR CMVC 192714,194493] prepare the class before attempting to access members */1408J9VMInternals.prepare(this);14091410/*[PR CMVC 194301] do not allow reflect access to sun.misc.Unsafe.getUnsafe() */1411return cacheMethods(Reflection.filterMethods(this, getDeclaredMethodsImpl()), CacheKey.DeclaredMethodsKey);1412}14131414/**1415* Answers an array containing Method objects describing1416* all methods which are defined by the receiver. Note that1417* some of the methods which are returned may not be visible1418* in the current execution context.1419*1420* @return the receiver's methods.1421*1422* @see #getMethods1423*/1424private native Method[] getDeclaredMethodsImpl();14251426/**1427* Answers the class which declared the class represented1428* by the receiver. This will return null if the receiver1429* is not a member of another class.1430*1431* @return the declaring class of the receiver.1432*/1433@CallerSensitive1434public Class<?> getDeclaringClass() {1435if (cachedDeclaringClassOffset == -1) {1436cachedDeclaringClassOffset = getFieldOffset("cachedDeclaringClass"); //$NON-NLS-1$1437}1438if (cachedDeclaringClass == null) {1439Class<?> localDeclaringClass = getDeclaringClassImpl();1440if (localDeclaringClass == null) {1441localDeclaringClass = ClassReflectNullPlaceHolder.class;1442}1443writeFieldValue(cachedDeclaringClassOffset, localDeclaringClass);1444}14451446/**1447* ClassReflectNullPlaceHolder.class means the value of cachedDeclaringClass is null1448* @see ClassReflectNullPlaceHolder.class1449*/1450Class<?> declaringClass = cachedDeclaringClass == ClassReflectNullPlaceHolder.class ? null : cachedDeclaringClass;1451if (declaringClass == null) {1452if (!cachedCheckInnerClassAttr) {1453/* Check whether the enclosing class has an valid inner class entry to the current class.1454* Note: the entries are populated with the InnerClass attribute when creating ROM class.1455*/1456checkInnerClassAttrOfEnclosingClass();1457cachedCheckInnerClassAttr = true;1458}1459return declaringClass;1460}1461if (declaringClass.isClassADeclaredClass(this)) {1462@SuppressWarnings("removal")1463SecurityManager security = System.getSecurityManager();1464if (security != null) {1465ClassLoader callerClassLoader = ClassLoader.getStackClassLoader(1);1466declaringClass.checkMemberAccess(security, callerClassLoader, MEMBER_INVALID_TYPE);1467}1468return declaringClass;1469} else if (this.isClassADeclaredClass(declaringClass) || this.isClassADeclaredClass(this) || this.isCircularDeclaringClass()) {1470/* The execution of VM shouldn't be interrupted by corrupted InnerClasses attributes such as circular entries.1471* To be specific, Class A is the declaringClass of B, Class B is the declaringClass of C, ..., Class Z is the1472* declaringClass of A, which forms a circle in the entries, whether or not the relationships between two classes1473* literally exist. e.g.1474* The specified declaringClass is fake one (intentionally set in the class file) which actually has no1475* relationship with current class but the current class is the declaring class of the specified declaringClass.1476* Thus, there are 3 cases:1477* 1) A --> B (real/fake) --> A: B is the declaring class of A and is one of the inner classes of A.1478* 2) B --> A --> A: B is the declaring class of A while A is one of the inner classes of A itself.1479* 3) A --> B --> C --> ... Z --> A: keep fetching the declaring class from A ends up wit A itself.1480*/1481return null;1482}14831484/*[MSG "K0555", "incompatible InnerClasses attribute between \"{0}\" and \"{1}\""]*/1485throw new IncompatibleClassChangeError(1486com.ibm.oti.util.Msg.getString("K0555", this.getName(), declaringClass.getName())); //$NON-NLS-1$1487}14881489/**1490* Checks whether the current class exists in the InnerClass attribute of the specified enclosing class1491* when this class is not defined directly inside the enclosing class (e.g. defined inside a method).1492*1493* Note: The direct inner classes of the declaring class is already checked in getDeclaringClass()1494* when the enclosing class is the declaring class.1495*/1496private void checkInnerClassAttrOfEnclosingClass() {1497Class<?> enclosingClass = getEnclosingObjectClass();1498if ((enclosingClass != null) && !enclosingClass.isClassAnEnclosedClass(this)) {1499/*[MSG "K0555", "incompatible InnerClasses attribute between \"{0}\" and \"{1}\""]*/1500throw new IncompatibleClassChangeError(1501com.ibm.oti.util.Msg.getString("K0555", this.getName(), enclosingClass.getName())); //$NON-NLS-1$1502}1503}15041505/**1506* Returns true if a cycle exists from the current class to itself by repeatedly searching the declaring classes.1507*1508* @return true if the cycle exists, false otherwise.1509*1510*/1511private native boolean isCircularDeclaringClass();15121513/**1514* Returns true if the class passed in to the method is a declared class of1515* this class.1516*1517* @param aClass The class to validate1518* @return true if aClass a declared class of this class1519* false otherwise.1520*1521*/1522private native boolean isClassADeclaredClass(Class<?> aClass);15231524/**1525* Returns true if the class passed in to the method is an enclosed class of1526* this class, which includes both the declared classes and the classes defined1527* inside a method of this class.1528*1529* @param aClass The class to validate1530* @return true if aClass an enclosed class of this class1531* false otherwise.1532*1533*/1534private native boolean isClassAnEnclosedClass(Class<?> aClass);15351536/**1537* Answers the class which declared the class represented1538* by the receiver. This will return null if the receiver1539* is a member of another class.1540*1541* @return the declaring class of the receiver.1542*/1543private native Class<?> getDeclaringClassImpl();15441545/**1546* Answers a Field object describing the field in the receiver1547* named by the argument which must be visible from the current1548* execution context.1549*1550* @param name The name of the field to look for.1551* @return the field in the receiver named by the argument.1552* @throws NoSuchFieldException If the given field does not exist1553* @throws SecurityException If access is denied1554*1555* @see #getDeclaredFields1556*/1557@CallerSensitive1558public Field getField(String name) throws NoSuchFieldException, SecurityException {1559@SuppressWarnings("removal")1560SecurityManager security = System.getSecurityManager();1561if (security != null) {1562ClassLoader callerClassLoader = ClassLoader.getStackClassLoader(1);1563checkMemberAccess(security, callerClassLoader, Member.PUBLIC);1564}15651566/*[PR CMVC 114820, CMVC 115873, CMVC 116166] add reflection cache */1567Field cachedField = lookupCachedField(name);1568if (cachedField != null && Modifier.isPublic(cachedField.getModifiers())) {1569return cachedField;1570}15711572/*[PR CMVC 192714,194493] prepare the class before attempting to access members */1573J9VMInternals.prepare(this);15741575Field field = getFieldImpl(name);15761577if (0 == Reflection.filterFields(this, new Field[] {field}).length) {1578throw new NoSuchFieldException(name);1579}15801581return cacheField(field);1582}15831584/**1585* Answers a Field object describing the field in the receiver1586* named by the argument which must be visible from the current1587* execution context.1588*1589* @param name The name of the field to look for.1590* @return the field in the receiver named by the argument.1591* @throws NoSuchFieldException If the given field does not exist1592*1593* @see #getDeclaredFields1594*/1595private native Field getFieldImpl(String name) throws NoSuchFieldException;15961597/**1598* Answers an array containing Field objects describing1599* all fields which are visible from the current execution1600* context.1601*1602* @return all visible fields starting from the receiver.1603* @throws SecurityException If member access is not allowed1604*1605* @see #getDeclaredFields1606*/1607@CallerSensitive1608public Field[] getFields() throws SecurityException {1609@SuppressWarnings("removal")1610SecurityManager security = System.getSecurityManager();1611if (security != null) {1612ClassLoader callerClassLoader = ClassLoader.getStackClassLoader(1);1613checkMemberAccess(security, callerClassLoader, Member.PUBLIC);1614}16151616/*[PR CMVC 114820, CMVC 115873, CMVC 116166] add reflection cache */1617Field[] cachedFields = lookupCachedFields(CacheKey.PublicFieldsKey);1618if (cachedFields != null) {1619return cachedFields;1620}16211622/*[PR CMVC 192714,194493] prepare the class before attempting to access members */1623J9VMInternals.prepare(this);16241625Field[] fields = getFieldsImpl();16261627return cacheFields(Reflection.filterFields(this, fields), CacheKey.PublicFieldsKey);1628}16291630/**1631* Answers an array containing Field objects describing1632* all fields which are visible from the current execution1633* context.1634*1635* @return all visible fields starting from the receiver.1636*1637* @see #getDeclaredFields1638*/1639private native Field[] getFieldsImpl();16401641/**1642* Answers an array of Class objects which match the interfaces1643* specified in the receiver classes <code>implements</code>1644* declaration1645*1646* @return {@code Class<?>[]}1647* the interfaces the receiver claims to implement.1648*/1649public Class<?>[] getInterfaces() {1650if (cachedInterfacesOffset == -1) {1651cachedInterfacesOffset = getFieldOffset("cachedInterfaces"); //$NON-NLS-1$1652}1653if (cachedInterfaces == null) {1654writeFieldValue(cachedInterfacesOffset, J9VMInternals.getInterfaces(this));1655}1656Class<?>[] newInterfaces = cachedInterfaces.length == 0 ? cachedInterfaces: cachedInterfaces.clone();1657return newInterfaces;1658}16591660/**1661* Answers a Method object which represents the method1662* described by the arguments.1663*1664* @param name String1665* the name of the method1666* @param parameterTypes {@code Class<?>[]}1667* the types of the arguments.1668* @return Method1669* the method described by the arguments.1670* @throws NoSuchMethodException1671* if the method could not be found.1672* @throws SecurityException1673* if member access is not allowed1674*1675* @see #getMethods1676*/1677@CallerSensitive1678public Method getMethod(String name, Class<?>... parameterTypes) throws NoSuchMethodException, SecurityException {1679@SuppressWarnings("removal")1680SecurityManager security = System.getSecurityManager();1681if (security != null) {1682ClassLoader callerClassLoader = ClassLoader.getStackClassLoader(1);1683checkMemberAccess(security, callerClassLoader, Member.PUBLIC);1684}1685return getMethodHelper(true, false, null, name, parameterTypes);1686}16871688/**1689* Helper method throws NoSuchMethodException when throwException is true, otherwise returns null.1690*/1691private Method throwExceptionOrReturnNull(boolean throwException, String name, Class<?>... parameterTypes) throws NoSuchMethodException {1692if (throwException) {1693throw newNoSuchMethodException(name, parameterTypes);1694} else {1695return null;1696}1697}1698/**1699* Helper method for1700* public Method getDeclaredMethod(String name, Class<?>... parameterTypes)1701* public Method getMethod(String name, Class<?>... parameterTypes)1702* List<Method> getDeclaredPublicMethods(String name, Class<?>... parameterTypes)1703* without going thorough security checking1704*1705* @param throwException boolean1706* true - throw exception in this helper;1707* false - return null instead without throwing NoSuchMethodException1708* @param forDeclaredMethod boolean1709* true - for getDeclaredMethod(String name, Class<?>... parameterTypes)1710* & getDeclaredPublicMethods(String name, Class<?>... parameterTypes);1711* false - for getMethod(String name, Class<?>... parameterTypes);1712* @param name String the name of the method1713* @param parameterTypes Class<?>[] the types of the arguments1714* @param methodList List<Method> a list to store the methods described by the arguments1715* for getDeclaredPublicMethods()1716* or null for getDeclaredMethod() & getMethod()1717* @return Method the method described by the arguments.1718* @throws NoSuchMethodException if the method could not be found.1719*/1720@CallerSensitive1721Method getMethodHelper(1722boolean throwException, boolean forDeclaredMethod, List<Method> methodList, String name, Class<?>... parameterTypes)1723throws NoSuchMethodException {1724Method result;1725Method bestCandidate;1726String strSig;1727boolean candidateFromInterface = false;17281729/*[PR CMVC 114820, CMVC 115873, CMVC 116166] add reflection cache */1730if (parameterTypes == null) {1731parameterTypes = EmptyParameters;1732}1733if (methodList == null) {1734// getDeclaredPublicMethods() has to go through all methods anyway1735Method cachedMethod = lookupCachedMethod(name, parameterTypes);1736if ((cachedMethod != null)1737&& ((forDeclaredMethod && (cachedMethod.getDeclaringClass() == this))1738|| (!forDeclaredMethod && Modifier.isPublic(cachedMethod.getModifiers())))) {1739return cachedMethod;1740}1741}17421743/*[PR CMVC 192714,194493] prepare the class before attempting to access members */1744J9VMInternals.prepare(this);17451746// Handle the no parameter case upfront1747/*[PR 103441] should throw NullPointerException when name is null */1748if (name == null || parameterTypes.length == 0) {1749strSig = "()"; //$NON-NLS-1$1750parameterTypes = EmptyParameters;1751} else {1752parameterTypes = parameterTypes.clone();1753// Build a signature for the requested method.1754strSig = getParameterTypesSignature(throwException, name, parameterTypes, ""); //$NON-NLS-1$1755if (strSig == null) {1756return null;1757}1758}17591760if (forDeclaredMethod) {1761result = getDeclaredMethodImpl(name, parameterTypes, strSig, null);1762} else {1763if (this.isInterface()) {1764/* if the result is not in the current class, all superinterfaces will need to be searched */1765result = getDeclaredMethodImpl(name, parameterTypes, strSig, null);1766if (null == result) {1767result = getMostSpecificMethodFromAllInterfacesOfCurrentClass(null, null, name, parameterTypes);1768candidateFromInterface = true;1769}1770} else {1771result = getMethodImpl(name, parameterTypes, strSig);1772/* Retrieve the specified method implemented by the superclass from the top to the bottom. */1773if ((result != null) && result.getDeclaringClass().isInterface()) {1774HashMap<Class<?>, HashMap<MethodInfo, MethodInfo>> infoCache = new HashMap<>(16);1775result = getMostSpecificMethodFromAllInterfacesOfAllSuperclasses(infoCache, name, parameterTypes);1776candidateFromInterface = true;1777}1778}1779}17801781if (result == null) {1782return throwExceptionOrReturnNull(throwException, name, parameterTypes);1783}1784if (0 == Reflection.filterMethods(this, new Method[] {result}).length) {1785return throwExceptionOrReturnNull(throwException, name, parameterTypes);1786}17871788/*[PR 127079] Use declaring classloader for Methods */1789/*[PR CMVC 104523] ensure parameter types are visible in the receiver's class loader */1790if (parameterTypes.length > 0) {1791ClassLoader loader = forDeclaredMethod ? getClassLoaderImpl() : result.getDeclaringClass().getClassLoaderImpl();1792for (int i = 0; i < parameterTypes.length; ++i) {1793Class<?> parameterType = parameterTypes[i];1794if (!parameterType.isPrimitive()) {1795try {1796if (Class.forName(parameterType.getName(), false, loader) != parameterType) {1797return throwExceptionOrReturnNull(throwException, name, parameterTypes);1798}1799} catch(ClassNotFoundException e) {1800return throwExceptionOrReturnNull(throwException, name, parameterTypes);1801}1802}1803}1804}1805if ((methodList != null) && ((result.getModifiers() & Modifier.PUBLIC) != 0)) {1806methodList.add(result);1807}18081809/* [PR 113003] The native is called repeatedly until it returns null,1810* as each call returns another match if one exists. The first call uses1811* getMethodImpl which searches across superclasses and interfaces, but1812* since the spec requires that we only weigh multiple matches against1813* each other if they are in the same class, on subsequent calls we call1814* getDeclaredMethodImpl on the declaring class of the first hit.1815* If more than one match is found, more specific method is selected.1816* For methods with same signature (name, parameter types) but different return types,1817* Method N with return type S is more specific than M with return type R if:1818* S is the same as or a subtype of R.1819* Otherwise, the result method is chosen arbitrarily from specific methods.1820*/1821bestCandidate = result;1822if (!candidateFromInterface) {1823Class<?> declaringClass = forDeclaredMethod ? this : result.getDeclaringClass();1824while (true) {1825result = declaringClass.getDeclaredMethodImpl(name, parameterTypes, strSig, result);1826if (result == null) {1827break;1828}1829boolean publicMethod = ((result.getModifiers() & Modifier.PUBLIC) != 0);1830if ((methodList != null) && publicMethod) {1831methodList.add(result);1832}1833if (forDeclaredMethod || publicMethod) {1834// bestCandidate and result have same declaringClass.1835Class<?> candidateRetType = bestCandidate.getReturnType();1836Class<?> resultRetType = result.getReturnType();1837if ((candidateRetType != resultRetType) && candidateRetType.isAssignableFrom(resultRetType)) {1838bestCandidate = result;1839}1840}1841}1842}1843return cacheMethod(bestCandidate);1844}18451846/**1847* Helper method searches all interfaces implemented by superclasses from the top to the bottom1848* for the most specific method declared in one of these interfaces.1849*1850* @param infoCache1851* @param name the specified method's name1852* @param parameterTypes the types of the arguments of the specified method1853* @return the most specific method selected from all interfaces from each superclass of the current class;1854* otherwise, return the method of the first interface from the top superclass1855* if the return types of all specified methods are identical.1856*/1857private Method getMostSpecificMethodFromAllInterfacesOfAllSuperclasses(HashMap<Class<?>, HashMap<MethodInfo, MethodInfo>> infoCache,1858String name, Class<?>... parameterTypes)1859{1860Method candidateMethod = null;1861if (this != Object.class) {1862/* get to the top superclass first. if all return types end up being the same the interfaces from this superclass have priority. */1863Class superclz = getSuperclass();1864candidateMethod = superclz.getMostSpecificMethodFromAllInterfacesOfAllSuperclasses(infoCache, name, parameterTypes);18651866/* search all interfaces of current class, comparing against result from previous superclass. */1867candidateMethod = getMostSpecificMethodFromAllInterfacesOfCurrentClass(infoCache, candidateMethod, name, parameterTypes);1868}1869return candidateMethod;1870}18711872/**1873* Helper method searches all interfaces implemented by the current class or interface1874* for the most specific method declared in one of these interfaces.1875*1876* @param infoCache1877* @param potentialCandidate potential candidate from superclass, null if currentClass is an interface1878* @param name the specified method's name1879* @param parameterTypes the types of the arguments of the specified method1880* @return the most specific method selected from all interfaces;1881* otherwise if return types from all qualifying methods are identical, return an arbitrary method.1882*/1883private Method getMostSpecificMethodFromAllInterfacesOfCurrentClass(HashMap<Class<?>, HashMap<MethodInfo, MethodInfo>> infoCache,1884Method potentialCandidate, String name, Class<?>... parameterTypes)1885{1886Method bestMethod = potentialCandidate;1887/* if infoCache is passed in, reuse from superclass */1888if (null == infoCache) {1889infoCache = new HashMap<>(16);1890}1891HashMap<MethodInfo, MethodInfo> methodCandidates = getMethodSet(infoCache, false, true);18921893for (MethodInfo mi : methodCandidates.values()) {1894if (null == mi.jlrMethods) {1895bestMethod = getMostSpecificInterfaceMethod(name, parameterTypes, bestMethod, mi.me);1896} else {1897for (Method m: mi.jlrMethods) {1898bestMethod = getMostSpecificInterfaceMethod(name, parameterTypes, bestMethod, m);1899/*[IF JAVA_SPEC_VERSION == 8]*/1900// Java 8 returns any matching method found1901if (bestMethod != null) {1902break;1903}1904/*[ENDIF] JAVA_SPEC_VERSION == 8 */1905}1906}1907/*[IF JAVA_SPEC_VERSION == 8]*/1908if (bestMethod != null) {1909break;1910}1911/*[ENDIF] JAVA_SPEC_VERSION == 8 */1912}19131914return bestMethod;19151916}19171918private static Method getMostSpecificInterfaceMethod(String name, Class<?>[] parameterTypes, Method bestMethod, Method candidateMethod) {1919if (candidateMethod == bestMethod) {1920return bestMethod;1921}19221923/* match name and parameters to user specification */1924if (!candidateMethod.getDeclaringClass().isInterface()1925|| !candidateMethod.getName().equals(name)1926|| !doParameterTypesMatch(candidateMethod.getParameterTypes(), parameterTypes)1927) {1928return bestMethod;1929}19301931if (null == bestMethod) {1932bestMethod = candidateMethod;1933return bestMethod;1934}19351936Class<?> bestRetType = bestMethod.getReturnType();1937Class<?> candidateRetType = candidateMethod.getReturnType();19381939if (bestRetType == candidateRetType) {1940int bestModifiers = bestMethod.getModifiers();1941int candidateModifiers = candidateMethod.getModifiers();1942Class<?> bestDeclaringClass = bestMethod.getDeclaringClass();1943Class<?> candidateDeclaringClass = candidateMethod.getDeclaringClass();1944/* if all return types end up being the same, non-static methods take priority over static methods and sub-interfaces take1945priority over superinterface */1946if ((Modifier.isStatic(bestModifiers) && !Modifier.isStatic(candidateModifiers))1947|| methodAOverridesMethodB(candidateDeclaringClass, Modifier.isAbstract(candidateModifiers), candidateDeclaringClass.isInterface(),1948bestDeclaringClass, Modifier.isAbstract(bestModifiers), bestDeclaringClass.isInterface())1949) {1950bestMethod = candidateMethod;1951}1952} else {1953/* resulting method should have the most specific return type */1954if (bestRetType.isAssignableFrom(candidateRetType)) {1955bestMethod = candidateMethod;1956}1957}19581959return bestMethod;1960}19611962private static boolean doParameterTypesMatch(Class<?>[] paramList1, Class<?>[] paramList2) {1963if (paramList1.length != paramList2.length) return false;19641965for (int index = 0; index < paramList1.length; index++) {1966if (!paramList1[index].equals(paramList2[index])) {1967return false;1968}1969}19701971return true;1972}19731974/**1975* Answers a Method object which represents the first method found matching1976* the arguments.1977*1978* @param name String1979* the name of the method1980* @param parameterTypes Class<?>[]1981* the types of the arguments.1982* @param partialSignature String1983* the signature of the method, without return type.1984* @return Object1985* the first Method found matching the arguments1986*1987* @see #getMethods1988*/1989private native Method getMethodImpl(String name, Class<?>[] parameterTypes, String partialSignature);19901991/**1992* Answers an array containing Method objects describing1993* all methods which are visible from the current execution1994* context.1995*1996* @return Method[]1997* all visible methods starting from the receiver.1998* @throws SecurityException1999* if member access is not allowed2000*2001* @see #getDeclaredMethods2002*/2003@CallerSensitive2004public Method[] getMethods() throws SecurityException {2005@SuppressWarnings("removal")2006SecurityManager security = System.getSecurityManager();2007if (security != null) {2008ClassLoader callerClassLoader = ClassLoader.getStackClassLoader(1);2009checkMemberAccess(security, callerClassLoader, Member.PUBLIC);2010}20112012Method[] methods;20132014/*[PR CMVC 114820, CMVC 115873, CMVC 116166] add reflection cache */2015methods = lookupCachedMethods(CacheKey.PublicMethodsKey);2016if (methods != null) {2017return methods;2018}20192020if(isPrimitive()) {2021return new Method[0];2022}20232024/*[PR CMVC 192714,194493] prepare the class before attempting to access members */2025J9VMInternals.prepare(this);2026HashMap<Class<?>, HashMap<MethodInfo, MethodInfo>> infoCache = new HashMap<>(16);2027HashMap<MethodInfo, MethodInfo> myMethods = getMethodSet(infoCache, false, false);2028ArrayList<Method> myMethodList = new ArrayList<>(16);2029for (MethodInfo mi: myMethods.values()) { /* don't know how big this will be at the start */2030if (null == mi.jlrMethods) {2031myMethodList.add(mi.me);2032} else {2033for (Method m: mi.jlrMethods) {2034myMethodList.add(m);2035}2036}2037}2038methods = myMethodList.toArray(new Method[myMethodList.size()]);2039return cacheMethods(Reflection.filterMethods(this, methods), CacheKey.PublicMethodsKey);2040}20412042private HashMap<MethodInfo, MethodInfo> getMethodSet(2043HashMap<Class<?>, HashMap<MethodInfo, MethodInfo>> infoCache,2044boolean virtualOnly, boolean localInterfacesOnly) {2045/* virtualOnly must be false only for the bottom class of the hierarchy */2046HashMap<MethodInfo, MethodInfo> myMethods = infoCache.get(this);2047if (null == myMethods) {2048/* haven't visited this class. Initialize with the methods from the VTable which take priority */2049myMethods = new HashMap<>(16);2050if (!isInterface() && !localInterfacesOnly) {2051int vCount = 0;2052int sCount = 0;2053Method methods[] = null; /* this includes the superclass's virtual and static methods. */2054Set<MethodInfo> methodFilter = null;2055boolean noHotswap = true;2056do {2057/* atomically get the list of methods, iterate if a hotswap occurred */2058vCount = getVirtualMethodCountImpl(); /* returns only public methods */2059sCount = getStaticMethodCountImpl();2060methods = (Method[])Method.class.allocateAndFillArray(vCount + sCount);2061if (null == methods) {2062throw new Error("Error retrieving class methods"); //$NON-NLS-1$2063}2064noHotswap = (getVirtualMethodsImpl(methods, 0, vCount) && getStaticMethodsImpl(methods, vCount, sCount));2065} while (!noHotswap);2066/* if we are here, this is the target class, so return static and virtual methods */2067boolean scanInterfaces = false;2068for (Method m: methods) {2069Class<?> mDeclaringClass = m.getDeclaringClass();2070MethodInfo mi = new MethodInfo(m);2071MethodInfo prevMI = myMethods.put(mi, mi);2072if (prevMI != null) {2073/* As per Java spec:2074* For methods with same signature (name, parameter types) and return type,2075* only the most specific method should be selected.2076* Method N is more specific than M if:2077* N is declared by a class and M is declared by an interface; or2078* N and M are both declared by either classes or interfaces and N's2079* declaring type is the same as or a subtype of M's declaring type.2080*/2081Class<?> prevMIDeclaringClass = prevMI.me.getDeclaringClass();2082if ((mDeclaringClass.isInterface() && !prevMIDeclaringClass.isInterface())2083|| (mDeclaringClass.isAssignableFrom(prevMIDeclaringClass))2084) {2085myMethods.put(prevMI, prevMI);2086}2087}2088if (mDeclaringClass.isInterface()) {2089scanInterfaces = true;2090/* Add all the interfaces at once to preserve ordering */2091myMethods.remove(mi, mi);2092}2093}2094if (scanInterfaces) {2095/* methodFilter is guaranteed to be non-null at this point */2096addInterfaceMethods(infoCache, methodFilter, myMethods, localInterfacesOnly);2097}2098} else {2099if (!localInterfacesOnly || isInterface()) {2100/* this is an interface and doesn't have a vTable, but may have static or private methods */2101for (Method m: getDeclaredMethods()) {2102int methodModifiers = m.getModifiers();2103if ((virtualOnly && Modifier.isStatic(methodModifiers)) || !Modifier.isPublic(methodModifiers)){2104continue;2105}2106MethodInfo mi = new MethodInfo(m);2107myMethods.put(mi, mi);2108}2109}2110addInterfaceMethods(infoCache, null, myMethods, localInterfacesOnly);2111}2112infoCache.put(this, myMethods); /* save results for future use */2113}2114return myMethods;2115}21162117/**2118* Add methods defined in this class's interfaces or those of superclasses2119* @param infoCache Cache of previously visited method lists2120* @param methodFilter List of methods to include. If null, include all2121* @param myMethods non-null if you want to update an existing list2122* @return list of methods with their various declarations2123*/2124private HashMap<MethodInfo, MethodInfo> addInterfaceMethods(2125HashMap<Class<?>, HashMap<MethodInfo, MethodInfo>> infoCache,2126Set<MethodInfo> methodFilter,2127HashMap<MethodInfo, MethodInfo> myMethods, boolean localInterfacesOnly) {2128boolean addToCache = false;2129boolean updateList = (null != myMethods);2130if (!updateList) {2131myMethods = infoCache.get(this);2132}2133if (null == myMethods) {2134/* haven't visited this class */2135myMethods = new HashMap<>();2136addToCache = true;2137updateList = true;2138}2139if (updateList) {2140Class mySuperclass = getSuperclass();2141if (!isInterface() && (Object.class != mySuperclass)) {2142/* some interface methods are visible via the superclass */2143HashMap<MethodInfo, MethodInfo> superclassMethods = mySuperclass.addInterfaceMethods(infoCache, methodFilter, null, localInterfacesOnly);2144for (MethodInfo otherInfo: superclassMethods.values()) {2145if ((null == methodFilter) || methodFilter.contains(otherInfo)) {2146addMethod(myMethods, otherInfo);2147}2148}2149}2150for (Class intf: getInterfaces()) {2151HashMap<MethodInfo, MethodInfo> intfMethods = intf.getMethodSet(infoCache, true, localInterfacesOnly);2152for (MethodInfo otherInfo: intfMethods.values()) {2153if ((null == methodFilter) || methodFilter.contains(otherInfo)) {2154addMethod(myMethods, otherInfo);2155}2156}2157}2158}2159if (addToCache) {2160infoCache.put(this, myMethods);2161/* save results for future use */2162}2163return myMethods;2164}21652166/* this is called only to add methods from implemented interfaces of a class or superinterfaces of an interface */2167private void addMethod(HashMap<MethodInfo, MethodInfo> myMethods, MethodInfo otherMi) {2168MethodInfo oldMi = myMethods.get(otherMi);2169if (null == oldMi) {2170/* haven't seen this method's name & sig */2171oldMi = new MethodInfo(otherMi);2172/* create a new MethodInfo object and add mi's Method objects to it */2173myMethods.put(oldMi, oldMi);2174} else {2175/* NB: the vTable has an abstract method for each method declared in the implemented interfaces */2176oldMi.update(otherMi); /* add the new method as appropriate */2177}2178}21792180private native int getVirtualMethodCountImpl();2181private native boolean getVirtualMethodsImpl(Method[] array, int start, int count);2182private native int getStaticMethodCountImpl();2183private native boolean getStaticMethodsImpl(Method[] array, int start, int count);2184private native Object[] allocateAndFillArray(int size);21852186/**2187* Answers an integer which is the receiver's modifiers.2188* Note that the constants which describe the bits which are2189* returned are implemented in class java.lang.reflect.Modifier2190* which may not be available on the target.2191*2192* @return the receiver's modifiers2193*/2194public int getModifiers() {2195/*[PR CMVC 89071, 89373] Return SYNTHETIC, ANNOTATION, ENUM modifiers */2196int rawModifiers = getModifiersImpl();2197if (isArray()) {2198rawModifiers &= Modifier.PUBLIC | Modifier.PRIVATE | Modifier.PROTECTED |2199Modifier.ABSTRACT | Modifier.FINAL;2200} else {2201rawModifiers &= Modifier.PUBLIC | Modifier.PRIVATE | Modifier.PROTECTED |2202Modifier.STATIC | Modifier.FINAL | Modifier.INTERFACE |2203Modifier.ABSTRACT | SYNTHETIC | ENUM | ANNOTATION;2204}2205return rawModifiers;2206}22072208private native int getModifiersImpl();22092210/*[IF Sidecar19-SE]*/2211/**2212* Answers the module to which the receiver belongs.2213* If this class doesn't belong to a named module, the unnamedModule of the classloader2214* loaded this class is returned;2215* If this class represents an array type, the module for the element type is returned;2216* If this class represents a primitive type or void, module java.base is returned.2217*2218* @return the module to which the receiver belongs2219*/2220public Module getModule()2221{2222return module;2223}2224/*[ENDIF] Sidecar19-SE */22252226/**2227* Answers the name of the class which the receiver represents.2228* For a description of the format which is used, see the class2229* definition of java.lang.Class.2230*2231* @return the receiver's name.2232*2233* @see java.lang.Class2234*/2235public String getName() {2236/*[PR CMVC 105714] Remove classNameMap (PR 115275) and always use getClassNameStringImpl() */2237String name = classNameString;2238if (name != null){2239return name;2240}2241//must have been null to set it2242return VM.getClassNameImpl(this, true);2243}22442245/**2246* Answers the ProtectionDomain of the receiver.2247* <p>2248* Note: In order to conserve space in embedded targets, we allow this2249* method to answer null for classes in the system protection domain2250* (i.e. for system classes). System classes are always given full2251* permissions (i.e. AllPermission). This is not changeable via the2252* java.security.Policy.2253*2254* @return ProtectionDomain2255* the receiver's ProtectionDomain.2256*2257* @see java.lang.Class2258*/2259public ProtectionDomain getProtectionDomain() {2260@SuppressWarnings("removal")2261SecurityManager security = System.getSecurityManager();2262if (security != null) {2263security.checkPermission(sun.security.util.SecurityConstants.GET_PD_PERMISSION);2264}2265return getProtectionDomainInternal();2266}22672268ProtectionDomain getProtectionDomainInternal() {2269ProtectionDomain result = getPDImpl();2270if (result != null) {2271return result;2272}2273if (AllPermissionsPD == null) {2274allocateAllPermissionsPD();2275}2276return AllPermissionsPD;2277}22782279private void allocateAllPermissionsPD() {2280Permissions collection = new Permissions();2281collection.add(sun.security.util.SecurityConstants.ALL_PERMISSION);2282AllPermissionsPD = new ProtectionDomain(null, collection);2283}22842285/**2286* Answers the ProtectionDomain of the receiver.2287* <p>2288* This method is for internal use only.2289*2290* @return ProtectionDomain2291* the receiver's ProtectionDomain.2292*2293* @see java.lang.Class2294*/2295ProtectionDomain getPDImpl() {2296/*[PR CMVC 125822] Move RAM class fields onto the heap to fix hotswap crash */2297return protectionDomain;2298}22992300/**2301* Helper method to get the name of the package of incoming non-array class.2302* returns an empty string if the class is in an unnamed package.2303*2304* @param clz a non-array class.2305* @return the package name of incoming non-array class.2306*/2307private static String getNonArrayClassPackageName(Class<?> clz) {2308String name = clz.getName();2309int index = name.lastIndexOf('.');2310if (index >= 0) {2311return name.substring(0, index).intern();2312}2313return ""; //$NON-NLS-1$2314}23152316/**2317* Answers the name of the package to which the receiver belongs.2318* For example, Object.class.getPackageName() returns "java.lang".2319* Returns "java.lang" if this class represents a primitive type or void,2320* and the element type's package name in the case of an array type.2321*2322* @return String the receiver's package name2323*2324* @see #getPackage2325*/2326/*[IF Sidecar19-SE]*/2327public2328/*[ENDIF] Sidecar19-SE */2329String getPackageName() {2330String packageName = this.packageNameString;2331if (null == packageName) {2332/*[IF Sidecar19-SE]*/2333if (isPrimitive()) {2334packageName = "java.lang"; //$NON-NLS-1$2335} else if (isArray()) {2336Class<?> componentType = getComponentType();2337while (componentType.isArray()) {2338componentType = componentType.getComponentType();2339}2340if (componentType.isPrimitive()) {2341packageName = "java.lang"; //$NON-NLS-1$2342} else {2343packageName = getNonArrayClassPackageName(componentType);2344}2345} else {2346packageName = getNonArrayClassPackageName(this);2347}2348/*[ELSE] Sidecar19-SE */2349packageName = getNonArrayClassPackageName(this);2350/*[ENDIF] Sidecar19-SE */2351this.packageNameString = packageName;2352}2353return packageName;2354}23552356/**2357* Answers a URL referring to the2358* resource specified by resName. The mapping between2359* the resource name and the URL is managed by the2360* class's class loader.2361*2362* @param resName the name of the resource.2363* @return a stream on the resource.2364*2365* @see java.lang.ClassLoader2366*/2367/*[IF Sidecar19-SE]*/2368@CallerSensitive2369/*[ENDIF] Sidecar19-SE */2370public URL getResource(String resName) {2371ClassLoader loader = this.getClassLoaderImpl();2372String absoluteResName = this.toResourceName(resName);2373URL result = null;2374/*[IF Sidecar19-SE]*/2375Module thisModule = getModule();2376if (useModularSearch(absoluteResName, thisModule, System.getCallerClass())) {2377try {2378result = loader.findResource(thisModule.getName(), absoluteResName);2379} catch (IOException e) {2380return null;2381}2382}2383if (null == result)2384/*[ENDIF] Sidecar19-SE */2385{2386if (loader == ClassLoader.bootstrapClassLoader) {2387result =ClassLoader.getSystemResource(absoluteResName);2388} else {2389result =loader.getResource(absoluteResName);2390}2391}2392return result;2393}23942395/**2396* Answers a read-only stream on the contents of the2397* resource specified by resName. The mapping between2398* the resource name and the stream is managed by the2399* class's class loader.2400*2401* @param resName the name of the resource.2402* @return a stream on the resource.2403*2404* @see java.lang.ClassLoader2405*/2406/*[IF Sidecar19-SE]*/2407@CallerSensitive2408/*[ENDIF] Sidecar19-SE */2409public InputStream getResourceAsStream(String resName) {2410ClassLoader loader = this.getClassLoaderImpl();2411String absoluteResName = this.toResourceName(resName);2412InputStream result = null;2413/*[IF Sidecar19-SE]*/2414Module thisModule = getModule();24152416if (useModularSearch(absoluteResName, thisModule, System.getCallerClass())) {2417try {2418result = thisModule.getResourceAsStream(absoluteResName);2419} catch (IOException e) {2420return null;2421}2422}2423if (null == result)2424/*[ENDIF] Sidecar19-SE */2425{2426if (loader == ClassLoader.bootstrapClassLoader) {2427result = ClassLoader.getSystemResourceAsStream(absoluteResName);2428} else {2429result = loader.getResourceAsStream(absoluteResName);2430}2431}2432return result;2433}24342435/*[IF Sidecar19-SE]*/2436/**2437* Indicate if the package should be looked up in a module or via the class path.2438* Look up the resource in the module if the module is named2439* and is the same module as the caller or the package is open to the caller.2440* The default package (i.e. resources at the root of the module) is considered open.2441*2442* @param absoluteResName name of resource, including package2443* @param thisModule module of the current class2444* @param callerClass class of method calling getResource() or getResourceAsStream()2445* @return true if modular lookup should be used.2446*/2447private boolean useModularSearch(String absoluteResName, Module thisModule, Class<?> callerClass) {2448boolean visible = false;24492450if (thisModule.isNamed()) {2451// When the caller class is null, assuming it is loaded by module java.base.2452// See https://github.com/eclipse-openj9/openj9/issues/8993 for more info.2453final Module callerModule = callerClass == null ? Class.class.getModule() : callerClass.getModule();2454visible = (thisModule == callerModule);2455if (!visible) {2456visible = absoluteResName.endsWith(".class"); //$NON-NLS-1$2457if (!visible) {2458// extract the package name2459int lastSlash = absoluteResName.lastIndexOf('/');2460if (-1 == lastSlash) { // no package name2461visible = true;2462} else {2463String result = absoluteResName.substring(0, lastSlash).replace('/', '.');2464visible = thisModule.isOpen(result, callerModule);2465}2466}2467}2468}2469return visible;2470}2471/*[ENDIF] Sidecar19-SE */247224732474/**2475* Answers a String object which represents the class's2476* signature, as described in the class definition of2477* java.lang.Class.2478*2479* @return the signature of the class.2480*2481* @see java.lang.Class2482*/2483private String getSignature() {2484if(isArray()) return getName(); // Array classes are named with their signature2485if(isPrimitive()) {2486// Special cases for each base type.2487if(this == void.class) return "V"; //$NON-NLS-1$2488if(this == boolean.class) return "Z"; //$NON-NLS-1$2489if(this == byte.class) return "B"; //$NON-NLS-1$2490if(this == char.class) return "C"; //$NON-NLS-1$2491if(this == short.class) return "S"; //$NON-NLS-1$2492if(this == int.class) return "I"; //$NON-NLS-1$2493if(this == long.class) return "J"; //$NON-NLS-1$2494if(this == float.class) return "F"; //$NON-NLS-1$2495if(this == double.class) return "D"; //$NON-NLS-1$2496}24972498// General case.2499// Create a buffer of the correct size2500String name = getName();2501return new StringBuilder(name.length() + 2).2502append('L').append(name).append(';').toString();2503}25042505/**2506* Answers the signers for the class represented by the2507* receiver, or null if there are no signers.2508*2509* @return the signers of the receiver.2510*2511* @see #getMethods2512*/2513public Object[] getSigners() {2514/*[PR CMVC 93861] allow setSigners() for bootstrap classes */2515return getClassLoaderImpl().getSigners(this);2516}25172518/**2519* Answers the Class which represents the receiver's2520* superclass. For Classes which represent base types,2521* interfaces, and for java.lang.Object the method2522* answers null.2523*2524* @return the receiver's superclass.2525*/2526public Class<? super T> getSuperclass()2527{2528return J9VMInternals.getSuperclass(this);2529}25302531/**2532* Answers true if the receiver represents an array class.2533*2534* @return <code>true</code>2535* if the receiver represents an array class2536* <code>false</code>2537* if it does not represent an array class2538*/2539public native boolean isArray();25402541/**2542* Answers true if the type represented by the argument2543* can be converted via an identity conversion or a widening2544* reference conversion (i.e. if either the receiver or the2545* argument represent primitive types, only the identity2546* conversion applies).2547*2548* @return <code>true</code>2549* the argument can be assigned into the receiver2550* <code>false</code>2551* the argument cannot be assigned into the receiver2552* @param cls Class2553* the class to test2554* @throws NullPointerException2555* if the parameter is null2556*2557*/2558public native boolean isAssignableFrom(Class<?> cls);25592560/**2561* Answers true if the argument is non-null and can be2562* cast to the type of the receiver. This is the runtime2563* version of the <code>instanceof</code> operator.2564*2565* @return <code>true</code>2566* the argument can be cast to the type of the receiver2567* <code>false</code>2568* the argument is null or cannot be cast to the2569* type of the receiver2570*2571* @param object Object2572* the object to test2573*/2574public native boolean isInstance(Object object);25752576/**2577* Answers true if the receiver represents an interface.2578*2579* @return <code>true</code>2580* if the receiver represents an interface2581* <code>false</code>2582* if it does not represent an interface2583*/2584public boolean isInterface() {2585// This code has been inlined in toGenericString. toGenericString2586// must be modified to reflect any changes to this implementation.2587return !isArray() && (getModifiersImpl() & 512 /* AccInterface */) != 0;2588}25892590/**2591* Answers true if the receiver represents a base type.2592*2593* @return <code>true</code>2594* if the receiver represents a base type2595* <code>false</code>2596* if it does not represent a base type2597*/2598public native boolean isPrimitive();25992600/*[IF INLINE-TYPES]*/2601/**2602* Answers true if the receiver represents a primitive class type. Array classes2603* return false.2604*2605* @return true if receiver is primitive class type, and false otherwise.2606*/2607public native boolean isPrimitiveClass();26082609/**2610* Answers true if the receiver represents a value class type. Array classes2611* return false.2612*2613* @return true if receiver is a value class type, and false otherwise.2614*/2615public native boolean isValue();26162617/**2618* ToDo: add comments for public methods - https://github.com/eclipse-openj9/openj9/issues/136152619*/2620public Class<?> asPrimaryType() {2621// ToDo: this is a temporary implementation - https://github.com/eclipse-openj9/openj9/issues/136152622return this;2623}2624public Class<?> asValueType() {2625// ToDo: this is a temporary implementation - https://github.com/eclipse-openj9/openj9/issues/136152626return this;2627}2628public boolean isPrimaryType() {2629// ToDo: this is a temporary implementation - https://github.com/eclipse-openj9/openj9/issues/136152630return true;2631}2632public boolean isPrimitiveValueType() {2633// ToDo: this is a temporary implementation - https://github.com/eclipse-openj9/openj9/issues/136152634return false;2635}2636/*[ENDIF] INLINE-TYPES */26372638/**2639* Answers a new instance of the class represented by the2640* receiver, created by invoking the default (i.e. zero-argument)2641* constructor. If there is no such constructor, or if the2642* creation fails (either because of a lack of available memory or2643* because an exception is thrown by the constructor), an2644* InstantiationException is thrown. If the default constructor2645* exists, but is not accessible from the context where this2646* message is sent, an IllegalAccessException is thrown.2647*2648* @return a new instance of the class represented by the receiver.2649* @throws IllegalAccessException if the constructor is not visible to the sender.2650* @throws InstantiationException if the instance could not be created.2651*/2652@CallerSensitive2653/*[IF Sidecar19-SE]*/2654@Deprecated(forRemoval=false, since="9")2655/*[ENDIF]*/2656public T newInstance() throws IllegalAccessException, InstantiationException {2657@SuppressWarnings("removal")2658SecurityManager security = System.getSecurityManager();2659if (security != null) {2660ClassLoader callerClassLoader = ClassLoader.getStackClassLoader(1);2661checkNonSunProxyMemberAccess(security, callerClassLoader, Member.PUBLIC);2662}26632664/*[IF JAVA_SPEC_VERSION >= 12]*/2665Class<?> callerClazz = getStackClass(1);2666if (callerClazz.classLoader == ClassLoader.bootstrapClassLoader) {2667/* newInstanceImpl() is required for all bootstrap classes to avoid an infinite loop2668* when calling copyConstructor.invoke() in cacheConstructor() at the bootstrap stage2669* as the constructors of bootstrap classes are not yet cached for use at that time.2670*/2671return (T)J9VMInternals.newInstanceImpl(this);2672} else {2673try {2674Constructor<?> ctr = getDeclaredConstructor();2675reflectionFactory = getReflectionFactory();2676return (T)reflectionFactory.newInstance(ctr, null, callerClazz);2677} catch (NoSuchMethodException e) {2678InstantiationException instantiationEx = new InstantiationException();2679throw (InstantiationException)instantiationEx.initCause(e);2680} catch (InvocationTargetException e) {2681getUnsafe().throwException(e.getCause());2682return null; //unreachable but required in compilation2683}2684}2685/*[ELSE] JAVA_SPEC_VERSION >= 12*/2686return (T)J9VMInternals.newInstanceImpl(this);2687/*[ENDIF] JAVA_SPEC_VERSION >= 12*/2688}26892690/**2691* Used as a prototype for the jit.2692*2693* @param callerClass2694* @return the object2695* @throws InstantiationException2696*/2697/*[PR CMVC 114139]InstantiationException has wrong detail message */2698private Object newInstancePrototype(Class<?> callerClass) throws InstantiationException {2699/*[PR 96623]*/2700throw new InstantiationException(this);2701}270227032704/**2705* Answers a string describing a path to the receiver's appropriate2706* package specific subdirectory, with the argument appended if the2707* argument did not begin with a slash. If it did, answer just the2708* argument with the leading slash removed.2709*2710* @return String2711* the path to the resource.2712* @param resName String2713* the name of the resource.2714*2715* @see #getResource2716* @see #getResourceAsStream2717*/2718private String toResourceName(String resName) {2719// Turn package name into a directory path2720if (resName.length() > 0 && resName.charAt(0) == '/')2721return resName.substring(1);27222723Class<?> thisObject = this;2724while (thisObject.isArray()) {2725thisObject = thisObject.getComponentType();2726}27272728String qualifiedClassName = thisObject.getName();2729int classIndex = qualifiedClassName.lastIndexOf('.');2730if (classIndex == -1) return resName; // from a default package2731return qualifiedClassName.substring(0, classIndex + 1).replace('.', '/') + resName;2732}27332734/**2735* Answers a string containing a concise, human-readable2736* description of the receiver.2737*2738* @return a printable representation for the receiver.2739*/2740@Override2741public String toString() {2742// Note change from 1.1.7 to 1.2: For primitive types,2743// return just the type name.2744if (isPrimitive()) return getName();2745return (isInterface() ? "interface " : "class ") + getName(); //$NON-NLS-1$ //$NON-NLS-2$2746}27472748/**2749* Returns a formatted string describing this Class. The string has2750* the following format:2751* <i>modifier1 modifier2 ... kind name<typeparam1, typeparam2, ...></i>.2752* kind is one of <code>class</code>, <code>enum</code>, <code>interface</code>,2753* <code>@interface</code>, or2754* the empty string for primitive types. The type parameter list is2755* omitted if there are no type parameters.2756/*[IF Sidecar19-SE]2757* For array classes, the string has the following format instead:2758* <i>name<typeparam1, typeparam2, ...></i> followed by a number of2759* <code>[]</code> pairs, one pair for each dimension of the array.2760/*[ENDIF]2761*2762* @return a formatted string describing this class2763* @since 1.82764*/2765public String toGenericString() {2766if (isPrimitive()) return getName();27672768StringBuilder result = new StringBuilder();2769int modifiers = getModifiers();27702771// Checks for isInterface, isAnnotation and isEnum have been inlined2772// in order to avoid multiple calls to isArray and getModifiers2773boolean isArray = isArray();2774boolean isInterface = !isArray && (0 != (modifiers & Modifier.INTERFACE));27752776// Get kind of type before modifying the modifiers2777String kindOfType;2778if ((!isArray) && ((modifiers & ANNOTATION) != 0)) {2779kindOfType = "@interface "; //$NON-NLS-1$2780} else if (isInterface) {2781kindOfType = "interface "; //$NON-NLS-1$2782} else if ((!isArray) && ((modifiers & ENUM) != 0) && (getSuperclass() == Enum.class)) {2783kindOfType = "enum "; //$NON-NLS-1$2784/*[IF JAVA_SPEC_VERSION >= 14]*/2785} else if (isRecord()) {2786kindOfType = "record "; //$NON-NLS-1$2787/*[ENDIF] JAVA_SPEC_VERSION >= 14 */2788} else {2789kindOfType = "class "; //$NON-NLS-1$2790}27912792// Remove "interface" from modifiers (is included as kind of type)2793if (isInterface) {2794modifiers -= Modifier.INTERFACE;2795}27962797// Build generic string2798/*[IF Sidecar19-SE]*/2799if (isArray) {2800int depth = 0;2801Class inner = this;2802Class component = this;2803do {2804inner = inner.getComponentType();2805if (inner != null) {2806component = inner;2807depth += 1;2808}2809} while (inner != null);2810result.append(component.getName());2811component.appendTypeParameters(result);2812for (int i = 0; i < depth; i++) {2813result.append('[').append(']');2814}2815return result.toString();2816}2817/*[ENDIF]*/2818result.append(Modifier.toString(modifiers));2819if (result.length() > 0) {2820result.append(' ');2821}2822result.append(kindOfType);2823result.append(getName());28242825appendTypeParameters(result);2826return result.toString();2827}28282829// Add type parameters to stringbuilder if present2830private void appendTypeParameters(StringBuilder nameBuilder) {2831TypeVariable<?>[] typeVariables = getTypeParameters();2832if (0 != typeVariables.length) {2833nameBuilder.append('<');2834boolean comma = false;2835for (TypeVariable<?> t : typeVariables) {2836if (comma) nameBuilder.append(',');2837nameBuilder.append(t);2838comma = true;2839/*[IF JAVA_SPEC_VERSION >= 12]*/2840Type[] types = t.getBounds();2841if (types.length == 1 && types[0].equals(Object.class)) {2842// skip in case the only bound is java.lang.Object2843} else {2844String prefix = " extends "; //$NON-NLS-1$2845for (Type type : types) {2846nameBuilder.append(prefix).append(type.getTypeName());2847prefix = " & "; //$NON-NLS-1$2848}2849}2850/*[ENDIF] JAVA_SPEC_VERSION >= 12 */2851}2852nameBuilder.append('>');2853}2854}28552856/**2857* Returns the Package of which this class is a member.2858* A class has a Package iff it was loaded from a SecureClassLoader.2859*2860* @return Package the Package of which this class is a member2861* or null in the case of primitive or array types2862*/2863public Package getPackage() {2864if (isArray() || isPrimitive()) {2865return null;2866}2867String packageName = getPackageName();2868if (null == packageName) {2869return null;2870} else {2871/*[IF Sidecar19-SE]*/2872if (this.classLoader == ClassLoader.bootstrapClassLoader) {2873return jdk.internal.loader.BootLoader.getDefinedPackage(packageName);2874} else {2875return getClassLoaderImpl().getDefinedPackage(packageName);2876}2877/*[ELSE]2878return getClassLoaderImpl().getPackage(packageName);2879/*[ENDIF]*/2880}2881}28822883static Class<?> getPrimitiveClass(String name) {2884if (name.equals("float")) //$NON-NLS-1$2885return new float[0].getClass().getComponentType();2886if (name.equals("double")) //$NON-NLS-1$2887return new double[0].getClass().getComponentType();2888if (name.equals("int")) //$NON-NLS-1$2889return new int[0].getClass().getComponentType();2890if (name.equals("long")) //$NON-NLS-1$2891return new long[0].getClass().getComponentType();2892if (name.equals("char")) //$NON-NLS-1$2893return new char[0].getClass().getComponentType();2894if (name.equals("byte")) //$NON-NLS-1$2895return new byte[0].getClass().getComponentType();2896if (name.equals("boolean")) //$NON-NLS-1$2897return new boolean[0].getClass().getComponentType();2898if (name.equals("short")) //$NON-NLS-1$2899return new short[0].getClass().getComponentType();2900if (name.equals("void")) { //$NON-NLS-1$2901try {2902java.lang.reflect.Method method = Runnable.class.getMethod("run", EmptyParameters); //$NON-NLS-1$2903return method.getReturnType();2904} catch (Exception e) {2905com.ibm.oti.vm.VM.dumpString("Cannot initialize Void.TYPE\n"); //$NON-NLS-1$2906}2907}2908throw new Error("Unknown primitive type: " + name); //$NON-NLS-1$2909}29102911/**2912* Returns the assertion status for this class.2913* Assertion is enabled/disabled based on2914* classloader default, package or class default at runtime2915*2916* @since 1.42917*2918* @return the assertion status for this class2919*/2920public boolean desiredAssertionStatus() {2921ClassLoader cldr = getClassLoaderImpl();2922if (cldr != null) {2923/*[PR CMVC 80253] package assertion status not checked */2924return cldr.getClassAssertionStatus(getName());2925}2926return false;2927}29282929/**2930* Answer the class at depth.2931*2932* Notes:2933* 1) This method operates on the defining classes of methods on stack.2934* NOT the classes of receivers.2935*2936* 2) The item at index zero describes the caller of this method.2937*2938* @param depth2939* @return the class at the given depth2940*/2941@CallerSensitive2942static final native Class<?> getStackClass(int depth);29432944/**2945* Walk the stack and answer an array containing the maxDepth2946* most recent classes on the stack of the calling thread.2947*2948* Starting with the caller of the caller of getStackClasses(), return an2949* array of not more than maxDepth Classes representing the classes of2950* running methods on the stack (including native methods). Frames2951* representing the VM implementation of java.lang.reflect are not included2952* in the list. If stopAtPrivileged is true, the walk will terminate at any2953* frame running one of the following methods:2954*2955* <code><ul>2956* <li>java/security/AccessController.doPrivileged(Ljava/security/PrivilegedAction;)Ljava/lang/Object;</li>2957* <li>java/security/AccessController.doPrivileged(Ljava/security/PrivilegedExceptionAction;)Ljava/lang/Object;</li>2958* <li>java/security/AccessController.doPrivileged(Ljava/security/PrivilegedAction;Ljava/security/AccessControlContext;)Ljava/lang/Object;</li>2959* <li>java/security/AccessController.doPrivileged(Ljava/security/PrivilegedExceptionAction;Ljava/security/AccessControlContext;)Ljava/lang/Object;</li>2960* </ul></code>2961*2962* If one of the doPrivileged methods is found, the walk terminate and that frame is NOT included in the returned array.2963*2964* Notes: <ul>2965* <li> This method operates on the defining classes of methods on stack.2966* NOT the classes of receivers. </li>2967*2968* <li> The item at index zero in the result array describes the caller of2969* the caller of this method. </li>2970*</ul>2971*2972* @param maxDepth maximum depth to walk the stack, -1 for the entire stack2973* @param stopAtPrivileged stop at privileged classes2974* @return the array of the most recent classes on the stack2975*/2976@CallerSensitive2977static final native Class<?>[] getStackClasses(int maxDepth, boolean stopAtPrivileged);297829792980/**2981* Called from JVM_ClassDepth.2982* Answers the index in the stack of the first method which2983* is contained in a class called <code>name</code>. If no2984* methods from this class are in the stack, return -1.2985*2986* @param name String2987* the name of the class to look for.2988* @return int2989* the depth in the stack of a the first2990* method found.2991*/2992@CallerSensitive2993static int classDepth (String name) {2994Class<?>[] classes = getStackClasses(-1, false);2995for (int i=1; i<classes.length; i++)2996if (classes[i].getName().equals(name))2997return i - 1;2998return -1;2999}30003001/**3002* Called from JVM_ClassLoaderDepth.3003* Answers the index in the stack of the first class3004* whose class loader is not a system class loader.3005*3006* @return the frame index of the first method whose class was loaded by a non-system class loader.3007*/3008@CallerSensitive3009static int classLoaderDepth() {3010// Now, check if there are any non-system class loaders in3011// the stack up to the first privileged method (or the end3012// of the stack.3013Class<?>[] classes = getStackClasses(-1, true);3014for (int i=1; i<classes.length; i++) {3015ClassLoader cl = classes[i].getClassLoaderImpl();3016if (!cl.isASystemClassLoader()) return i - 1;3017}3018return -1;3019}30203021/**3022* Called from JVM_CurrentClassLoader.3023* Answers the class loader of the first class in the stack3024* whose class loader is not a system class loader.3025*3026* @return the most recent non-system class loader.3027*/3028@CallerSensitive3029static ClassLoader currentClassLoader() {3030// Now, check if there are any non-system class loaders in3031// the stack up to the first privileged method (or the end3032// of the stack.3033Class<?>[] classes = getStackClasses(-1, true);3034for (int i=1; i<classes.length; i++) {3035ClassLoader cl = classes[i].getClassLoaderImpl();3036if (!cl.isASystemClassLoader()) return cl;3037}3038return null;3039}30403041/**3042* Called from JVM_CurrentLoadedClass.3043* Answers the first class in the stack which was loaded3044* by a class loader which is not a system class loader.3045*3046* @return the most recent class loaded by a non-system class loader.3047*/3048@CallerSensitive3049static Class<?> currentLoadedClass() {3050// Now, check if there are any non-system class loaders in3051// the stack up to the first privileged method (or the end3052// of the stack.3053Class<?>[] classes = getStackClasses(-1, true);3054for (int i=1; i<classes.length; i++) {3055ClassLoader cl = classes[i].getClassLoaderImpl();3056if (!cl.isASystemClassLoader()) return classes[i];3057}3058return null;3059}30603061/**3062* Return the specified Annotation for this Class. Inherited Annotations3063* are searched.3064*3065* @param annotation the Annotation type3066* @return the specified Annotation or null3067*3068* @since 1.53069*/3070public <A extends Annotation> A getAnnotation(Class<A> annotation) {3071if (annotation == null) throw new NullPointerException();3072LinkedHashMap<Class<? extends Annotation>, Annotation> map = getAnnotationCache().annotationMap;3073if (map != null) {3074return (A)map.get(annotation);3075}3076return null;3077}30783079/**3080* Return the directly declared Annotations for this Class, including the Annotations3081* inherited from superclasses.3082* If an annotation type has been included before, then next occurrences will not be included.3083*3084* Repeated annotations are not included since they will be stored in their container annotation.3085* But container annotations are included. (If a container annotation is repeatable and it is repeated,3086* then these container annotations' container annotation is included. )3087* @return an array of Annotation3088*3089* @since 1.53090*/3091public Annotation[] getAnnotations() {3092LinkedHashMap<Class<? extends Annotation>, Annotation> map = getAnnotationCache().annotationMap;3093if (map != null) {3094Collection<Annotation> annotations = map.values();3095return annotations.toArray(new Annotation[annotations.size()]);3096}3097return EMPTY_ANNOTATION_ARRAY;3098}30993100/**3101* Looks through directly declared annotations for this class, not including Annotations inherited from superclasses.3102*3103* @param annotation the Annotation to search for3104* @return directly declared annotation of specified annotation type.3105*3106* @since 1.83107*/3108public <A extends Annotation> A getDeclaredAnnotation(Class<A> annotation) {3109if (annotation == null) throw new NullPointerException();3110LinkedHashMap<Class<? extends Annotation>, Annotation> map = getAnnotationCache().directAnnotationMap;3111if (map != null) {3112return (A)map.get(annotation);3113}3114return null;3115}31163117/**3118* Return the annotated types for the implemented interfaces.3119* @return array, possibly empty, of AnnotatedTypes3120*/3121public AnnotatedType[] getAnnotatedInterfaces() {3122return TypeAnnotationParser.buildAnnotatedInterfaces(this);3123}31243125/**3126* Return the annotated superclass of this class.3127* @return null if this class is Object, an interface, a primitive type, or an array type. Otherwise return (possibly empty) AnnotatedType.3128*/3129public AnnotatedType getAnnotatedSuperclass() {3130if (this.equals(Object.class) || this.isInterface() || this.isPrimitive() || this.isArray()) {3131return null;3132}3133return TypeAnnotationParser.buildAnnotatedSupertype(this);3134}31353136/**3137* Answers the type name of the class which the receiver represents.3138*3139* @return the fully qualified type name, with brackets if an array class3140*3141* @since 1.83142*/3143@Override3144public String getTypeName() {3145if (isArray()) {3146StringBuilder nameBuffer = new StringBuilder("[]"); //$NON-NLS-1$3147Class<?> componentType = getComponentType();3148while (componentType.isArray()) {3149nameBuffer.append("[]"); //$NON-NLS-1$3150componentType = componentType.getComponentType();3151}3152nameBuffer.insert(0, componentType.getName());3153return nameBuffer.toString();3154} else {3155return getName();3156}3157}31583159/**3160* Returns the annotations only for this Class, not including Annotations inherited from superclasses.3161* It includes all the directly declared annotations.3162* Repeated annotations are not included but their container annotation does.3163*3164* @return an array of declared annotations3165*3166*3167* @since 1.53168*/3169public Annotation[] getDeclaredAnnotations() {3170LinkedHashMap<Class<? extends Annotation>, Annotation> map = getAnnotationCache().directAnnotationMap;3171if (map != null) {3172Collection<Annotation> annotations = map.values();3173return annotations.toArray(new Annotation[annotations.size()]);3174}3175return EMPTY_ANNOTATION_ARRAY;3176}31773178/**3179* Gets the specified type annotations of this class.3180* <br>3181* Terms used for annotations :<br><br>3182* Repeatable Annotation :3183* <p>An annotation which can be used more than once for the same class declaration.3184* Repeatable annotations are annotated with Repeatable annotation which tells the3185* container annotation for this repeatable annotation.</p>3186* Example3187* <pre><code>3188* {@literal @}interface ContainerAnnotation {RepeatableAnn[] value();}3189* {@literal @}Repeatable(ContainerAnnotation.class)3190* </code></pre>3191* Container Annotation:3192* <p>Container annotation stores the repeated annotations in its array-valued element.3193* Using repeatable annotations more than once makes them stored in their container annotation.3194* In this case, container annotation is visible directly on class declaration, but not the repeated annotations.</p>3195* Repeated Annotation:3196* <p>A repeatable annotation which is used more than once for the same class.</p>3197* Directly Declared Annotation :3198* <p>All non repeatable annotations are directly declared annotations.3199* As for repeatable annotations, they can be directly declared annotation if and only if they are used once.3200* Repeated annotations are not directly declared in class declaration, but their container annotation does.</p>3201*3202* -------------------------------------------------------------------------------------------------------3203*3204* <p>If the specified type is not repeatable annotation, then returned array size will be 0 or 1.3205* If specified type is repeatable annotation, then all the annotations of that type will be returned. Array size might be 0, 1 or more.</p>3206*3207* It does not search through super classes.3208*3209* @param annotationClass the annotation type to search for3210* @return array of declared annotations in the specified annotation type3211*3212* @since 1.83213*/3214public <A extends Annotation> A[] getDeclaredAnnotationsByType(Class<A> annotationClass) {3215ArrayList<A> annotationsList = internalGetDeclaredAnnotationsByType(annotationClass);3216return annotationsList.toArray((A[])Array.newInstance(annotationClass, annotationsList.size()));3217}32183219private <A extends Annotation> ArrayList<A> internalGetDeclaredAnnotationsByType(Class<A> annotationClass) {3220AnnotationCache currentAnnotationCache = getAnnotationCache();3221ArrayList<A> annotationsList = new ArrayList<>();32223223LinkedHashMap<Class<? extends Annotation>, Annotation> map = currentAnnotationCache.directAnnotationMap;3224if (map != null) {3225Repeatable repeatable = annotationClass.getDeclaredAnnotation(Repeatable.class);3226if (repeatable == null) {3227A annotation = (A)map.get(annotationClass);3228if (annotation != null) {3229annotationsList.add(annotation);3230}3231} else {3232Class<? extends Annotation> containerType = repeatable.value();3233// if the annotation and its container are both present, the order must be maintained3234for (Map.Entry<Class<? extends Annotation>, Annotation> entry : map.entrySet()) {3235Class<? extends Annotation> annotationType = entry.getKey();3236if (annotationType == annotationClass) {3237annotationsList.add((A)entry.getValue());3238} else if (annotationType == containerType) {3239A[] containedAnnotations = (A[])getAnnotationsArrayFromValue(entry.getValue(), containerType, annotationClass);3240if (containedAnnotations != null) {3241annotationsList.addAll(Arrays.asList(containedAnnotations));3242}3243}3244}3245}3246}32473248return annotationsList;3249}32503251/**3252* Gets the specified type annotations of this class.3253* If the specified type is not repeatable annotation, then returned array size will be 0 or 1.3254* If specified type is repeatable annotation, then all the annotations of that type will be returned. Array size might be 0, 1 or more.3255*3256* It searches through superclasses until it finds the inherited specified annotationClass.3257*3258* @param annotationClass the annotation type to search for3259* @return array of declared annotations in the specified annotation type3260*3261* @since 1.83262*/3263public <A extends Annotation> A[] getAnnotationsByType(Class<A> annotationClass)3264{3265ArrayList<A> annotationsList = internalGetDeclaredAnnotationsByType(annotationClass);32663267if (annotationClass.isInheritedAnnotationType()) {3268Class<?> sc = this;3269while (0 == annotationsList.size()) {3270sc = sc.getSuperclass();3271if (null == sc) break;3272ArrayList<A> superAnnotations = sc.internalGetDeclaredAnnotationsByType(annotationClass);3273if (superAnnotations != null) {3274annotationsList.addAll(superAnnotations);3275}3276}3277}3278return annotationsList.toArray((A[])Array.newInstance(annotationClass, annotationsList.size()));3279}32803281AnnotationVars getAnnotationVars() {3282AnnotationVars tempAnnotationVars = annotationVars;3283if (tempAnnotationVars == null) {3284if (annotationVarsOffset == -1) {3285try {3286Field annotationVarsField = Class.class.getDeclaredField("annotationVars"); //$NON-NLS-1$3287annotationVarsOffset = getUnsafe().objectFieldOffset(annotationVarsField);3288} catch (NoSuchFieldException e) {3289throw newInternalError(e);3290}3291}3292tempAnnotationVars = new AnnotationVars();3293synchronized (this) {3294if (annotationVars == null) {3295// Lazy initialization of a non-volatile field. Ensure the Object is initialized3296// and flushed to memory before assigning to the annotationVars field.3297/*[IF Sidecar19-SE]3298getUnsafe().putObjectRelease(this, annotationVarsOffset, tempAnnotationVars);3299/*[ELSE]*/3300getUnsafe().putOrderedObject(this, annotationVarsOffset, tempAnnotationVars);3301/*[ENDIF]*/3302} else {3303tempAnnotationVars = annotationVars;3304}3305}3306}3307return tempAnnotationVars;3308}33093310private MethodHandle getValueMethod(final Class<? extends Annotation> containedType) {3311final AnnotationVars localAnnotationVars = getAnnotationVars();3312MethodHandle valueMethod = localAnnotationVars.valueMethod;3313if (valueMethod == null) {3314final MethodType methodType = MethodType.methodType(Array.newInstance(containedType, 0).getClass());3315valueMethod = AccessController.doPrivileged(new PrivilegedAction<MethodHandle>() {3316@Override3317public MethodHandle run() {3318try {3319MethodHandles.Lookup localImplLookup = implLookup;3320if (localImplLookup == null) {3321Field privilegedLookupField = MethodHandles.Lookup.class.getDeclaredField("IMPL_LOOKUP"); //$NON-NLS-1$3322privilegedLookupField.setAccessible(true);3323localImplLookup = (MethodHandles.Lookup)privilegedLookupField.get(MethodHandles.Lookup.class);3324Field implLookupField = Class.class.getDeclaredField("implLookup"); //$NON-NLS-1$3325long implLookupOffset = getUnsafe().staticFieldOffset(implLookupField);3326// Lazy initialization of a non-volatile field. Ensure the Object is initialized3327// and flushed to memory before assigning to the implLookup field.3328/*[IF Sidecar19-SE]3329getUnsafe().putObjectRelease(Class.class, implLookupOffset, localImplLookup);3330/*[ELSE]*/3331getUnsafe().putOrderedObject(Class.class, implLookupOffset, localImplLookup);3332/*[ENDIF]*/3333}3334MethodHandle handle = localImplLookup.findVirtual(Class.this, "value", methodType); //$NON-NLS-1$3335if (AnnotationVars.valueMethodOffset == -1) {3336Field valueMethodField = AnnotationVars.class.getDeclaredField("valueMethod"); //$NON-NLS-1$3337AnnotationVars.valueMethodOffset = getUnsafe().objectFieldOffset(valueMethodField);3338}3339// Lazy initialization of a non-volatile field. Ensure the Object is initialized3340// and flushed to memory before assigning to the valueMethod field.3341/*[IF Sidecar19-SE]3342getUnsafe().putObjectRelease(localAnnotationVars, AnnotationVars.valueMethodOffset, handle);3343/*[ELSE]*/3344getUnsafe().putOrderedObject(localAnnotationVars, AnnotationVars.valueMethodOffset, handle);3345/*[ENDIF]*/3346return handle;3347} catch (NoSuchMethodException e) {3348return null;3349} catch (IllegalAccessException | NoSuchFieldException e) {3350throw newInternalError(e);3351}3352}3353});3354}3355return valueMethod;3356}33573358private MetadataCache getMetadataCache() {3359if (metadataCache == null) {3360/*[IF JAVA_SPEC_VERSION >= 11]3361metadataCacheOffset = getUnsafe().objectFieldOffset(Class.class, "metadataCache"); //$NON-NLS-1$3362/*[ELSE] JAVA_SPEC_VERSION >= 11 */3363try {3364Field field = Class.class.getDeclaredFieldInternal("metadataCache", false); //$NON-NLS-1$3365metadataCacheOffset = getUnsafe().objectFieldOffset(field);3366} catch (NoSuchFieldException e) {3367throw newInternalError(e);3368}3369/*[ENDIF] JAVA_SPEC_VERSION >= 11 */3370writeFieldValue(metadataCacheOffset, new MetadataCache());3371}3372return metadataCache;3373}33743375private String cacheSimpleName(String simpleName) {3376MetadataCache cache = getMetadataCache();33773378if (cache.cachedSimpleName == null || cache.cachedSimpleName.get() == null) {3379MetadataCache.cachedSimpleNameOffset = getFieldOffset(3380MetadataCache.class, "cachedSimpleName", MetadataCache.cachedSimpleNameOffset); //$NON-NLS-1$33813382writeFieldValue(cache, MetadataCache.cachedSimpleNameOffset, new SoftReference<>(simpleName));3383}33843385return simpleName;3386}33873388private String cacheCanonicalName(String canonicalName) {3389MetadataCache cache = getMetadataCache();33903391if (cache.cachedCanonicalName == null || cache.cachedCanonicalName.get() == null) {3392MetadataCache.cachedCanonicalNameOffset = getFieldOffset(3393MetadataCache.class, "cachedCanonicalName", MetadataCache.cachedCanonicalNameOffset); //$NON-NLS-1$33943395writeFieldValue(cache, MetadataCache.cachedCanonicalNameOffset, new SoftReference<>(canonicalName));3396}33973398return canonicalName;3399}34003401/**3402* This helper method atomically writes the given {@code fieldValue} to the3403* field specified by the {@code fieldOffset} of the {@code target} object3404*/3405private static void writeFieldValue(Object target, long fieldOffset, Object fieldValue) {3406/*[IF JAVA_SPEC_VERSION >= 11]3407getUnsafe().putObjectRelease(target, fieldOffset, fieldValue);3408/*[ELSE] JAVA_SPEC_VERSION >= 11 */3409getUnsafe().putOrderedObject(target, fieldOffset, fieldValue);3410/*[ENDIF] JAVA_SPEC_VERSION >= 11 */3411}34123413private void writeFieldValue(long fieldOffset, Object fieldValue) {3414writeFieldValue(this, fieldOffset, fieldValue);3415}34163417private static long getFieldOffset(Class<?> hostClass, String fieldName, long initialOffset) {3418if (initialOffset == -1) {3419try {3420Field field = hostClass.getDeclaredField(fieldName);3421return getUnsafe().objectFieldOffset(field);3422} catch (NoSuchFieldException e) {3423throw newInternalError(e);3424}3425}3426return initialOffset;3427}34283429private static long getFieldOffset(String fieldName) {3430return getFieldOffset(Class.class, fieldName, -1);3431}34323433/**3434* Gets the array of containedType from the value() method.3435*3436* @param container the annotation which is the container of the repeated annotation3437* @param containerType the annotationType() of the container. This implements the value() method.3438* @param containedType the annotationType() stored in the container3439* @return Annotation array if the given annotation has a value() method which returns an array of the containedType. Otherwise, return null.3440*/3441private static Annotation[] getAnnotationsArrayFromValue(Annotation container, Class<? extends Annotation> containerType, Class<? extends Annotation> containedType) {3442try {3443MethodHandle valueMethod = containerType.getValueMethod(containedType);3444if (valueMethod != null) {3445Object children = valueMethod.invoke(container);3446/*3447* Check whether value is Annotation array or not3448*/3449if (children instanceof Annotation[]) {3450return (Annotation[])children;3451}3452}3453return null;3454} catch (Error | RuntimeException e) {3455throw e;3456} catch (Throwable t) {3457throw new RuntimeException(t);3458}3459}34603461private boolean isInheritedAnnotationType() {3462LinkedHashMap<Class<? extends Annotation>, Annotation> map = getAnnotationCache().directAnnotationMap;3463if (map != null) {3464return map.get(Inherited.class) != null;3465}3466return false;3467}34683469private LinkedHashMap<Class<? extends Annotation>, Annotation> buildAnnotations(LinkedHashMap<Class<? extends Annotation>, Annotation> directAnnotationsMap) {3470Class<?> superClass = getSuperclass();3471if (superClass == null) {3472return directAnnotationsMap;3473}3474LinkedHashMap<Class<? extends Annotation>, Annotation> superAnnotations = superClass.getAnnotationCache().annotationMap;3475LinkedHashMap<Class<? extends Annotation>, Annotation> annotationsMap = null;3476if (superAnnotations != null) {3477for (Map.Entry<Class<? extends Annotation>, Annotation> entry : superAnnotations.entrySet()) {3478Class<? extends Annotation> annotationType = entry.getKey();3479// if the annotation is Inherited store the annotation3480if (annotationType.isInheritedAnnotationType()) {3481if (annotationsMap == null) {3482annotationsMap = new LinkedHashMap<>((superAnnotations.size() + (directAnnotationsMap != null ? directAnnotationsMap.size() : 0)) * 4 / 3);3483}3484annotationsMap.put(annotationType, entry.getValue());3485}3486}3487}3488if (annotationsMap == null) {3489return directAnnotationsMap;3490}3491if (directAnnotationsMap != null) {3492annotationsMap.putAll(directAnnotationsMap);3493}3494return annotationsMap;3495}34963497/**3498* Gets all the direct annotations.3499* It does not include repeated annotations for this class, it includes their container annotation(s).3500*3501* @return array of all the direct annotations.3502*/3503private AnnotationCache getAnnotationCache() {3504AnnotationCache annotationCacheResult = annotationCache;35053506if (annotationCacheResult == null) {3507byte[] annotationsData = getDeclaredAnnotationsData();3508if (annotationsData == null) {3509annotationCacheResult = new AnnotationCache(null, buildAnnotations(null));3510} else {3511long offset = Unsafe.ARRAY_BYTE_BASE_OFFSET + ((annotationsData.length * Unsafe.ARRAY_BYTE_INDEX_SCALE) - VM.FJ9OBJECT_SIZE);3512long ramCPAddr = 0;3513if (VM.FJ9OBJECT_SIZE == 4) {3514/* Compressed object refs */3515ramCPAddr = Integer.toUnsignedLong(unsafe.getInt(annotationsData, offset));3516} else {3517ramCPAddr = unsafe.getLong(annotationsData, offset);3518}3519Object internalCP = VM.getVMLangAccess().createInternalConstantPool(ramCPAddr);35203521Annotation[] directAnnotations = sun.reflect.annotation.AnnotationParser.toArray(3522sun.reflect.annotation.AnnotationParser.parseAnnotations(3523annotationsData,3524getConstantPool(internalCP),3525this));35263527LinkedHashMap<Class<? extends Annotation>, Annotation> directAnnotationsMap = new LinkedHashMap<>(directAnnotations.length * 4 / 3);3528for (Annotation annotation : directAnnotations) {3529Class<? extends Annotation> annotationType = annotation.annotationType();3530directAnnotationsMap.put(annotationType, annotation);3531}3532annotationCacheResult = new AnnotationCache(directAnnotationsMap, buildAnnotations(directAnnotationsMap));3533}35343535// Don't bother with synchronization. Since it is just a cache, it doesn't matter if it gets overwritten3536// because multiple threads create the cache at the same time3537long localAnnotationCacheOffset = annotationCacheOffset;3538if (localAnnotationCacheOffset == -1) {3539try {3540Field annotationCacheField = Class.class.getDeclaredField("annotationCache"); //$NON-NLS-1$3541localAnnotationCacheOffset = getUnsafe().objectFieldOffset(annotationCacheField);3542annotationCacheOffset = localAnnotationCacheOffset;3543} catch (NoSuchFieldException e) {3544throw newInternalError(e);3545}3546}3547// Lazy initialization of a non-volatile field. Ensure the Object is initialized3548// and flushed to memory before assigning to the annotationCache field.3549/*[IF Sidecar19-SE]*/3550getUnsafe().putObjectRelease(this, localAnnotationCacheOffset, annotationCacheResult);3551/*[ELSE]*/3552getUnsafe().putOrderedObject(this, localAnnotationCacheOffset, annotationCacheResult);3553/*[ENDIF]*/3554}3555return annotationCacheResult;3556}355735583559private native byte[] getDeclaredAnnotationsData();35603561/**3562* Answer if this class is an Annotation.3563*3564* @return true if this class is an Annotation3565*3566* @since 1.53567*/3568public boolean isAnnotation() {3569// This code has been inlined in toGenericString. toGenericString3570// must be modified to reflect any changes to this implementation.3571/*[PR CMVC 89373] Ensure Annotation subclass is not annotation */3572return !isArray() && (getModifiersImpl() & ANNOTATION) != 0;3573}35743575/**3576* Answer if the specified Annotation exists for this Class. Inherited3577* Annotations are searched.3578*3579* @param annotation the Annotation type3580* @return true if the specified Annotation exists3581*3582* @since 1.53583*/3584public boolean isAnnotationPresent(Class<? extends Annotation> annotation) {3585if (annotation == null) throw new NullPointerException();3586return getAnnotation(annotation) != null;3587}35883589/**3590* Cast this Class to a subclass of the specified Class.3591* @param <U> the type for casting to3592* @param cls the Class to cast to3593* @return this Class, cast to a subclass of the specified Class3594*3595* @throws ClassCastException if this Class is not the same or a subclass3596* of the specified Class3597*3598* @since 1.53599*/3600public <U> Class<? extends U> asSubclass(Class<U> cls) {3601if (!cls.isAssignableFrom(this))3602throw new ClassCastException(this.toString());3603return (Class<? extends U>)this;3604}36053606/**3607* Cast the specified object to this Class.3608*3609* @param object the object to cast3610*3611* @return the specified object, cast to this Class3612*3613* @throws ClassCastException if the specified object cannot be cast3614* to this Class3615*3616* @since 1.53617*/3618public T cast(Object object) {3619if ((object != null) && !this.isInstance(object)) {3620/*[MSG "K0336", "Cannot cast {0} to {1}"]*/3621throw new ClassCastException(com.ibm.oti.util.Msg.getString("K0336", object.getClass().getName(), getName())); //$NON-NLS-1$3622}3623return (T)object;3624}36253626/**3627* Answer if this Class is an enum.3628*3629* @return true if this Class is an enum3630*3631* @since 1.53632*/3633public boolean isEnum() {3634// This code has been inlined in toGenericString. toGenericString3635// must be modified to reflect any changes to this implementation.3636/*[PR CMVC 89071] Ensure class with enum access flag (modifier) !isEnum() */3637return !isArray() && (getModifiersImpl() & ENUM) != 0 &&3638getSuperclass() == Enum.class;3639}36403641private EnumVars<T> getEnumVars() {3642EnumVars<T> tempEnumVars = enumVars;3643if (tempEnumVars == null) {3644long localEnumVarsOffset = enumVarsOffset;3645if (localEnumVarsOffset == -1) {3646Field enumVarsField;3647try {3648enumVarsField = Class.class.getDeclaredField("enumVars"); //$NON-NLS-1$3649localEnumVarsOffset = getUnsafe().objectFieldOffset(enumVarsField);3650enumVarsOffset = localEnumVarsOffset;3651} catch (NoSuchFieldException e) {3652throw newInternalError(e);3653}3654}3655// Don't bother with synchronization to determine if the field is already assigned. Since it is just a cache,3656// it doesn't matter if it gets overwritten because multiple threads create the cache at the same time3657tempEnumVars = new EnumVars<>();3658// Lazy initialization of a non-volatile field. Ensure the Object is initialized3659// and flushed to memory before assigning to the enumVars field.3660/*[IF Sidecar19-SE]3661getUnsafe().putObjectRelease(this, localEnumVarsOffset, tempEnumVars);3662/*[ELSE]*/3663getUnsafe().putOrderedObject(this, localEnumVarsOffset, tempEnumVars);3664/*[ENDIF]*/3665}3666return tempEnumVars;3667}36683669/**3670*3671* @return Map keyed by enum name, of uncloned and cached enum constants in this class3672*/3673Map<String, T> enumConstantDirectory() {3674EnumVars<T> localEnumVars = getEnumVars();3675Map<String, T> map = localEnumVars.cachedEnumConstantDirectory;3676if (null == map) {3677/*[PR CMVC 189091] Perf: EnumSet.allOf() is slow */3678T[] enums = getEnumConstantsShared();3679if (enums == null) {3680/*[PR CMVC 189257] Class#valueOf throws NPE instead of IllegalArgEx for nonEnum Classes */3681/*3682* Class#valueOf() is the caller of this method,3683* according to the spec it throws IllegalArgumentException if the class is not an Enum.3684*/3685/*[MSG "K0564", "{0} is not an Enum"]*/3686throw new IllegalArgumentException(com.ibm.oti.util.Msg.getString("K0564", getName())); //$NON-NLS-1$3687}3688map = new HashMap<>(enums.length * 4 / 3);3689for (int i = 0; i < enums.length; i++) {3690map.put(((Enum<?>) enums[i]).name(), enums[i]);3691}36923693if (EnumVars.enumDirOffset == -1) {3694try {3695Field enumDirField = EnumVars.class.getDeclaredField("cachedEnumConstantDirectory"); //$NON-NLS-1$3696EnumVars.enumDirOffset = getUnsafe().objectFieldOffset(enumDirField);3697} catch (NoSuchFieldException e) {3698throw newInternalError(e);3699}3700}3701// Lazy initialization of a non-volatile field. Ensure the Object is initialized3702// and flushed to memory before assigning to the cachedEnumConstantDirectory field.3703/*[IF Sidecar19-SE]3704getUnsafe().putObjectRelease(localEnumVars, EnumVars.enumDirOffset, map);3705/*[ELSE]*/3706getUnsafe().putOrderedObject(localEnumVars, EnumVars.enumDirOffset, map);3707/*[ENDIF]*/3708}3709return map;3710}37113712/**3713* Answer the shared uncloned array of enum constants for this Class. Returns null if3714* this class is not an enum.3715*3716* @return the array of enum constants, or null3717*3718* @since 1.53719*/3720/*[PR CMVC 189091] Perf: EnumSet.allOf() is slow */3721T[] getEnumConstantsShared() {3722/*[PR CMVC 188840] Perf: Class.getEnumConstants() is slow */3723EnumVars<T> localEnumVars = getEnumVars();3724T[] enums = localEnumVars.cachedEnumConstants;3725if (null == enums && isEnum()) {3726try {3727final PrivilegedExceptionAction<Method> privilegedAction = new PrivilegedExceptionAction<Method>() {3728@Override3729public Method run() throws Exception {3730Method method = getMethod("values"); //$NON-NLS-1$3731/*[PR CMVC 83171] caused ClassCastException: <enum class> not an enum]*/3732// the enum class may not be visible3733method.setAccessible(true);3734return method;3735}3736};37373738Method values = AccessController.doPrivileged(privilegedAction);3739enums = (T[])values.invoke(this);37403741long localEnumConstantsOffset = EnumVars.enumConstantsOffset;3742if (localEnumConstantsOffset == -1) {3743try {3744Field enumConstantsField = EnumVars.class.getDeclaredField("cachedEnumConstants"); //$NON-NLS-1$3745localEnumConstantsOffset = getUnsafe().objectFieldOffset(enumConstantsField);3746EnumVars.enumConstantsOffset = localEnumConstantsOffset;3747} catch (NoSuchFieldException e) {3748throw newInternalError(e);3749}3750}3751// Lazy initialization of a non-volatile field. Ensure the Object is initialized3752// and flushed to memory before assigning to the cachedEnumConstants field.3753/*[IF Sidecar19-SE]3754getUnsafe().putObjectRelease(localEnumVars, localEnumConstantsOffset, enums);3755/*[ELSE]*/3756getUnsafe().putOrderedObject(localEnumVars, localEnumConstantsOffset, enums);3757/*[ENDIF]*/3758} catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException | PrivilegedActionException e) {3759enums = null;3760}3761}37623763return enums;3764}37653766/**3767* Answer the array of enum constants for this Class. Returns null if3768* this class is not an enum.3769*3770* @return the array of enum constants, or null3771*3772* @since 1.53773*/3774public T[] getEnumConstants() {3775/*[PR CMVC 188840] Perf: Class.getEnumConstants() is slow */3776/*[PR CMVC 189091] Perf: EnumSet.allOf() is slow */3777/*[PR CMVC 192837] JAVA8:JCK: NPE at j.l.Class.getEnumConstants */3778T[] enumConstants = getEnumConstantsShared();3779if (null != enumConstants) {3780return enumConstants.clone();3781} else {3782return null;3783}3784}37853786/**3787* Answer if this Class is synthetic. A synthetic Class is created by3788* the compiler.3789*3790* @return true if this Class is synthetic.3791*3792* @since 1.53793*/3794public boolean isSynthetic() {3795return !isArray() && (getModifiersImpl() & SYNTHETIC) != 0;3796}37973798private native String getGenericSignature();37993800private CoreReflectionFactory getFactory() {3801return CoreReflectionFactory.make(this, ClassScope.make(this));3802}38033804private ClassRepositoryHolder getClassRepositoryHolder() {3805ClassRepositoryHolder localClassRepositoryHolder = classRepoHolder;3806if (localClassRepositoryHolder == null) {3807synchronized(this) {3808localClassRepositoryHolder = classRepoHolder;3809if (localClassRepositoryHolder == null) {3810String signature = getGenericSignature();3811if (signature == null) {3812localClassRepositoryHolder = ClassRepositoryHolder.NullSingleton;3813} else {3814ClassRepository classRepo = ClassRepository.make(signature, getFactory());3815localClassRepositoryHolder = new ClassRepositoryHolder(classRepo);3816}3817classRepoHolder = localClassRepositoryHolder;3818}3819}3820}3821return localClassRepositoryHolder;3822}382338243825/**3826* Answers an array of TypeVariable for the generic parameters declared3827* on this Class.3828*3829* @return the TypeVariable[] for the generic parameters3830*3831* @since 1.53832*/3833@SuppressWarnings("unchecked")3834public TypeVariable<Class<T>>[] getTypeParameters() {3835ClassRepositoryHolder holder = getClassRepositoryHolder();3836ClassRepository repository = holder.classRepository;3837if (repository == null) return new TypeVariable[0];3838return (TypeVariable<Class<T>>[])repository.getTypeParameters();3839}38403841/**3842* Answers an array of Type for the Class objects which match the3843* interfaces specified in the receiver classes <code>implements</code>3844* declaration.3845*3846* @return Type[]3847* the interfaces the receiver claims to implement.3848*3849* @since 1.53850*/3851public Type[] getGenericInterfaces() {3852ClassRepositoryHolder holder = getClassRepositoryHolder();3853ClassRepository repository = holder.classRepository;3854if (repository == null) return getInterfaces();3855return repository.getSuperInterfaces();3856}38573858/**3859* Answers the Type for the Class which represents the receiver's3860* superclass. For classes which represent base types,3861* interfaces, and for java.lang.Object the method3862* answers null.3863*3864* @return the Type for the receiver's superclass.3865*3866* @since 1.53867*/3868public Type getGenericSuperclass() {3869ClassRepositoryHolder holder = getClassRepositoryHolder();3870ClassRepository repository = holder.classRepository;3871if (repository == null) return getSuperclass();3872if (isInterface()) return null;3873return repository.getSuperclass();3874}38753876private native Object getEnclosingObject();38773878/**3879* If this Class is defined inside a constructor, return the Constructor.3880*3881* @return the enclosing Constructor or null3882* @throws SecurityException if declared member access or package access is not allowed3883*3884* @since 1.53885*3886* @see #isAnonymousClass()3887* @see #isLocalClass()3888*/3889@CallerSensitive3890public Constructor<?> getEnclosingConstructor() throws SecurityException {3891Constructor<?> constructor = null;3892Object enclosing = getEnclosingObject();3893if (enclosing instanceof Constructor<?>) {3894constructor = (Constructor<?>) enclosing;3895@SuppressWarnings("removal")3896SecurityManager security = System.getSecurityManager();3897if (security != null) {3898ClassLoader callerClassLoader = ClassLoader.getStackClassLoader(1);3899constructor.getDeclaringClass().checkMemberAccess(security, callerClassLoader, Member.DECLARED);3900}3901/*[PR CMVC 201439] To remove CheckPackageAccess call from getEnclosingMethod of J9 */3902}3903return constructor;3904}39053906/**3907* If this Class is defined inside a method, return the Method.3908*3909* @return the enclosing Method or null3910* @throws SecurityException if declared member access or package access is not allowed3911*3912* @since 1.53913*3914* @see #isAnonymousClass()3915* @see #isLocalClass()3916*/3917@CallerSensitive3918public Method getEnclosingMethod() throws SecurityException {3919Method method = null;3920Object enclosing = getEnclosingObject();3921if (enclosing instanceof Method) {3922method = (Method)enclosing;3923@SuppressWarnings("removal")3924SecurityManager security = System.getSecurityManager();3925if (security != null) {3926ClassLoader callerClassLoader = ClassLoader.getStackClassLoader(1);3927method.getDeclaringClass().checkMemberAccess(security, callerClassLoader, Member.DECLARED);3928}3929/*[PR CMVC 201439] To remove CheckPackageAccess call from getEnclosingMethod of J9 */3930}3931return method;3932}39333934private native Class<?> getEnclosingObjectClass();39353936/**3937* Return the enclosing Class of this Class. Unlike getDeclaringClass(),3938* this method works on any nested Class, not just classes nested directly3939* in other classes.3940*3941* @return the enclosing Class or null3942* @throws SecurityException if package access is not allowed3943*3944* @since 1.53945*3946* @see #getDeclaringClass()3947* @see #isAnonymousClass()3948* @see #isLocalClass()3949* @see #isMemberClass()3950*/3951@CallerSensitive3952public Class<?> getEnclosingClass() throws SecurityException {3953Class<?> enclosingClass = getDeclaringClass();3954if (enclosingClass == null) {3955if (cachedEnclosingClassOffset == -1) {3956cachedEnclosingClassOffset = getFieldOffset("cachedEnclosingClass"); //$NON-NLS-1$3957}3958if (cachedEnclosingClass == null) {3959Class<?> localEnclosingClass = getEnclosingObjectClass();3960if (localEnclosingClass == null){3961localEnclosingClass = ClassReflectNullPlaceHolder.class;3962}3963writeFieldValue(cachedEnclosingClassOffset, localEnclosingClass);3964}3965/**3966* ClassReflectNullPlaceHolder.class means the value of cachedEnclosingClass is null3967* @see ClassReflectNullPlaceHolder.class3968*/3969enclosingClass = cachedEnclosingClass == ClassReflectNullPlaceHolder.class ? null: cachedEnclosingClass;3970}3971if (enclosingClass != null) {3972@SuppressWarnings("removal")3973SecurityManager security = System.getSecurityManager();3974if (security != null) {3975ClassLoader callerClassLoader = ClassLoader.getStackClassLoader(1);3976enclosingClass.checkMemberAccess(security, callerClassLoader, MEMBER_INVALID_TYPE);3977}3978}39793980return enclosingClass;3981}39823983private native String getSimpleNameImpl();39843985/**3986* Return the simple name of this Class. The simple name does not include3987* the package or the name of the enclosing class. The simple name of an3988* anonymous class is "".3989*3990* @return the simple name3991*3992* @since 1.53993*3994* @see #isAnonymousClass()3995*/3996public String getSimpleName() {3997MetadataCache cache = getMetadataCache();3998if (cache.cachedSimpleName != null) {3999String cachedSimpleName = cache.cachedSimpleName.get();4000if (cachedSimpleName != null) {4001return cachedSimpleName;4002}4003}40044005int arrayCount = 0;4006Class<?> baseType = this;4007if (isArray()) {4008arrayCount = 1;4009while ((baseType = baseType.getComponentType()).isArray()) {4010arrayCount++;4011}4012}4013String simpleName = baseType.getSimpleNameImpl();4014String fullName = baseType.getName();4015if (simpleName == null) {4016/**4017* It is a base class, an anonymous class, or a hidden class.4018* Call getEnclosingClass() instead of getEnclosingObjectClass() to check getDeclaringClass() first. Hidden class test expects4019* NoClassDefFoundError from getDeclaringClass().4020*/4021Class<?> parent = baseType.getEnclosingClass();4022if (parent != null) {4023simpleName = ""; //$NON-NLS-1$4024} else {4025// remove the package name4026int index = fullName.lastIndexOf('.');4027if (index != -1) {4028simpleName = fullName.substring(index+1);4029} else {4030// no periods in fully qualified name, thus simple name is also the full name4031simpleName = fullName;4032}4033}4034}4035/*[IF !Sidecar19-SE]*/4036/* In Java 8, the simple name needs to match the full name*/4037else if (!fullName.endsWith(simpleName)) {4038Class<?> parent = baseType.getEnclosingObjectClass();4039int index = fullName.lastIndexOf('.') + 1;4040if (parent == null) {4041parent = getDeclaringClassImpl();4042}4043if (parent != null) {4044/* Nested classes have names which consist of the parent class name followed by a '$', followed by4045* the simple name. Some nested classes have additional characters between the parent class name4046* and the simple name of the nested class.4047*/4048String parentName = parent.getName();4049if (fullName.startsWith(parentName) && (fullName.charAt(parentName.length()) == '$')) {4050index = fullName.lastIndexOf('$') + 1;4051// a local class simple name is preceded by a sequence of digits4052while (index < fullName.length() && !Character.isJavaIdentifierStart(fullName.charAt(index))) {4053index++;4054}4055}4056}4057if (index != -1) {4058simpleName = fullName.substring(index);4059}4060}4061/*[ENDIF] !Sidecar19-SE*/4062if (arrayCount > 0) {4063StringBuilder result = new StringBuilder(simpleName);4064for (int i=0; i<arrayCount; i++) {4065result.append("[]"); //$NON-NLS-1$4066}4067return result.toString();4068}4069return cacheSimpleName(simpleName);4070}40714072/**4073* Return the canonical name of this Class. The canonical name is null4074* for a local or anonymous class. The canonical name includes the package4075* and the name of the enclosing class.4076*4077* @return the canonical name or null4078*4079* @since 1.54080*4081* @see #isAnonymousClass()4082* @see #isLocalClass()4083*/4084public String getCanonicalName() {4085MetadataCache cache = getMetadataCache();4086if (cache.cachedCanonicalName != null) {4087String cachedCanonicalName = cache.cachedCanonicalName.get();4088if (cachedCanonicalName != null) {4089return cachedCanonicalName;4090}4091}40924093int arrayCount = 0;4094Class<?> baseType = this;4095if (isArray()) {4096arrayCount = 1;4097while ((baseType = baseType.getComponentType()).isArray()) {4098arrayCount++;4099}4100}4101/*[IF JAVA_SPEC_VERSION >= 15]*/4102if (baseType.isHidden()) {4103/* Canonical name is always null for hidden classes. */4104return null;4105}4106/*[ENDIF] JAVA_SPEC_VERSION >= 15 */4107if (baseType.getEnclosingObjectClass() != null) {4108// local or anonymous class4109return null;4110}4111String canonicalName;4112Class<?> declaringClass = baseType.getDeclaringClass();4113if (declaringClass == null) {4114canonicalName = baseType.getName();4115} else {4116/*[PR 119256] The canonical name of a member class of a local class should be null */4117String declaringClassCanonicalName = declaringClass.getCanonicalName();4118if (declaringClassCanonicalName == null) return null;4119// remove the enclosingClass from the name, including the $4120String simpleName = baseType.getName().substring(declaringClass.getName().length() + 1);4121canonicalName = declaringClassCanonicalName + '.' + simpleName;4122}41234124if (arrayCount > 0) {4125StringBuilder result = new StringBuilder(canonicalName);4126for (int i=0; i<arrayCount; i++) {4127result.append("[]"); //$NON-NLS-1$4128}4129return result.toString();4130}4131return cacheCanonicalName(canonicalName);4132}41334134/**4135* Answer if this Class is anonymous. An unnamed Class defined4136* inside a method.4137*4138* @return true if this Class is anonymous.4139*4140* @since 1.54141*4142* @see #isLocalClass()4143*/4144public boolean isAnonymousClass() {4145return getSimpleNameImpl() == null && getEnclosingObjectClass() != null;4146}41474148/**4149* Answer if this Class is local. A named Class defined inside4150* a method.4151*4152* @return true if this Class is local.4153*4154* @since 1.54155*4156* @see #isAnonymousClass()4157*/4158public boolean isLocalClass() {4159return getEnclosingObjectClass() != null && getSimpleNameImpl() != null;4160}41614162/**4163* Answer if this Class is a member Class. A Class defined inside another4164* Class.4165*4166* @return true if this Class is local.4167*4168* @since 1.54169*4170* @see #isLocalClass()4171*/4172public boolean isMemberClass() {4173return getEnclosingObjectClass() == null && getDeclaringClass() != null;4174}41754176/**4177* Compute the signature for get*Method()4178*4179* @param throwException if NoSuchMethodException is thrown4180* @param name the name of the method4181* @param parameterTypes the types of the arguments4182* @return the signature string4183* @throws NoSuchMethodException if one of the parameter types cannot be found in the local class loader4184*4185* @see #getDeclaredMethod4186* @see #getMethod4187*/4188private String getParameterTypesSignature(boolean throwException, String name, Class<?>[] parameterTypes, String returnTypeSignature) throws NoSuchMethodException {4189int total = 2;4190String[] sigs = new String[parameterTypes.length];4191for(int i = 0; i < parameterTypes.length; i++) {4192Class<?> parameterType = parameterTypes[i];4193/*[PR 103441] should throw NoSuchMethodException */4194if (parameterType != null) {4195sigs[i] = parameterType.getSignature();4196total += sigs[i].length();4197} else {4198if (throwException) {4199throw newNoSuchMethodException(name, parameterTypes);4200} else {4201return null;4202}4203}4204}4205total += returnTypeSignature.length();4206StringBuilder signature = new StringBuilder(total);4207signature.append('(');4208for(int i = 0; i < parameterTypes.length; i++)4209signature.append(sigs[i]);4210signature.append(')').append(returnTypeSignature);4211return signature.toString();4212}42134214/*[IF JAVA_SPEC_VERSION == 8]*/4215/*[PR CMVC 114820, CMVC 115873, CMVC 116166] add reflection cache */4216private static Method copyMethod, copyField, copyConstructor;4217private static Field methodParameterTypesField;4218private static Field constructorParameterTypesField;4219private static final Object[] NoArgs = new Object[0];4220/*[ENDIF] JAVA_SPEC_VERSION == 8 */42214222/*[PR JAZZ 107786] constructorParameterTypesField should be initialized regardless of reflectCacheEnabled or not */4223static void initCacheIds(boolean cacheEnabled, boolean cacheDebug) {4224reflectCacheEnabled = cacheEnabled;4225reflectCacheDebug = cacheDebug;4226/*[IF JAVA_SPEC_VERSION == 8]*/4227AccessController.doPrivileged(new PrivilegedAction<Void>() {4228@Override4229public Void run() {4230doInitCacheIds();4231return null;4232}4233});4234/*[ENDIF] JAVA_SPEC_VERSION == 8 */4235}4236static void setReflectCacheAppOnly(boolean cacheAppOnly) {4237reflectCacheAppOnly = cacheAppOnly;4238}4239/*[IF JAVA_SPEC_VERSION == 8]*/4240@SuppressWarnings("nls")4241static void doInitCacheIds() {4242/*4243* We cannot just call getDeclaredField() because that method includes a call4244* to Reflection.filterFields() which will remove the fields needed here.4245* The remaining required behavior of getDeclaredField() is inlined here.4246* The security checks are omitted (they would be redundant). Caching is4247* not done (we're in the process of initializing the caching mechanisms).4248* We must ensure the classes that own the fields of interest are prepared.4249*/4250J9VMInternals.prepare(Constructor.class);4251J9VMInternals.prepare(Method.class);4252try {4253constructorParameterTypesField = Constructor.class.getDeclaredFieldImpl("parameterTypes");4254methodParameterTypesField = Method.class.getDeclaredFieldImpl("parameterTypes");4255} catch (NoSuchFieldException e) {4256throw newInternalError(e);4257}4258constructorParameterTypesField.setAccessible(true);4259methodParameterTypesField.setAccessible(true);4260if (reflectCacheEnabled) {4261copyConstructor = getAccessibleMethod(Constructor.class, "copy");4262copyMethod = getAccessibleMethod(Method.class, "copy");4263copyField = getAccessibleMethod(Field.class, "copy");4264}4265}4266/*[ENDIF] JAVA_SPEC_VERSION == 8 */4267private static Method getAccessibleMethod(Class<?> cls, String name) {4268try {4269Method method = cls.getDeclaredMethod(name, EmptyParameters);4270method.setAccessible(true);4271return method;4272} catch (NoSuchMethodException e) {4273throw newInternalError(e);4274}4275}42764277/*[PR RTC 104994 redesign getMethods]*/4278/**4279* represents all methods of a given name and signature visible from a given class or interface.4280*4281*/4282private class MethodInfo {4283ArrayList<Method> jlrMethods;4284Method me;4285private final int myHash;4286private Class<?>[] paramTypes;4287private Class<?> returnType;4288private java.lang.String methodName;42894290public MethodInfo(Method myMethod) {4291me = myMethod;4292methodName = myMethod.getName();4293myHash = methodName.hashCode();4294this.paramTypes = null;4295this.returnType = null;4296jlrMethods = null;4297}42984299public MethodInfo(MethodInfo otherMi) {4300this.me = otherMi.me;4301this.methodName = otherMi.methodName;4302this.paramTypes = otherMi.paramTypes;4303this.returnType = otherMi.returnType;4304this.myHash = otherMi.myHash;43054306if (null != otherMi.jlrMethods) {4307jlrMethods = (ArrayList<Method>) otherMi.jlrMethods.clone();4308} else {4309jlrMethods = null;4310}43114312}43134314private void initializeTypes() {4315paramTypes = getParameterTypes(me);4316returnType = me.getReturnType();4317}43184319/** (non-Javadoc)4320* @param that another MethodInfo object4321* @return true if the methods have the same name and signature4322* @note does not compare the defining class, permissions, exceptions, etc.4323*/4324@Override4325public boolean equals(Object that) {4326if (this == that) {4327return true;4328}4329if (!that.getClass().equals(this.getClass())) {4330return false;4331}4332@SuppressWarnings("unchecked")4333MethodInfo otherMethod = (MethodInfo) that;4334if (!methodName.equals(otherMethod.methodName)) {4335return false;4336}4337if (null == returnType) {4338initializeTypes();4339}4340if (null == otherMethod.returnType) {4341otherMethod.initializeTypes();4342}4343if (!returnType.equals(otherMethod.returnType)) {4344return false;4345}4346Class<?>[] m1Parms = paramTypes;4347Class<?>[] m2Parms = otherMethod.paramTypes;4348if (m1Parms.length != m2Parms.length) {4349return false;4350}4351for (int i = 0; i < m1Parms.length; i++) {4352if (m1Parms[i] != m2Parms[i]) {4353return false;4354}4355}4356return true;4357}43584359/**4360* Add a method to the list. newMethod may be discarded if it is masked by an incumbent method in the list.4361* Also, an incumbent method may be removed if newMethod masks it.4362* In general, a target class inherits a method from its direct superclass or directly implemented interfaces unless:4363* - the method is static or private and the declaring class is not the target class4364* - the target class declares the method (concrete or abstract)4365* - the method is default and a superclass of the target class contains a concrete implementation of the method4366* - a more specific implemented interface contains a concrete implementation4367* @param newMethod method to be added.4368*/4369void update(Method newMethod) {4370int newModifiers = newMethod.getModifiers();4371if (!Modifier.isPublic(newModifiers)) { /* can't see the method */4372return;4373}4374Class<?> newMethodClass = newMethod.getDeclaringClass();4375boolean newMethodIsAbstract = Modifier.isAbstract(newModifiers);4376boolean newMethodClassIsInterface = newMethodClass.isInterface();43774378if (null == jlrMethods) {4379/* handle the common case of a single declaration */4380if (!newMethod.equals(me)) {4381Class<?> incumbentMethodClass = me.getDeclaringClass();4382if (Class.this != incumbentMethodClass) {4383boolean incumbentIsAbstract = Modifier.isAbstract(me.getModifiers());4384boolean incumbentClassIsInterface = incumbentMethodClass.isInterface();4385if (methodAOverridesMethodB(newMethodClass, newMethodIsAbstract, newMethodClassIsInterface,4386incumbentMethodClass, incumbentIsAbstract, incumbentClassIsInterface)4387) {4388me = newMethod;4389} else if (!methodAOverridesMethodB(incumbentMethodClass, incumbentIsAbstract, incumbentClassIsInterface,4390newMethodClass, newMethodIsAbstract, newMethodClassIsInterface)4391) {4392/* we need to store both */4393jlrMethods = new ArrayList<>(2);4394jlrMethods.add(me);4395jlrMethods.add(newMethod);4396}4397}4398}4399} else {4400int methodCursor = 0;4401boolean addMethod = true;4402boolean replacedMethod = false;4403while (methodCursor < jlrMethods.size()) {4404int increment = 1;4405Method m = jlrMethods.get(methodCursor);4406if (newMethod.equals(m)) { /* already have this method */4407addMethod = false;4408} else {4409Class<?> incumbentMethodClass = m.getDeclaringClass();4410if (Class.this == incumbentMethodClass) {4411addMethod = false;4412} else {4413boolean incumbentIsAbstract = Modifier.isAbstract(m.getModifiers());4414boolean incumbentClassIsInterface = incumbentMethodClass.isInterface();4415if (methodAOverridesMethodB(newMethodClass, newMethodIsAbstract, newMethodClassIsInterface,4416incumbentMethodClass, incumbentIsAbstract, incumbentClassIsInterface)4417) {4418if (!replacedMethod) {4419/* preserve ordering by removing old and appending new instead of directly replacing. */4420jlrMethods.remove(methodCursor);4421jlrMethods.add(newMethod);4422increment = 0;4423replacedMethod = true;4424} else {4425jlrMethods.remove(methodCursor);4426increment = 0;4427/* everything slid over one slot */4428}4429addMethod = false;4430} else if (methodAOverridesMethodB(incumbentMethodClass, incumbentIsAbstract, incumbentClassIsInterface,4431newMethodClass, newMethodIsAbstract, newMethodClassIsInterface)4432) {4433addMethod = false;4434}4435}4436}4437methodCursor += increment;4438}4439if (addMethod) {4440jlrMethods.add(newMethod);4441}4442}4443}44444445public void update(MethodInfo otherMi) {4446if (null == otherMi.jlrMethods) {4447update(otherMi.me);4448} else for (Method m: otherMi.jlrMethods) {4449update(m);4450}4451}4452@Override4453public int hashCode() {4454return myHash;4455}44564457}44584459static boolean methodAOverridesMethodB(Class<?> methodAClass, boolean methodAIsAbstract, boolean methodAClassIsInterface,4460Class<?> methodBClass, boolean methodBIsAbstract, boolean methodBClassIsInterface) {4461return (methodBIsAbstract && methodBClassIsInterface && !methodAIsAbstract && !methodAClassIsInterface) ||4462(methodBClass.isAssignableFrom(methodAClass)4463/*[IF !Sidecar19-SE]*/4464/*4465* In Java 8, abstract methods in subinterfaces do not hide abstract methods in superinterfaces.4466* This is fixed in Java 9.4467*/4468&& (!methodAClassIsInterface || !methodAIsAbstract)4469/*[ENDIF]*/4470);4471}44724473/*[PR 125873] Improve reflection cache */4474private static final class ReflectRef extends SoftReference<Object> implements Runnable {4475private static final ReferenceQueue<Object> queue = new ReferenceQueue<>();4476private final ReflectCache cache;4477final CacheKey key;4478ReflectRef(ReflectCache cache, CacheKey key, Object value) {4479super(value, queue);4480this.cache = cache;4481this.key = key;4482}4483@Override4484public void run() {4485cache.handleCleared(this);4486}4487}44884489/*[IF]*/4490/*4491* Keys for constructors, fields and methods are all mutually distinct so we can4492* distinguish them in a single map. The key for a field has parameterTypes == null4493* while parameterTypes can't be null for constructors or methods. The key for a4494* constructor has an empty name which is not legal in a class file (for any feature).4495* The Public* and Declared* keys have names that can't collide with any other normal4496* key (derived from a legal class).4497*/4498/*[ENDIF]*/4499private static final class CacheKey {4500/*[PR CMVC 163440] java.lang.Class$CacheKey.PRIME should be static */4501private static final int PRIME = 31;4502private static int hashCombine(int partial, int itemHash) {4503return partial * PRIME + itemHash;4504}4505private static int hashCombine(int partial, Object item) {4506return hashCombine(partial, item == null ? 0 : item.hashCode());4507}45084509static CacheKey newConstructorKey(Class<?>[] parameterTypes) {4510return new CacheKey("", parameterTypes, null); //$NON-NLS-1$4511}4512static CacheKey newFieldKey(String fieldName, Class<?> type) {4513return new CacheKey(fieldName, null, type);4514}4515static CacheKey newMethodKey(String methodName, Class<?>[] parameterTypes, Class<?> returnType) {4516return new CacheKey(methodName, parameterTypes, returnType);4517}4518/*[IF JAVA_SPEC_VERSION >= 11]*/4519static CacheKey newDeclaredPublicMethodsKey(String methodName, Class<?>[] parameterTypes) {4520return new CacheKey("#m" + methodName, parameterTypes, null); //$NON-NLS-1$4521}4522/*[ENDIF] JAVA_SPEC_VERSION >= 11 */45234524static final CacheKey PublicConstructorsKey = new CacheKey("/c", EmptyParameters, null); //$NON-NLS-1$4525static final CacheKey PublicFieldsKey = newFieldKey("/f", null); //$NON-NLS-1$4526static final CacheKey PublicMethodsKey = new CacheKey("/m", EmptyParameters, null); //$NON-NLS-1$45274528static final CacheKey DeclaredConstructorsKey = new CacheKey(".c", EmptyParameters, null); //$NON-NLS-1$4529static final CacheKey DeclaredFieldsKey = newFieldKey(".f", null); //$NON-NLS-1$4530static final CacheKey DeclaredMethodsKey = new CacheKey(".m", EmptyParameters, null); //$NON-NLS-1$45314532private final String name;4533private final Class<?>[] parameterTypes;4534private final Class<?> returnType;4535private final int hashCode;4536private CacheKey(String name, Class<?>[] parameterTypes, Class<?> returnType) {4537super();4538int hash = hashCombine(name.hashCode(), returnType);4539if (parameterTypes != null) {4540for (Class<?> parameterType : parameterTypes) {4541hash = hashCombine(hash, parameterType);4542}4543}4544this.name = name;4545this.parameterTypes = parameterTypes;4546this.returnType = returnType;4547this.hashCode = hash;4548}4549@Override4550public boolean equals(Object obj) {4551if (this == obj) {4552return true;4553}4554CacheKey that = (CacheKey) obj;4555if (this.returnType == that.returnType4556&& sameTypes(this.parameterTypes, that.parameterTypes)) {4557return this.name.equals(that.name);4558}4559return false;4560}4561@Override4562public int hashCode() {4563return hashCode;4564}4565}45664567private static Class<?>[] getParameterTypes(Constructor<?> constructor) {4568/*[IF JAVA_SPEC_VERSION >= 11]*/4569reflectionFactory = getReflectionFactory();4570return reflectionFactory.getExecutableSharedParameterTypes(constructor);4571/*[ELSE] JAVA_SPEC_VERSION >= 11*/4572try {4573if (null != constructorParameterTypesField) {4574return (Class<?>[]) constructorParameterTypesField.get(constructor);4575} else {4576return constructor.getParameterTypes();4577}4578} catch (IllegalAccessException | IllegalArgumentException e) {4579throw newInternalError(e);4580}4581/*[ENDIF] JAVA_SPEC_VERSION >= 11 */4582}45834584static Class<?>[] getParameterTypes(Method method) {4585/*[IF JAVA_SPEC_VERSION >= 11]*/4586reflectionFactory = getReflectionFactory();4587return reflectionFactory.getExecutableSharedParameterTypes(method);4588/*[ELSE] JAVA_SPEC_VERSION >= 11*/4589try {4590if (null != methodParameterTypesField) {4591return (Class<?>[]) methodParameterTypesField.get(method);4592} else {4593return method.getParameterTypes();4594}4595} catch (IllegalAccessException | IllegalArgumentException e) {4596throw newInternalError(e);4597}4598/*[ENDIF] JAVA_SPEC_VERSION >= 11 */4599}46004601/*[PR 125873] Improve reflection cache */4602private static final class ReflectCache extends ConcurrentHashMap<CacheKey, ReflectRef> {4603private static final long serialVersionUID = 6551549321039776630L;46044605private final Class<?> owner;4606private final AtomicInteger useCount;46074608ReflectCache(Class<?> owner) {4609super();4610this.owner = owner;4611this.useCount = new AtomicInteger();4612}46134614ReflectCache acquire() {4615useCount.incrementAndGet();4616return this;4617}46184619void handleCleared(ReflectRef ref) {4620boolean removed = false;4621if (remove(ref.key, ref) && isEmpty()) {4622if (useCount.get() == 0) {4623owner.setReflectCache(null);4624removed = true;4625}4626}4627if (reflectCacheDebug) {4628if (removed) {4629System.err.println("Removed reflect cache for: " + this); //$NON-NLS-1$4630} else {4631System.err.println("Retained reflect cache for: " + this + ", size: " + size()); //$NON-NLS-1$ //$NON-NLS-2$4632}4633}4634}46354636Object find(CacheKey key) {4637ReflectRef ref = get(key);4638return ref != null ? ref.get() : null;4639}46404641void insert(CacheKey key, Object value) {4642put(key, new ReflectRef(this, key, value));4643}46444645<T> T insertIfAbsent(CacheKey key, T value) {4646ReflectRef newRef = new ReflectRef(this, key, value);4647for (;;) {4648ReflectRef oldRef = putIfAbsent(key, newRef);4649if (oldRef == null) {4650return value;4651}4652T oldValue = (T) oldRef.get();4653if (oldValue != null) {4654return oldValue;4655}4656// The entry addressed by key has been cleared, but not yet removed from this map.4657// One thread will successfully replace the entry; the value stored will be shared.4658if (replace(key, oldRef, newRef)) {4659return value;4660}4661}4662}46634664void release() {4665useCount.decrementAndGet();4666}46674668}46694670private transient ReflectCache reflectCache;4671private static long reflectCacheOffset = -1;46724673private ReflectCache acquireReflectCache() {4674ReflectCache cache = reflectCache;4675if (cache == null) {4676Unsafe theUnsafe = getUnsafe();4677long cacheOffset = getReflectCacheOffset();4678ReflectCache newCache = new ReflectCache(this);4679do {4680// Some thread will insert this new cache making it available to all.4681/*[IF Sidecar19-SE]*/4682if (theUnsafe.compareAndSetObject(this, cacheOffset, null, newCache)) {4683/*[ELSE]4684if (theUnsafe.compareAndSwapObject(this, cacheOffset, null, newCache)) {4685/*[ENDIF]*/4686cache = newCache;4687break;4688}4689cache = (ReflectCache) theUnsafe.getObject(this, cacheOffset);4690} while (cache == null);4691}4692return cache.acquire();4693}4694private static long getReflectCacheOffset() {4695long cacheOffset = reflectCacheOffset;4696if (cacheOffset < 0) {4697try {4698// Bypass the reflection cache to avoid infinite recursion.4699Field reflectCacheField = Class.class.getDeclaredFieldImpl("reflectCache"); //$NON-NLS-1$4700cacheOffset = getUnsafe().objectFieldOffset(reflectCacheField);4701reflectCacheOffset = cacheOffset;4702} catch (NoSuchFieldException e) {4703throw newInternalError(e);4704}4705}4706return cacheOffset;4707}4708void setReflectCache(ReflectCache cache) {4709// Lazy initialization of a non-volatile field. Ensure the Object is initialized4710// and flushed to memory before assigning to the annotationCache field.4711/*[IF Sidecar19-SE]4712getUnsafe().putObjectRelease(this, getReflectCacheOffset(), cache);4713/*[ELSE]*/4714getUnsafe().putOrderedObject(this, getReflectCacheOffset(), cache);4715/*[ENDIF]*/4716}47174718private ReflectCache peekReflectCache() {4719return reflectCache;4720}47214722static InternalError newInternalError(Exception cause) {4723return new InternalError(cause);4724}47254726private Method lookupCachedMethod(String methodName, Class<?>[] parameters) {4727if (!reflectCacheEnabled) return null;4728if (reflectCacheDebug) {4729reflectCacheDebugHelper(null, 0, "lookup Method: ", getName(), ".", methodName); //$NON-NLS-1$ //$NON-NLS-2$4730}4731ReflectCache cache = peekReflectCache();4732if (cache != null) {4733// use a null returnType to find the Method with the largest depth4734Method method = (Method) cache.find(CacheKey.newMethodKey(methodName, parameters, null));4735if (method != null) {4736try {4737Class<?>[] orgParams = getParameterTypes(method);4738// ensure the parameter classes are identical4739if (sameTypes(parameters, orgParams)) {4740/*[IF JAVA_SPEC_VERSION >= 11]*/4741reflectionFactory = getReflectionFactory();4742return (Method) reflectionFactory.copyMethod(method);4743/*[ELSE] JAVA_SPEC_VERSION >= 11*/4744return (Method) copyMethod.invoke(method, NoArgs);4745/*[ENDIF] JAVA_SPEC_VERSION >= 11 */4746}4747} catch (IllegalArgumentException4748/*[IF JAVA_SPEC_VERSION == 8]*/4749| IllegalAccessException | InvocationTargetException4750/*[ENDIF] JAVA_SPEC_VERSION == 8 */4751e) {4752throw newInternalError(e);4753}4754}4755}4756return null;4757}47584759@CallerSensitive4760private Method cacheMethod(Method method) {4761if (!reflectCacheEnabled) return method;4762if (reflectCacheAppOnly && ClassLoader.getStackClassLoader(2) == ClassLoader.bootstrapClassLoader) {4763return method;4764}4765/*[IF JAVA_SPEC_VERSION == 8]*/4766if (copyMethod == null) return method;4767/*[ENDIF] JAVA_SPEC_VERSION == 8 */4768if (reflectCacheDebug) {4769reflectCacheDebugHelper(null, 0, "cache Method: ", getName(), ".", method.getName()); //$NON-NLS-1$ //$NON-NLS-2$4770}4771try {4772Class<?>[] parameterTypes = getParameterTypes(method);4773CacheKey key = CacheKey.newMethodKey(method.getName(), parameterTypes, method.getReturnType());4774Class<?> declaringClass = method.getDeclaringClass();4775ReflectCache cache = declaringClass.acquireReflectCache();4776try {4777/*[PR CMVC 116493] store inherited methods in their declaringClass */4778method = cache.insertIfAbsent(key, method);4779} finally {4780if (declaringClass != this) {4781cache.release();4782cache = acquireReflectCache();4783}4784}4785try {4786// cache the Method with the largest depth with a null returnType4787CacheKey lookupKey = CacheKey.newMethodKey(method.getName(), parameterTypes, null);4788cache.insert(lookupKey, method);4789} finally {4790cache.release();4791}4792/*[IF JAVA_SPEC_VERSION >= 11]*/4793reflectionFactory = getReflectionFactory();4794return (Method) reflectionFactory.copyMethod(method);4795/*[ELSE] JAVA_SPEC_VERSION >= 11*/4796return (Method) copyMethod.invoke(method, NoArgs);4797/*[ENDIF] JAVA_SPEC_VERSION >= 11 */4798} catch (IllegalArgumentException4799/*[IF JAVA_SPEC_VERSION == 8]*/4800| IllegalAccessException | InvocationTargetException4801/*[ENDIF] JAVA_SPEC_VERSION == 8 */4802e) {4803throw newInternalError(e);4804}4805}48064807private Field lookupCachedField(String fieldName) {4808if (!reflectCacheEnabled) return null;4809if (reflectCacheDebug) {4810reflectCacheDebugHelper(null, 0, "lookup Field: ", getName(), ".", fieldName); //$NON-NLS-1$ //$NON-NLS-2$4811}4812ReflectCache cache = peekReflectCache();4813if (cache != null) {4814/*[PR 124746] Field cache cannot handle same field name with multiple types */4815Field field = (Field) cache.find(CacheKey.newFieldKey(fieldName, null));4816if (field != null) {4817try {4818/*[IF JAVA_SPEC_VERSION >= 11]*/4819reflectionFactory = getReflectionFactory();4820return (Field) reflectionFactory.copyField(field);4821/*[ELSE] JAVA_SPEC_VERSION >= 11*/4822return (Field) copyField.invoke(field, NoArgs);4823/*[ENDIF] JAVA_SPEC_VERSION >= 11 */4824} catch (IllegalArgumentException4825/*[IF JAVA_SPEC_VERSION == 8]*/4826| IllegalAccessException | InvocationTargetException4827/*[ENDIF] JAVA_SPEC_VERSION == 8 */4828e) {4829throw newInternalError(e);4830}4831}4832}4833return null;4834}48354836@CallerSensitive4837private Field cacheField(Field field) {4838if (!reflectCacheEnabled) return field;4839if (reflectCacheAppOnly && ClassLoader.getStackClassLoader(2) == ClassLoader.bootstrapClassLoader) {4840return field;4841}4842/*[IF JAVA_SPEC_VERSION == 8]*/4843if (copyField == null) return field;4844/*[ENDIF] JAVA_SPEC_VERSION == 8 */4845if (reflectCacheDebug) {4846reflectCacheDebugHelper(null, 0, "cache Field: ", getName(), ".", field.getName()); //$NON-NLS-1$ //$NON-NLS-2$4847}4848/*[PR 124746] Field cache cannot handle same field name with multiple types */4849CacheKey typedKey = CacheKey.newFieldKey(field.getName(), field.getType());4850Class<?> declaringClass = field.getDeclaringClass();4851ReflectCache cache = declaringClass.acquireReflectCache();4852try {4853field = cache.insertIfAbsent(typedKey, field);4854/*[PR 124746] Field cache cannot handle same field name with multiple types */4855if (declaringClass == this) {4856// cache the Field returned from getField() with a null returnType4857CacheKey lookupKey = CacheKey.newFieldKey(field.getName(), null);4858cache.insert(lookupKey, field);4859}4860} finally {4861cache.release();4862}4863try {4864/*[IF JAVA_SPEC_VERSION >= 11]*/4865reflectionFactory = getReflectionFactory();4866return (Field) reflectionFactory.copyField(field);4867/*[ELSE] JAVA_SPEC_VERSION >= 11*/4868return (Field) copyField.invoke(field, NoArgs);4869/*[ENDIF] JAVA_SPEC_VERSION >= 11 */4870} catch (IllegalArgumentException4871/*[IF JAVA_SPEC_VERSION == 8]*/4872| IllegalAccessException | InvocationTargetException4873/*[ENDIF] JAVA_SPEC_VERSION == 8 */4874e) {4875throw newInternalError(e);4876}4877}48784879private Constructor<T> lookupCachedConstructor(Class<?>[] parameters) {4880if (!reflectCacheEnabled) return null;48814882if (reflectCacheDebug) {4883reflectCacheDebugHelper(parameters, 1, "lookup Constructor: ", getName()); //$NON-NLS-1$4884}4885ReflectCache cache = peekReflectCache();4886if (cache != null) {4887Constructor<?> constructor = (Constructor<?>) cache.find(CacheKey.newConstructorKey(parameters));4888if (constructor != null) {4889Class<?>[] orgParams = getParameterTypes(constructor);4890try {4891// ensure the parameter classes are identical4892if (sameTypes(orgParams, parameters)) {4893/*[IF JAVA_SPEC_VERSION >= 11]*/4894reflectionFactory = getReflectionFactory();4895return (Constructor<T>) reflectionFactory.copyConstructor(constructor);4896/*[ELSE] JAVA_SPEC_VERSION >= 11*/4897return (Constructor<T>) copyConstructor.invoke(constructor, NoArgs);4898/*[ENDIF] JAVA_SPEC_VERSION >= 11 */4899}4900} catch (IllegalArgumentException4901/*[IF JAVA_SPEC_VERSION == 8]*/4902| IllegalAccessException | InvocationTargetException4903/*[ENDIF] JAVA_SPEC_VERSION == 8 */4904e) {4905throw newInternalError(e);4906}4907}4908}4909return null;4910}49114912@CallerSensitive4913private Constructor<T> cacheConstructor(Constructor<T> constructor) {4914if (!reflectCacheEnabled) return constructor;4915if (reflectCacheAppOnly && ClassLoader.getStackClassLoader(2) == ClassLoader.bootstrapClassLoader) {4916return constructor;4917}4918/*[IF JAVA_SPEC_VERSION == 8]*/4919if (copyConstructor == null) return constructor;4920/*[ENDIF] JAVA_SPEC_VERSION == 8 */4921if (reflectCacheDebug) {4922reflectCacheDebugHelper(constructor.getParameterTypes(), 1, "cache Constructor: ", getName()); //$NON-NLS-1$4923}4924ReflectCache cache = acquireReflectCache();4925try {4926CacheKey key = CacheKey.newConstructorKey(getParameterTypes(constructor));4927cache.insert(key, constructor);4928} finally {4929cache.release();4930}4931try {4932/*[IF JAVA_SPEC_VERSION >= 11]*/4933reflectionFactory = getReflectionFactory();4934return (Constructor<T>) reflectionFactory.copyConstructor(constructor);4935/*[ELSE] JAVA_SPEC_VERSION >= 11*/4936return (Constructor<T>) copyConstructor.invoke(constructor, NoArgs);4937/*[ENDIF] JAVA_SPEC_VERSION >= 11 */4938} catch (IllegalArgumentException4939/*[IF JAVA_SPEC_VERSION == 8]*/4940| IllegalAccessException | InvocationTargetException4941/*[ENDIF] JAVA_SPEC_VERSION == 8 */4942e) {4943throw newInternalError(e);4944}4945}49464947private static Method[] copyMethods(Method[] methods) {4948Method[] result = new Method[methods.length];4949try {4950/*[IF JAVA_SPEC_VERSION >= 11]*/4951reflectionFactory = getReflectionFactory();4952/*[ENDIF] JAVA_SPEC_VERSION >= 11 */4953for (int i=0; i<methods.length; i++) {4954/*[IF JAVA_SPEC_VERSION >= 11]*/4955result[i] = (Method) reflectionFactory.copyMethod(methods[i]);4956/*[ELSE] JAVA_SPEC_VERSION >= 11*/4957result[i] = (Method) copyMethod.invoke(methods[i], NoArgs);4958/*[ENDIF] JAVA_SPEC_VERSION >= 11 */4959}4960return result;4961} catch (IllegalArgumentException4962/*[IF JAVA_SPEC_VERSION == 8]*/4963| IllegalAccessException | InvocationTargetException4964/*[ENDIF] JAVA_SPEC_VERSION == 8 */4965e) {4966throw newInternalError(e);4967}4968}49694970private Method[] lookupCachedMethods(CacheKey cacheKey) {4971if (!reflectCacheEnabled) return null;49724973if (reflectCacheDebug) {4974reflectCacheDebugHelper(null, 0, "lookup Methods in: ", getName()); //$NON-NLS-1$4975}4976ReflectCache cache = peekReflectCache();4977if (cache != null) {4978Method[] methods = (Method[]) cache.find(cacheKey);4979if (methods != null) {4980return copyMethods(methods);4981}4982}4983return null;4984}49854986@CallerSensitive4987private Method[] cacheMethods(Method[] methods, CacheKey cacheKey) {4988if (!reflectCacheEnabled) return methods;4989if (reflectCacheAppOnly && ClassLoader.getStackClassLoader(2) == ClassLoader.bootstrapClassLoader) {4990return methods;4991}4992/*[IF JAVA_SPEC_VERSION == 8]*/4993if (copyMethod == null) return methods;4994/*[ENDIF] JAVA_SPEC_VERSION == 8 */4995if (reflectCacheDebug) {4996reflectCacheDebugHelper(null, 0, "cache Methods in: ", getName()); //$NON-NLS-1$4997}4998ReflectCache cache = null;4999Class<?> cacheOwner = null;5000try {5001for (int i = 0; i < methods.length; ++i) {5002Method method = methods[i];5003CacheKey key = CacheKey.newMethodKey(method.getName(), getParameterTypes(method), method.getReturnType());5004Class<?> declaringClass = method.getDeclaringClass();5005if (cacheOwner != declaringClass || cache == null) {5006if (cache != null) {5007cache.release();5008cache = null;5009}5010cache = declaringClass.acquireReflectCache();5011cacheOwner = declaringClass;5012}5013methods[i] = cache.insertIfAbsent(key, method);5014}5015if (cache != null && cacheOwner != this) {5016cache.release();5017cache = null;5018}5019if (cache == null) {5020cache = acquireReflectCache();5021}5022cache.insert(cacheKey, methods);5023} finally {5024if (cache != null) {5025cache.release();5026}5027}5028return copyMethods(methods);5029}50305031private static Field[] copyFields(Field[] fields) {5032Field[] result = new Field[fields.length];5033try {5034/*[IF JAVA_SPEC_VERSION >= 11]*/5035reflectionFactory = getReflectionFactory();5036/*[ENDIF] JAVA_SPEC_VERSION >= 11 */5037for (int i=0; i<fields.length; i++) {5038/*[IF JAVA_SPEC_VERSION >= 11]*/5039result[i] = (Field) reflectionFactory.copyField(fields[i]);5040/*[ELSE] JAVA_SPEC_VERSION >= 11*/5041result[i] = (Field) copyField.invoke(fields[i], NoArgs);5042/*[ENDIF] JAVA_SPEC_VERSION >= 11 */5043}5044return result;5045} catch (IllegalArgumentException5046/*[IF JAVA_SPEC_VERSION == 8]*/5047| IllegalAccessException | InvocationTargetException5048/*[ENDIF] JAVA_SPEC_VERSION == 8 */5049e) {5050throw newInternalError(e);5051}5052}50535054private Field[] lookupCachedFields(CacheKey cacheKey) {5055if (!reflectCacheEnabled) return null;50565057if (reflectCacheDebug) {5058reflectCacheDebugHelper(null, 0, "lookup Fields in: ", getName()); //$NON-NLS-1$5059}5060ReflectCache cache = peekReflectCache();5061if (cache != null) {5062Field[] fields = (Field[]) cache.find(cacheKey);5063if (fields != null) {5064return copyFields(fields);5065}5066}5067return null;5068}50695070@CallerSensitive5071private Field[] cacheFields(Field[] fields, CacheKey cacheKey) {5072if (!reflectCacheEnabled) return fields;5073if (reflectCacheAppOnly && ClassLoader.getStackClassLoader(2) == ClassLoader.bootstrapClassLoader) {5074return fields;5075}5076/*[IF JAVA_SPEC_VERSION == 8]*/5077if (copyField == null) return fields;5078/*[ENDIF] JAVA_SPEC_VERSION == 8 */5079if (reflectCacheDebug) {5080reflectCacheDebugHelper(null, 0, "cache Fields in: ", getName()); //$NON-NLS-1$5081}5082ReflectCache cache = null;5083Class<?> cacheOwner = null;5084try {5085for (int i = 0; i < fields.length; ++i) {5086/*[PR 124746] Field cache cannot handle same field name with multiple types */5087Field field = fields[i];5088Class<?> declaringClass = field.getDeclaringClass();5089if (cacheOwner != declaringClass || cache == null) {5090if (cache != null) {5091cache.release();5092cache = null;5093}5094cache = declaringClass.acquireReflectCache();5095cacheOwner = declaringClass;5096}5097fields[i] = cache.insertIfAbsent(CacheKey.newFieldKey(field.getName(), field.getType()), field);5098}5099if (cache != null && cacheOwner != this) {5100cache.release();5101cache = null;5102}5103if (cache == null) {5104cache = acquireReflectCache();5105}5106cache.insert(cacheKey, fields);5107} finally {5108if (cache != null) {5109cache.release();5110}5111}5112return copyFields(fields);5113}51145115private static <T> Constructor<T>[] copyConstructors(Constructor<T>[] constructors) {5116Constructor<T>[] result = new Constructor[constructors.length];5117try {5118/*[IF JAVA_SPEC_VERSION >= 11]*/5119reflectionFactory = getReflectionFactory();5120/*[ENDIF] JAVA_SPEC_VERSION >= 11 */5121for (int i=0; i<constructors.length; i++) {5122/*[IF JAVA_SPEC_VERSION >= 11]*/5123result[i] = (Constructor<T>) reflectionFactory.copyConstructor(constructors[i]);5124/*[ELSE] JAVA_SPEC_VERSION >= 11*/5125result[i] = (Constructor<T>) copyConstructor.invoke(constructors[i], NoArgs);5126/*[ENDIF] JAVA_SPEC_VERSION >= 11 */5127}5128return result;5129} catch (IllegalArgumentException5130/*[IF JAVA_SPEC_VERSION == 8]*/5131| IllegalAccessException | InvocationTargetException5132/*[ENDIF] JAVA_SPEC_VERSION == 8 */5133e) {5134throw newInternalError(e);5135}5136}51375138private Constructor<T>[] lookupCachedConstructors(CacheKey cacheKey) {5139if (!reflectCacheEnabled) return null;51405141if (reflectCacheDebug) {5142reflectCacheDebugHelper(null, 0, "lookup Constructors in: ", getName()); //$NON-NLS-1$5143}5144ReflectCache cache = peekReflectCache();5145if (cache != null) {5146Constructor<T>[] constructors = (Constructor<T>[]) cache.find(cacheKey);5147if (constructors != null) {5148return copyConstructors(constructors);5149}5150}5151return null;5152}51535154@CallerSensitive5155private Constructor<T>[] cacheConstructors(Constructor<T>[] constructors, CacheKey cacheKey) {5156if (!reflectCacheEnabled) return constructors;5157if (reflectCacheAppOnly && ClassLoader.getStackClassLoader(2) == ClassLoader.bootstrapClassLoader) {5158return constructors;5159}5160/*[IF JAVA_SPEC_VERSION == 8]*/5161if (copyConstructor == null) return constructors;5162/*[ENDIF] JAVA_SPEC_VERSION == 8 */5163if (reflectCacheDebug) {5164reflectCacheDebugHelper(null, 0, "cache Constructors in: ", getName()); //$NON-NLS-1$5165}5166ReflectCache cache = acquireReflectCache();5167try {5168for (int i=0; i<constructors.length; i++) {5169CacheKey key = CacheKey.newConstructorKey(getParameterTypes(constructors[i]));5170constructors[i] = cache.insertIfAbsent(key, constructors[i]);5171}5172cache.insert(cacheKey, constructors);5173} finally {5174cache.release();5175}5176return copyConstructors(constructors);5177}51785179private static <T> Constructor<T> checkParameterTypes(Constructor<T> constructor, Class<?>[] parameterTypes) {5180Class<?>[] constructorParameterTypes = getParameterTypes(constructor);5181return sameTypes(constructorParameterTypes, parameterTypes) ? constructor : null;5182}51835184static boolean sameTypes(Class<?>[] aTypes, Class<?>[] bTypes) {5185if (aTypes == null) {5186if (bTypes == null) {5187return true;5188}5189} else if (bTypes != null) {5190int length = aTypes.length;5191if (length == bTypes.length) {5192for (int i = 0; i < length; ++i) {5193if (aTypes[i] != bTypes[i]) {5194return false;5195}5196}5197return true;5198}5199}5200return false;5201}52025203Object getMethodHandleCache() {5204return methodHandleCache;5205}52065207Object setMethodHandleCache(Object cache) {5208Object result = methodHandleCache;5209if (null == result) {5210synchronized (this) {5211result = methodHandleCache;5212if (null == result) {5213methodHandleCache = cache;5214result = cache;5215}5216}5217}5218return result;5219}52205221ConstantPool getConstantPool(Object internalCP) {5222return VM.getVMLangAccess().getConstantPool(internalCP);5223}52245225/*[IF Sidecar19-SE]*/5226Map<Class<? extends Annotation>, Annotation> getDeclaredAnnotationMap() {5227throw new Error("Class.getDeclaredAnnotationMap() unimplemented"); //$NON-NLS-1$5228}5229byte[] getRawAnnotations() {5230throw new Error("Class.getRawAnnotations() unimplemented"); //$NON-NLS-1$5231}5232byte[] getRawTypeAnnotations() {5233throw new Error("Class.getRawTypeAnnotations() unimplemented"); //$NON-NLS-1$5234}5235static byte[] getExecutableTypeAnnotationBytes(Executable exec) {5236throw new Error("Class.getExecutableTypeAnnotationBytes() unimplemented"); //$NON-NLS-1$5237}5238/*[ENDIF] Sidecar19-SE*/52395240/*[IF JAVA_SPEC_VERSION >= 11]*/5241/**5242* Answers the host class of the receiver's nest.5243*5244* @return the host class of the receiver.5245*/5246private native Class<?> getNestHostImpl();52475248/**5249* Answers the nest member classes of the receiver's nest host.5250*5251* @return the host class of the receiver.5252*5253* @implNote This implementation does not remove duplicate nest members if they are present.5254*/5255private native Class<?>[] getNestMembersImpl();52565257/**5258* Answers the host class of the receiver's nest.5259*5260* @throws SecurityException if nestHost is not same as the current class, a security manager5261* is present, the classloader of the caller is not the same or an ancestor of nestHost5262* class, and checkPackageAccess() denies access5263* @return the host class of the receiver.5264*/5265@CallerSensitive5266public Class<?> getNestHost() throws SecurityException {5267if (nestHost == null) {5268nestHost = getNestHostImpl();5269}5270/* The specification requires that if:5271* - the returned class is not the current class5272* - a security manager is present5273* - the caller's class loader is not the same or an ancestor of the returned class5274* - s.checkPackageAccess() disallows access to the package of the returned class5275* then throw a SecurityException.5276*/5277if (nestHost != this) {5278@SuppressWarnings("removal")5279SecurityManager securityManager = System.getSecurityManager();5280if (securityManager != null) {5281ClassLoader callerClassLoader = ClassLoader.getCallerClassLoader();5282ClassLoader nestHostClassLoader = nestHost.internalGetClassLoader();5283if (!doesClassLoaderDescendFrom(nestHostClassLoader, callerClassLoader)) {5284String nestHostPackageName = nestHost.getPackageName();5285if ((nestHostPackageName != null) && (nestHostPackageName != "")) {5286securityManager.checkPackageAccess(nestHostPackageName);5287}5288}5289}5290}5291return nestHost;5292}52935294/**5295* Returns true if the class passed has the same nest top as this class.5296*5297* @param that The class to compare5298* @return true if class is a nestmate of this class; false otherwise.5299*5300*/5301public boolean isNestmateOf(Class<?> that) {5302Class<?> thisNestHost = this.nestHost;5303if (thisNestHost == null) {5304thisNestHost = this.getNestHostImpl();5305}5306Class<?> thatNestHost = that.nestHost;5307if (thatNestHost == null) {5308thatNestHost = that.getNestHostImpl();5309}5310return (thisNestHost == thatNestHost);5311}53125313/**5314* Answers the nest member classes of the receiver's nest host.5315*5316* @throws SecurityException if a SecurityManager is present and package access is not allowed5317/*[IF JAVA_SPEC_VERSION < 15]5318* @throws LinkageError if there is any problem loading or validating a nest member or the nest host5319/*[ENDIF]5320* @throws SecurityException if a returned class is not the current class, a security manager is enabled,5321* the caller's class loader is not the same or an ancestor of that returned class, and the5322* checkPackageAccess() denies access5323* @return the host class of the receiver.5324*/5325@CallerSensitive5326public Class<?>[] getNestMembers() throws5327/*[IF JAVA_SPEC_VERSION < 15] */5328LinkageError,5329/*[ENDIF] JAVA_SPEC_VERSION < 15 */5330SecurityException {5331if (isArray() || isPrimitive()) {5332/* By spec, Class objects representing array types or primitive types5333* belong to the nest consisting only of itself.5334*/5335return new Class<?>[] { this };5336}53375338Class<?>[] members = getNestMembersImpl();5339/* Skip security check for the Class object that belongs to the nest consisting only of itself */5340if (members.length > 1) {5341@SuppressWarnings("removal")5342SecurityManager securityManager = System.getSecurityManager();5343if (securityManager != null) {5344/* All classes in a nest must be in the same runtime package and therefore same classloader */5345ClassLoader nestMemberClassLoader = this.internalGetClassLoader();5346ClassLoader callerClassLoader = ClassLoader.getCallerClassLoader();5347if (!doesClassLoaderDescendFrom(nestMemberClassLoader, callerClassLoader)) {5348String nestMemberPackageName = this.getPackageName();5349if ((nestMemberPackageName != null) && (nestMemberPackageName != "")) { //$NON-NLS-1$5350securityManager.checkPackageAccess(nestMemberPackageName);5351}5352}5353}5354}53555356return members;5357}5358/*[ENDIF] JAVA_SPEC_VERSION >= 11 */53595360/*[IF JAVA_SPEC_VERSION >= 12]*/5361/**5362* Create class of an array. The component type will be this Class instance.5363*5364* @return array class where the component type is this Class instance5365*/5366public Class<?> arrayType() {5367if (this == void.class) {5368throw new IllegalArgumentException();5369}5370return arrayTypeImpl();5371}53725373private native Class<?> arrayTypeImpl();53745375/**5376* Answers a Class object which represents the receiver's component type if the receiver5377* represents an array type. The component type of an array type is the type of the elements5378* of the array.5379*5380* @return the component type of the receiver. Returns null if the receiver does5381* not represent an array.5382*/5383public Class<?> componentType() {5384return getComponentType();5385}53865387/**5388* Returns the nominal descriptor of this Class instance, or an empty Optional5389* if construction is not possible.5390*5391* @return Optional with a nominal descriptor of Class instance5392*/5393public Optional<ClassDesc> describeConstable() {5394/*[IF JAVA_SPEC_VERSION >= 15]*/5395Class<?> clazz = this;5396if (isArray()) {5397clazz = getComponentType();5398while (clazz.isArray()) {5399clazz = clazz.getComponentType();5400}5401}5402if (clazz.isHidden()) {5403/* It is always an empty Optional for hidden classes. */5404return Optional.empty();5405}5406/*[ENDIF] JAVA_SPEC_VERSION >= 15 */54075408ClassDesc classDescriptor = ClassDesc.ofDescriptor(this.descriptorString());5409return Optional.of(classDescriptor);5410}54115412/**5413* Return field descriptor of Class instance.5414*5415* @return field descriptor of Class instance5416*/5417public String descriptorString() {5418/* see MethodTypeHelper.getBytecodeStringName */54195420if (this.isPrimitive()) {5421if (this == int.class) {5422return "I"; //$NON-NLS-1$5423} else if (this == long.class) {5424return "J"; //$NON-NLS-1$5425} else if (this == byte.class) {5426return "B"; //$NON-NLS-1$5427} else if (this == boolean.class) {5428return "Z"; //$NON-NLS-1$5429} else if (this == void.class) {5430return "V"; //$NON-NLS-1$5431} else if (this == char.class) {5432return "C"; //$NON-NLS-1$5433} else if (this == double.class) {5434return "D"; //$NON-NLS-1$5435} else if (this == float.class) {5436return "F"; //$NON-NLS-1$5437} else if (this == short.class) {5438return "S"; //$NON-NLS-1$5439}5440}5441String name = this.getName().replace('.', '/');5442/*[IF JAVA_SPEC_VERSION >= 15]*/5443Class<?> clazz = this;5444if (isArray()) {5445clazz = getComponentType();5446while (clazz.isArray()) {5447clazz = clazz.getComponentType();5448}5449}5450if (clazz.isHidden()) {5451/* descriptor String of hidden class is something like: "Lpackage/ClassName.romaddress;". */5452int index = name.lastIndexOf('/');5453name = name.substring(0, index)+ '.' + name.substring(index + 1,name.length());5454}5455/*[ENDIF] JAVA_SPEC_VERSION >= 15 */5456if (this.isArray()) {5457}5458/*[IF INLINE-TYPES]*/5459else if (this.isPrimitiveClass()) {5460name = new StringBuilder(name.length() + 2).5461append('Q').append(name).append(';').toString();5462}5463/*[ENDIF] INLINE-TYPES */5464else {5465name = new StringBuilder(name.length() + 2).5466append('L').append(name).append(';').toString();5467}5468return name;5469}5470/*[ENDIF] JAVA_SPEC_VERSION >= 12 */54715472/*[IF JAVA_SPEC_VERSION >= 14]*/5473/**5474* Returns true if the class instance is a record.5475*5476* @return true for a record class, false otherwise5477*/5478public boolean isRecord() {5479/*[IF JAVA_SPEC_VERSION >= 16]*/5480Class superclazz = getSuperclass();5481return ((superclazz == Record.class) && isRecordImpl());5482/*[ELSE] JAVA_SPEC_VERSION >= 16*/5483return isRecordImpl();5484/*[ENDIF] JAVA_SPEC_VERSION >= 16*/5485}54865487private native boolean isRecordImpl();54885489/**5490* Returns an array of RecordComponent objects for a record class.5491*5492* @return array of RecordComponent objects, one for each component in the record.5493* For a class that is not a record, null is returned.5494* For a record with no components an empty array is returned.5495*5496* @throws SecurityException if declared member access or package access is not allowed5497*/5498@CallerSensitive5499public RecordComponent[] getRecordComponents() {5500@SuppressWarnings("removal")5501SecurityManager security = System.getSecurityManager();5502if (security != null) {5503ClassLoader callerClassLoader = ClassLoader.getStackClassLoader(1);5504checkMemberAccess(security, callerClassLoader, Member.DECLARED);5505}55065507if (!isRecord()) {5508return null;5509}55105511return getRecordComponentsImpl();5512}55135514private native RecordComponent[] getRecordComponentsImpl();5515/*[ENDIF] JAVA_SPEC_VERSION >= 14 */55165517/*[IF JAVA_SPEC_VERSION >= 15]*/5518/**5519* Returns true if class or interface is sealed.5520*5521* @return true if class is sealed, false otherwise5522*/5523public native boolean isSealed();55245525private native boolean isHiddenImpl();5526/**5527* Returns true if the class is a hidden class.5528*5529* @return true for a hidden class, false otherwise5530*/5531public boolean isHidden() {5532return isHiddenImpl();5533}55345535/**5536* Returns the classData stored in the class.5537*5538* @return the classData (Object).5539*/5540Object getClassData() {5541return classData;5542}55435544private native String[] permittedSubclassesImpl();5545/*[ENDIF] JAVA_SPEC_VERSION >= 15 */55465547/*[IF JAVA_SPEC_VERSION >= 16]*/5548/**5549* Returns the permitted subclasses related to the calling sealed class as an array5550* of Class objects. If the calling class is not a sealed class, is an array class,5551* or is primitive, then this method returns null instead.5552* The order of any classes returned in the array is unspecified, and any classes5553* that cannot be loaded are not included in the returned array. The returned array5554* may be empty if there are no permitted subclasses.5555*5556* @return array of Class objects if permitted subclasses exist or null if not a sealed class.5557*5558* @throws SecurityException if access to any of the classes returned in the array is denied5559*5560* @since 165561*/5562@CallerSensitive5563public Class<?>[] getPermittedSubclasses() throws SecurityException {5564if (!isSealed()) {5565return null;5566}5567Class<?>[] localPermittedSubclasses = cachedPermittedSubclasses;5568if (null == localPermittedSubclasses) {5569String[] permittedSubclassesNames = permittedSubclassesImpl();5570ArrayList<Class<?>> permittedSubclasses = new ArrayList<>(permittedSubclassesNames.length);55715572for (int i = 0; i < permittedSubclassesNames.length; i++) {5573String subclassName = permittedSubclassesNames[i];5574try {5575Class<?> permitted = forNameImpl(subclassName, false, this.classLoader);5576permittedSubclasses.add(permitted);5577} catch (ClassNotFoundException e) {5578// do nothing if class not found5579}5580}5581localPermittedSubclasses = permittedSubclasses.toArray(new Class<?>[0]);55825583long localPermittedSubclassesCacheOffset = cachedPermittedSubclassesOffset;5584if (-1 == localPermittedSubclassesCacheOffset) {5585localPermittedSubclassesCacheOffset = getUnsafe().objectFieldOffset(Class.class, "cachedPermittedSubclasses");5586cachedPermittedSubclassesOffset = localPermittedSubclassesCacheOffset;5587}5588getUnsafe().putObjectRelease(this, localPermittedSubclassesCacheOffset, localPermittedSubclasses);5589}55905591@SuppressWarnings("removal")5592SecurityManager sm = System.getSecurityManager();5593if (null != sm) {5594HashSet<String> packages = new HashSet<>();5595ClassLoader callerClassLoader = ClassLoader.getCallerClassLoader();5596for (int i = 0; i < localPermittedSubclasses.length; i++) {5597ClassLoader subClassLoader = localPermittedSubclasses[i].internalGetClassLoader();5598if (sun.reflect.misc.ReflectUtil.needsPackageAccessCheck(callerClassLoader, subClassLoader)) {5599String pkgName = localPermittedSubclasses[i].getPackageName();5600if ((pkgName != null) && (pkgName != "")) {5601packages.add(pkgName);5602}5603}5604}5605for (String pkgName : packages) {5606sm.checkPackageAccess(pkgName);5607}5608}56095610return localPermittedSubclasses;5611}5612/*[ENDIF] JAVA_SPEC_VERSION >= 16 */56135614/*[IF JAVA_SPEC_VERSION >= 11]*/5615@SuppressWarnings("removal")5616private static ReflectionFactory getReflectionFactory() {5617if (reflectionFactory == null) {5618reflectionFactory = AccessController.doPrivileged(new ReflectionFactory.GetReflectionFactoryAction());5619}5620return reflectionFactory;5621}5622/*[ENDIF] JAVA_SPEC_VERSION >= 11 */56235624}562556265627