Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/openj9
Path: blob/master/jcl/src/java.base/share/classes/java/lang/Class.java
12513 views
1
/*[INCLUDE-IF JAVA_SPEC_VERSION >= 8]*/
2
/*******************************************************************************
3
* Copyright (c) 1998, 2022 IBM Corp. and others
4
*
5
* This program and the accompanying materials are made available under
6
* the terms of the Eclipse Public License 2.0 which accompanies this
7
* distribution and is available at https://www.eclipse.org/legal/epl-2.0/
8
* or the Apache License, Version 2.0 which accompanies this distribution and
9
* is available at https://www.apache.org/licenses/LICENSE-2.0.
10
*
11
* This Source Code may also be made available under the following
12
* Secondary Licenses when the conditions for such availability set
13
* forth in the Eclipse Public License, v. 2.0 are satisfied: GNU
14
* General Public License, version 2 with the GNU Classpath
15
* Exception [1] and GNU General Public License, version 2 with the
16
* OpenJDK Assembly Exception [2].
17
*
18
* [1] https://www.gnu.org/software/classpath/license.html
19
* [2] http://openjdk.java.net/legal/assembly-exception.html
20
*
21
* 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-exception
22
*******************************************************************************/
23
package java.lang;
24
25
import java.io.InputStream;
26
import java.security.AccessControlContext;
27
import java.security.ProtectionDomain;
28
import java.security.Permissions;
29
/*[IF JAVA_SPEC_VERSION >= 12]*/
30
import java.lang.constant.ClassDesc;
31
/*[ENDIF] JAVA_SPEC_VERSION >= 12*/
32
/*[IF JAVA_SPEC_VERSION >= 11]*/
33
import jdk.internal.reflect.ReflectionFactory;
34
/*[ENDIF] JAVA_SPEC_VERSION >= 11*/
35
import java.lang.reflect.*;
36
import java.net.URL;
37
import java.lang.annotation.*;
38
import java.util.Collection;
39
import java.util.HashMap;
40
/*[IF JAVA_SPEC_VERSION >= 16]*/
41
import java.util.HashSet;
42
/*[ENDIF] JAVA_SPEC_VERSION >= 16 */
43
import java.util.LinkedHashMap;
44
import java.util.List;
45
import java.util.Map;
46
import java.util.Set;
47
/*[IF JAVA_SPEC_VERSION >= 12]*/
48
import java.util.Optional;
49
/*[ENDIF] JAVA_SPEC_VERSION >= 12 */
50
import java.util.concurrent.ConcurrentHashMap;
51
import java.util.concurrent.atomic.AtomicInteger;
52
import java.security.AccessController;
53
import java.security.PrivilegedExceptionAction;
54
import java.security.PrivilegedAction;
55
import java.lang.ref.*;
56
/*[IF JAVA_SPEC_VERSION >= 12]*/
57
import java.lang.constant.ClassDesc;
58
import java.lang.constant.Constable;
59
/*[ENDIF] JAVA_SPEC_VERSION >= 12 */
60
61
import sun.reflect.generics.repository.ClassRepository;
62
import sun.reflect.generics.factory.CoreReflectionFactory;
63
import sun.reflect.generics.scope.ClassScope;
64
import sun.reflect.annotation.AnnotationType;
65
import java.util.Arrays;
66
import com.ibm.oti.vm.VM;
67
/*[IF JAVA_SPEC_VERSION >= 11]*/
68
import static com.ibm.oti.util.Util.doesClassLoaderDescendFrom;
69
/*[ENDIF] JAVA_SPEC_VERSION >= 11*/
70
71
/*[IF Sidecar19-SE]
72
import jdk.internal.misc.Unsafe;
73
/*[IF JAVA_SPEC_VERSION >= 15]*/
74
import jdk.internal.access.SharedSecrets;
75
/*[ELSE] JAVA_SPEC_VERSION >= 15
76
import jdk.internal.misc.SharedSecrets;
77
/*[ENDIF] JAVA_SPEC_VERSION >= 15 */
78
import java.io.IOException;
79
import jdk.internal.reflect.Reflection;
80
import jdk.internal.reflect.CallerSensitive;
81
import jdk.internal.reflect.ConstantPool;
82
/*[ELSE]*/
83
import sun.misc.Unsafe;
84
import sun.misc.SharedSecrets;
85
import sun.reflect.Reflection;
86
import sun.reflect.CallerSensitive;
87
import sun.reflect.ConstantPool;
88
/*[ENDIF]*/
89
90
import java.util.ArrayList;
91
import java.lang.annotation.Repeatable;
92
import java.lang.invoke.*;
93
import com.ibm.oti.reflect.TypeAnnotationParser;
94
import java.security.PrivilegedActionException;
95
import sun.security.util.SecurityConstants;
96
97
/*[IF JAVA_SPEC_VERSION >= 18]*/
98
import jdk.internal.reflect.CallerSensitiveAdapter;
99
/*[ENDIF] JAVA_SPEC_VERSION >= 18 */
100
101
/**
102
* An instance of class Class is the in-image representation
103
* of a Java class. There are three basic types of Classes
104
* <dl>
105
* <dt><em>Classes representing object types (classes or interfaces)</em></dt>
106
* <dd>These are Classes which represent the class of a
107
* simple instance as found in the class hierarchy.
108
* The name of one of these Classes is simply the
109
* fully qualified class name of the class or interface
110
* that it represents. Its <em>signature</em> is
111
* the letter "L", followed by its name, followed
112
* by a semi-colon (";").</dd>
113
* <dt><em>Classes representing base types</em></dt>
114
* <dd>These Classes represent the standard Java base types.
115
* Although it is not possible to create new instances
116
* of these Classes, they are still useful for providing
117
* reflection information, and as the component type
118
* of array classes. There is one of these Classes for
119
* each base type, and their signatures are:
120
* <ul>
121
* <li><code>B</code> representing the <code>byte</code> base type</li>
122
* <li><code>S</code> representing the <code>short</code> base type</li>
123
* <li><code>I</code> representing the <code>int</code> base type</li>
124
* <li><code>J</code> representing the <code>long</code> base type</li>
125
* <li><code>F</code> representing the <code>float</code> base type</li>
126
* <li><code>D</code> representing the <code>double</code> base type</li>
127
* <li><code>C</code> representing the <code>char</code> base type</li>
128
* <li><code>Z</code> representing the <code>boolean</code> base type</li>
129
* <li><code>V</code> representing void function return values</li>
130
* </ul>
131
* The name of a Class representing a base type
132
* is the keyword which is used to represent the
133
* type in Java source code (i.e. "int" for the
134
* <code>int</code> base type.</dd>
135
* <dt><em>Classes representing array classes</em></dt>
136
* <dd>These are Classes which represent the classes of
137
* Java arrays. There is one such Class for all array
138
* instances of a given arity (number of dimensions)
139
* and leaf component type. In this case, the name of the
140
* class is one or more left square brackets (one per
141
* dimension in the array) followed by the signature ofP
142
* the class representing the leaf component type, which
143
* can be either an object type or a base type. The
144
* signature of a Class representing an array type
145
* is the same as its name.</dd>
146
* </dl>
147
*
148
* @author OTI
149
* @version initial
150
*/
151
public final class Class<T> implements java.io.Serializable, GenericDeclaration, Type
152
/*[IF JAVA_SPEC_VERSION >= 12]*/
153
, Constable, TypeDescriptor, TypeDescriptor.OfField<Class<?>>
154
/*[ENDIF] JAVA_SPEC_VERSION >= 12 */
155
{
156
private static final long serialVersionUID = 3206093459760846163L;
157
private static ProtectionDomain AllPermissionsPD;
158
private static final int SYNTHETIC = 0x1000;
159
private static final int ANNOTATION = 0x2000;
160
private static final int ENUM = 0x4000;
161
private static final int MEMBER_INVALID_TYPE = -1;
162
163
/*[IF]*/
164
/**
165
* It is important that these remain static final
166
* because the VM peeks for them before running the <clinit>
167
*/
168
/*[ENDIF]*/
169
static final Class<?>[] EmptyParameters = new Class<?>[0];
170
171
/*[PR VMDESIGN 485]*/
172
private transient long vmRef;
173
private transient ClassLoader classLoader;
174
175
/*[IF Sidecar19-SE]*/
176
private transient Module module;
177
/*[ENDIF]*/
178
179
/*[PR CMVC 125822] Move RAM class fields onto the heap to fix hotswap crash */
180
private transient ProtectionDomain protectionDomain;
181
private transient String classNameString;
182
183
/* Cache filename on Class to avoid repeated lookups / allocations in stack traces */
184
private transient String fileNameString;
185
186
/* Cache the packageName of the Class */
187
private transient String packageNameString;
188
189
private static final class AnnotationVars {
190
AnnotationVars() {}
191
static long annotationTypeOffset = -1;
192
static long valueMethodOffset = -1;
193
194
/*[PR 66931] annotationType should be volatile because we use compare and swap */
195
volatile AnnotationType annotationType;
196
MethodHandle valueMethod;
197
}
198
private transient AnnotationVars annotationVars;
199
private static long annotationVarsOffset = -1;
200
201
/*[PR JAZZ 55717] add Java 8 new field: transient ClassValue.ClassValueMap classValueMap */
202
/*[PR CMVC 200702] New field to support changes for RI defect 7030453 */
203
transient ClassValue.ClassValueMap classValueMap;
204
205
private static final class EnumVars<T> {
206
EnumVars() {}
207
static long enumDirOffset = -1;
208
static long enumConstantsOffset = -1;
209
210
Map<String, T> cachedEnumConstantDirectory;
211
/*[PR CMVC 188840] Perf: Class.getEnumConstants() is slow */
212
T[] cachedEnumConstants;
213
}
214
private transient EnumVars<T> enumVars;
215
private static long enumVarsOffset = -1;
216
217
transient J9VMInternals.ClassInitializationLock initializationLock;
218
219
private transient Object methodHandleCache;
220
221
/*[PR Jazz 85476] Address locking contention on classRepository in getGeneric*() methods */
222
private transient ClassRepositoryHolder classRepoHolder;
223
224
/*[IF JAVA_SPEC_VERSION >= 11]*/
225
private static ReflectionFactory reflectionFactory;
226
/*[ENDIF] JAVA_SPEC_VERSION >= 11 */
227
228
/* Helper class to hold the ClassRepository. We use a Class with a final
229
* field to ensure that we have both safe initialization and safe publication.
230
*/
231
private static final class ClassRepositoryHolder {
232
static final ClassRepositoryHolder NullSingleton = new ClassRepositoryHolder(null);
233
final ClassRepository classRepository;
234
235
ClassRepositoryHolder(ClassRepository classRepo) {
236
classRepository = classRepo;
237
}
238
}
239
240
private static final class AnnotationCache {
241
final LinkedHashMap<Class<? extends Annotation>, Annotation> directAnnotationMap;
242
final LinkedHashMap<Class<? extends Annotation>, Annotation> annotationMap;
243
AnnotationCache(
244
LinkedHashMap<Class<? extends Annotation>, Annotation> directMap,
245
LinkedHashMap<Class<? extends Annotation>, Annotation> annMap
246
) {
247
directAnnotationMap = directMap;
248
annotationMap = annMap;
249
}
250
}
251
private transient AnnotationCache annotationCache;
252
private static long annotationCacheOffset = -1;
253
private static boolean reflectCacheEnabled;
254
private static boolean reflectCacheDebug;
255
private static boolean reflectCacheAppOnly = true;
256
257
/*
258
* This {@code ClassReflectNullPlaceHolder} class is created to indicate the cached class value is
259
* initialized to null rather than the default value null ;e.g. {@code cachedDeclaringClass}
260
* and {@code cachedEnclosingClass}. The reason default value has to be null is that
261
* j.l.Class instances are created by the VM only rather than Java, and
262
* any instance field with non-null default values have to be set by VM natives.
263
*/
264
private static final class ClassReflectNullPlaceHolder {}
265
266
private static final class MetadataCache {
267
MetadataCache() {}
268
269
static long cachedCanonicalNameOffset = -1;
270
static long cachedSimpleNameOffset = -1;
271
272
SoftReference<String> cachedCanonicalName;
273
SoftReference<String> cachedSimpleName;
274
}
275
276
private transient MetadataCache metadataCache;
277
private static long metadataCacheOffset = -1;
278
279
private transient Class<?>[] cachedInterfaces;
280
private static long cachedInterfacesOffset = -1;
281
282
private transient Class<?> cachedDeclaringClass;
283
private static long cachedDeclaringClassOffset = -1;
284
285
private transient Class<?> cachedEnclosingClass;
286
private static long cachedEnclosingClassOffset = -1;
287
288
private transient boolean cachedCheckInnerClassAttr;
289
290
private static Annotation[] EMPTY_ANNOTATION_ARRAY = new Annotation[0];
291
292
static MethodHandles.Lookup implLookup;
293
294
private static final Unsafe unsafe = Unsafe.getUnsafe();
295
296
static Unsafe getUnsafe() {
297
return unsafe;
298
}
299
300
/*[IF JAVA_SPEC_VERSION >= 11]*/
301
private Class<?> nestHost;
302
/*[ENDIF] JAVA_SPEC_VERSION >= 11 */
303
304
/*[IF JAVA_SPEC_VERSION >= 15]*/
305
private transient Object classData;
306
/*[ENDIF] JAVA_SPEC_VERSION >= 15*/
307
308
/*[IF JAVA_SPEC_VERSION >= 16]*/
309
private transient Class<?>[] cachedPermittedSubclasses;
310
private static long cachedPermittedSubclassesOffset = -1;
311
/*[ENDIF] JAVA_SPEC_VERSION >= 16 */
312
313
/**
314
* Prevents this class from being instantiated. Instances
315
* created by the virtual machine only.
316
*/
317
private Class() {}
318
319
/*
320
* Ensure the caller has the requested type of access.
321
*
322
* @param security the current SecurityManager
323
* @param callerClassLoader the ClassLoader of the caller of the original protected API
324
* @param type type of access, PUBLIC, DECLARED or INVALID
325
*
326
*/
327
void checkMemberAccess(SecurityManager security, ClassLoader callerClassLoader, int type) {
328
if (callerClassLoader != ClassLoader.bootstrapClassLoader) {
329
ClassLoader loader = getClassLoaderImpl();
330
/*[PR CMVC 82311] Spec is incorrect before 1.5, RI has this behavior since 1.2 */
331
/*[PR CMVC 201490] To remove CheckPackageAccess call from more Class methods */
332
if (type == Member.DECLARED && callerClassLoader != loader) {
333
security.checkPermission(SecurityConstants.CHECK_MEMBER_ACCESS_PERMISSION);
334
}
335
/*[PR CMVC 195558, 197433, 198986] Various fixes. */
336
if (sun.reflect.misc.ReflectUtil.needsPackageAccessCheck(callerClassLoader, loader)) {
337
if (Proxy.isProxyClass(this)) {
338
sun.reflect.misc.ReflectUtil.checkProxyPackageAccess(callerClassLoader, this.getInterfaces());
339
} else {
340
String packageName = this.getPackageName();
341
if ((packageName != null) && (packageName != "")) { //$NON-NLS-1$
342
security.checkPackageAccess(packageName);
343
}
344
}
345
}
346
}
347
}
348
349
/**
350
* Ensure the caller has the requested type of access.
351
*
352
* This helper method is only called by getClasses, and skip security.checkPackageAccess()
353
* when the class is a ProxyClass and the package name is sun.proxy.
354
*
355
* @param type type of access, PUBLIC or DECLARED
356
*
357
*/
358
private void checkNonSunProxyMemberAccess(SecurityManager security, ClassLoader callerClassLoader, int type) {
359
if (callerClassLoader != ClassLoader.bootstrapClassLoader) {
360
ClassLoader loader = getClassLoaderImpl();
361
if (type == Member.DECLARED && callerClassLoader != loader) {
362
security.checkPermission(SecurityConstants.CHECK_MEMBER_ACCESS_PERMISSION);
363
}
364
String packageName = this.getPackageName();
365
if (!(Proxy.isProxyClass(this) && packageName.equals(sun.reflect.misc.ReflectUtil.PROXY_PACKAGE)) &&
366
packageName != null && packageName != "" && sun.reflect.misc.ReflectUtil.needsPackageAccessCheck(callerClassLoader, loader)) //$NON-NLS-1$
367
{
368
security.checkPackageAccess(packageName);
369
}
370
}
371
}
372
373
private static void forNameAccessCheck(final SecurityManager sm, final Class<?> callerClass, final Class<?> foundClass) {
374
if (null != callerClass) {
375
ProtectionDomain pd = callerClass.getPDImpl();
376
if (null != pd) {
377
AccessController.doPrivileged(new PrivilegedAction<Object>() {
378
@Override
379
public Object run() {
380
foundClass.checkMemberAccess(sm, callerClass.getClassLoaderImpl(), MEMBER_INVALID_TYPE);
381
return null;
382
}
383
}, new AccessControlContext(new ProtectionDomain[]{pd}));
384
}
385
}
386
}
387
388
/**
389
* Answers a Class object which represents the class
390
* named by the argument. The name should be the name
391
* of a class as described in the class definition of
392
* java.lang.Class, however Classes representing base
393
* types can not be found using this method.
394
*
395
* @param className The name of the non-base type class to find
396
* @return the named Class
397
* @throws ClassNotFoundException If the class could not be found
398
*
399
* @see java.lang.Class
400
*/
401
@CallerSensitive
402
public static Class<?> forName(String className) throws ClassNotFoundException
403
{
404
/*[IF JAVA_SPEC_VERSION >= 18]*/
405
return forName(className, getStackClass(1));
406
/*[ELSE] JAVA_SPEC_VERSION >= 18
407
@SuppressWarnings("removal")
408
SecurityManager sm = null;
409
/**
410
* Get the SecurityManager from System. If the VM has not yet completed bootstrapping (i.e., J9VMInternals.initialized is still false)
411
* sm is kept as null without referencing System in order to avoid loading System earlier than necessary.
412
*/
413
if (J9VMInternals.initialized) {
414
sm = System.getSecurityManager();
415
}
416
if (null == sm) {
417
return forNameImpl(className, true, ClassLoader.callerClassLoader());
418
}
419
Class<?> caller = getStackClass(1);
420
ClassLoader callerClassLoader = null;
421
if (null != caller) {
422
callerClassLoader = caller.getClassLoaderImpl();
423
}
424
Class<?> c = forNameImpl(className, false, callerClassLoader);
425
forNameAccessCheck(sm, caller, c);
426
J9VMInternals.initialize(c);
427
return c;
428
/*[ENDIF] JAVA_SPEC_VERSION >= 18 */
429
}
430
431
/*[IF JAVA_SPEC_VERSION >= 18]*/
432
@CallerSensitiveAdapter
433
private static Class<?> forName(String className, Class<?> caller) throws ClassNotFoundException
434
{
435
@SuppressWarnings("removal")
436
SecurityManager sm = null;
437
/**
438
* Get the SecurityManager from System. If the VM has not yet completed bootstrapping (i.e., J9VMInternals.initialized is still false)
439
* sm is kept as null without referencing System in order to avoid loading System earlier than necessary.
440
*/
441
if (J9VMInternals.initialized) {
442
sm = System.getSecurityManager();
443
}
444
ClassLoader callerClassLoader = null;
445
if (null == sm) {
446
if (null != caller) {
447
callerClassLoader = caller.internalGetClassLoader();
448
}
449
return forNameImpl(className, true, callerClassLoader);
450
}
451
if (null != caller) {
452
callerClassLoader = caller.getClassLoaderImpl();
453
}
454
Class<?> c = forNameImpl(className, false, callerClassLoader);
455
forNameAccessCheck(sm, caller, c);
456
J9VMInternals.initialize(c);
457
return c;
458
}
459
/*[ENDIF] JAVA_SPEC_VERSION >= 18 */
460
461
AnnotationType getAnnotationType() {
462
AnnotationVars localAnnotationVars = getAnnotationVars();
463
return localAnnotationVars.annotationType;
464
}
465
void setAnnotationType(AnnotationType t) {
466
AnnotationVars localAnnotationVars = getAnnotationVars();
467
localAnnotationVars.annotationType = t;
468
}
469
/**
470
* Compare-And-Swap the AnnotationType instance corresponding to this class.
471
* (This method only applies to annotation types.)
472
*/
473
boolean casAnnotationType(AnnotationType oldType, AnnotationType newType) {
474
AnnotationVars localAnnotationVars = getAnnotationVars();
475
long localTypeOffset = AnnotationVars.annotationTypeOffset;
476
if (-1 == localTypeOffset) {
477
Field field = AccessController.doPrivileged(new PrivilegedAction<Field>() {
478
public Field run() {
479
try {
480
return AnnotationVars.class.getDeclaredField("annotationType"); //$NON-NLS-1$
481
} catch (Exception e) {
482
throw newInternalError(e);
483
}
484
}
485
});
486
localTypeOffset = getUnsafe().objectFieldOffset(field);
487
AnnotationVars.annotationTypeOffset = localTypeOffset;
488
}
489
/*[IF Sidecar19-SE]*/
490
return getUnsafe().compareAndSetObject(localAnnotationVars, localTypeOffset, oldType, newType);
491
/*[ELSE]
492
return getUnsafe().compareAndSwapObject(localAnnotationVars, localTypeOffset, oldType, newType);
493
/*[ENDIF]*/
494
}
495
496
/**
497
* Answers a Class object which represents the class
498
* named by the argument. The name should be the name
499
* of a class as described in the class definition of
500
* java.lang.Class, however Classes representing base
501
* types can not be found using this method.
502
* Security rules will be obeyed.
503
*
504
* @param className The name of the non-base type class to find
505
* @param initializeBoolean A boolean indicating whether the class should be
506
* initialized
507
* @param classLoader The classloader to use to load the class
508
* @return the named class.
509
* @throws ClassNotFoundException If the class could not be found
510
*
511
* @see java.lang.Class
512
*/
513
@CallerSensitive
514
public static Class<?> forName(
515
String className, boolean initializeBoolean, ClassLoader classLoader) throws ClassNotFoundException
516
{
517
/*[IF JAVA_SPEC_VERSION >= 18]*/
518
return forNameHelper(className, initializeBoolean, classLoader, null, false);
519
/*[ELSE] JAVA_SPEC_VERSION >= 18
520
@SuppressWarnings("removal")
521
SecurityManager sm = null;
522
if (J9VMInternals.initialized) {
523
sm = System.getSecurityManager();
524
}
525
if (null == sm) {
526
return forNameImpl(className, initializeBoolean, classLoader);
527
}
528
Class<?> caller = getStackClass(1);
529
/* perform security checks */
530
if (null == classLoader) {
531
if (null != caller) {
532
ClassLoader callerClassLoader = caller.getClassLoaderImpl();
533
if (callerClassLoader != ClassLoader.bootstrapClassLoader) {
534
/* only allowed if caller has RuntimePermission("getClassLoader") permission */
535
sm.checkPermission(SecurityConstants.GET_CLASSLOADER_PERMISSION);
536
}
537
}
538
}
539
Class<?> c = forNameImpl(className, false, classLoader);
540
forNameAccessCheck(sm, caller, c);
541
if (initializeBoolean) {
542
J9VMInternals.initialize(c);
543
}
544
return c;
545
/*[ENDIF] JAVA_SPEC_VERSION >= 18 */
546
}
547
548
/*[IF JAVA_SPEC_VERSION >= 18]*/
549
@CallerSensitiveAdapter
550
private static Class<?> forName(
551
String className, boolean initializeBoolean, ClassLoader classLoader,
552
Class<?> caller) throws ClassNotFoundException
553
{
554
return forNameHelper(className, initializeBoolean, classLoader, caller, true);
555
}
556
557
@CallerSensitive
558
private static Class<?> forNameHelper(
559
String className, boolean initializeBoolean, ClassLoader classLoader,
560
Class<?> caller, boolean isAdapter) throws ClassNotFoundException
561
{
562
@SuppressWarnings("removal")
563
SecurityManager sm = null;
564
if (J9VMInternals.initialized) {
565
sm = System.getSecurityManager();
566
}
567
if (null == sm) {
568
return forNameImpl(className, initializeBoolean, classLoader);
569
}
570
if (!isAdapter) {
571
caller = getStackClass(2);
572
}
573
/* perform security checks */
574
if (null == classLoader) {
575
if (null != caller) {
576
ClassLoader callerClassLoader = caller.getClassLoaderImpl();
577
if (callerClassLoader != ClassLoader.bootstrapClassLoader) {
578
/* only allowed if caller has RuntimePermission("getClassLoader") permission */
579
sm.checkPermission(SecurityConstants.GET_CLASSLOADER_PERMISSION);
580
}
581
}
582
}
583
Class<?> c = forNameImpl(className, false, classLoader);
584
forNameAccessCheck(sm, caller, c);
585
if (initializeBoolean) {
586
J9VMInternals.initialize(c);
587
}
588
return c;
589
}
590
/*[ENDIF] JAVA_SPEC_VERSION >= 18 */
591
592
/*[IF Sidecar19-SE]*/
593
/**
594
* Answers a Class object which represents the class
595
* with the given name in the given module.
596
* The name should be the name of a class as described
597
* in the class definition of java.lang.Class,
598
* however Classes representing base
599
* types can not be found using this method.
600
* It does not invoke the class initializer.
601
* Note that this method does not check whether the
602
* requested class is accessible to its caller.
603
* Security rules will be obeyed.
604
*
605
* @param module The name of the module
606
* @param name The name of the non-base type class to find
607
*
608
* @return The Class object representing the named class
609
*
610
* @see java.lang.Class
611
*/
612
@CallerSensitive
613
public static Class<?> forName(Module module, String name)
614
{
615
/*[IF JAVA_SPEC_VERSION >= 18]*/
616
return forNameHelper(module, name, null, false);
617
/*[ELSE] JAVA_SPEC_VERSION >= 18
618
@SuppressWarnings("removal")
619
SecurityManager sm = null;
620
ClassLoader classLoader;
621
Class<?> c;
622
623
if ((null == module) || (null == name)) {
624
throw new NullPointerException();
625
}
626
if (J9VMInternals.initialized) {
627
sm = System.getSecurityManager();
628
}
629
if (null != sm) {
630
Class<?> caller = getStackClass(1);
631
/* If the caller is not the specified module and RuntimePermission("getClassLoader") permission is denied, throw SecurityException */
632
if ((null != caller) && (caller.getModule() != module)) {
633
sm.checkPermission(SecurityConstants.GET_CLASSLOADER_PERMISSION);
634
}
635
classLoader = AccessController.doPrivileged(new PrivilegedAction<ClassLoader>() {
636
public ClassLoader run() {
637
return module.getClassLoader();
638
}
639
});
640
} else {
641
classLoader = module.getClassLoader();
642
}
643
644
try {
645
if (classLoader == null) {
646
c = ClassLoader.bootstrapClassLoader.loadClass(module, name);
647
} else {
648
c = classLoader.loadClassHelper(name, false, false, module);
649
}
650
} catch (ClassNotFoundException e) {
651
/* This method returns null on failure rather than throwing a ClassNotFoundException */
652
return null;
653
}
654
if (null != c) {
655
/* If the class loader of the given module defines other modules and
656
* the given name is a class defined in a different module,
657
* this method returns null after the class is loaded.
658
*/
659
if (c.getModule() != module) {
660
return null;
661
}
662
}
663
return c;
664
/*[ENDIF] JAVA_SPEC_VERSION >= 18 */
665
}
666
667
/*[IF JAVA_SPEC_VERSION >= 18]*/
668
@CallerSensitiveAdapter
669
private static Class<?> forName(Module module, String name, Class<?> caller)
670
{
671
return forNameHelper(module, name, caller, true);
672
}
673
674
@CallerSensitive
675
private static Class<?> forNameHelper(Module module, String name, Class<?> caller, boolean isAdapter)
676
{
677
@SuppressWarnings("removal")
678
SecurityManager sm = null;
679
ClassLoader classLoader;
680
Class<?> c;
681
682
if ((null == module) || (null == name)) {
683
throw new NullPointerException();
684
}
685
if (J9VMInternals.initialized) {
686
sm = System.getSecurityManager();
687
}
688
if (null != sm) {
689
if (!isAdapter) {
690
caller = getStackClass(2);
691
}
692
/* If the caller is not the specified module and RuntimePermission("getClassLoader") permission is denied, throw SecurityException */
693
if ((null != caller) && (caller.getModule() != module)) {
694
sm.checkPermission(SecurityConstants.GET_CLASSLOADER_PERMISSION);
695
}
696
classLoader = AccessController.doPrivileged(new PrivilegedAction<ClassLoader>() {
697
public ClassLoader run() {
698
return module.getClassLoader();
699
}
700
});
701
} else {
702
classLoader = module.getClassLoader();
703
}
704
705
try {
706
if (classLoader == null) {
707
c = ClassLoader.bootstrapClassLoader.loadClass(module, name);
708
} else {
709
c = classLoader.loadClassHelper(name, false, false, module);
710
}
711
} catch (ClassNotFoundException e) {
712
/* This method returns null on failure rather than throwing a ClassNotFoundException */
713
return null;
714
}
715
if (null != c) {
716
/* If the class loader of the given module defines other modules and
717
* the given name is a class defined in a different module,
718
* this method returns null after the class is loaded.
719
*/
720
if (c.getModule() != module) {
721
return null;
722
}
723
}
724
return c;
725
}
726
/*[ENDIF] JAVA_SPEC_VERSION >= 18 */
727
/*[ENDIF] Sidecar19-SE */
728
729
/**
730
* Answers a Class object which represents the class
731
* named by the argument. The name should be the name
732
* of a class as described in the class definition of
733
* java.lang.Class, however Classes representing base
734
* types can not be found using this method.
735
*
736
* @param className The name of the non-base type class to find
737
* @param initializeBoolean A boolean indicating whether the class should be
738
* initialized
739
* @param classLoader The classloader to use to load the class
740
* @return the named class.
741
* @throws ClassNotFoundException If the class could not be found
742
*
743
* @see java.lang.Class
744
*/
745
private static native Class<?> forNameImpl(String className,
746
boolean initializeBoolean,
747
ClassLoader classLoader)
748
throws ClassNotFoundException;
749
750
/**
751
* Answers an array containing all public class members
752
* of the class which the receiver represents and its
753
* superclasses and interfaces
754
*
755
* @return the class' public class members
756
* @throws SecurityException If member access is not allowed
757
*
758
* @see java.lang.Class
759
*/
760
@CallerSensitive
761
public Class<?>[] getClasses() {
762
/*[PR CMVC 82311] Spec is incorrect before 1.5, RI has this behavior since 1.2 */
763
@SuppressWarnings("removal")
764
SecurityManager security = System.getSecurityManager();
765
if (security != null) {
766
ClassLoader callerClassLoader = ClassLoader.getStackClassLoader(1);
767
checkNonSunProxyMemberAccess(security, callerClassLoader, Member.PUBLIC);
768
}
769
770
java.util.Vector<Class<?>> publicClasses = new java.util.Vector<>();
771
Class<?> current = this;
772
Class<?>[] classes;
773
while(current != null) {
774
/*[PR 97353] Call the native directly, as the security check in getDeclaredClasses() does nothing but check the caller classloader */
775
classes = current.getDeclaredClassesImpl();
776
for (int i = 0; i < classes.length; i++)
777
if (Modifier.isPublic(classes[i].getModifiers()))
778
publicClasses.addElement(classes[i]);
779
current = current.getSuperclass();
780
}
781
classes = new Class<?>[publicClasses.size()];
782
publicClasses.copyInto(classes);
783
return classes;
784
}
785
786
/**
787
* Answers the classloader which was used to load the
788
* class represented by the receiver. Answer null if the
789
* class was loaded by the system class loader.
790
*
791
* @return the receiver's class loader or nil
792
*
793
* @see java.lang.ClassLoader
794
*/
795
@CallerSensitive
796
public ClassLoader getClassLoader() {
797
if (null != classLoader) {
798
if (classLoader == ClassLoader.bootstrapClassLoader) {
799
return null;
800
}
801
@SuppressWarnings("removal")
802
SecurityManager security = System.getSecurityManager();
803
if (null != security) {
804
ClassLoader callersClassLoader = ClassLoader.callerClassLoader();
805
if (ClassLoader.needsClassLoaderPermissionCheck(callersClassLoader, classLoader)) {
806
security.checkPermission(SecurityConstants.GET_CLASSLOADER_PERMISSION);
807
}
808
}
809
}
810
return classLoader;
811
}
812
813
/**
814
* Returns the classloader used to load the receiver's class.
815
* Returns null if the class was loaded by the bootstrap (system) class loader.
816
* This skips security checks.
817
* @return the receiver's class loader or null
818
* @see java.lang.ClassLoader
819
*/
820
ClassLoader internalGetClassLoader() {
821
return (classLoader == ClassLoader.bootstrapClassLoader)? null: classLoader;
822
}
823
824
/**
825
* Answers the ClassLoader which was used to load the
826
* class represented by the receiver.
827
*
828
* @return the receiver's class loader
829
*
830
* @see java.lang.ClassLoader
831
*/
832
ClassLoader getClassLoader0() {
833
ClassLoader loader = getClassLoaderImpl();
834
return loader;
835
}
836
837
838
/**
839
* Return the ClassLoader for this Class without doing any security
840
* checks. The bootstrap ClassLoader is returned, unlike getClassLoader()
841
* which returns null in place of the bootstrap ClassLoader.
842
*
843
* @return the ClassLoader
844
*
845
* @see ClassLoader#isASystemClassLoader()
846
*/
847
ClassLoader getClassLoaderImpl()
848
{
849
return classLoader;
850
}
851
852
/**
853
* Answers a Class object which represents the receiver's
854
* component type if the receiver represents an array type.
855
* Otherwise answers nil. The component type of an array
856
* type is the type of the elements of the array.
857
*
858
* @return the component type of the receiver.
859
*
860
* @see java.lang.Class
861
*/
862
public native Class<?> getComponentType();
863
864
private NoSuchMethodException newNoSuchMethodException(String name, Class<?>[] types) {
865
StringBuilder error = new StringBuilder();
866
error.append(getName()).append('.').append(name).append('(');
867
/*[PR CMVC 80340] check for null types */
868
for (int i = 0; i < types.length; ++i) {
869
if (i != 0) error.append(", "); //$NON-NLS-1$
870
error.append(types[i] == null ? null : types[i].getName());
871
}
872
error.append(')');
873
return new NoSuchMethodException(error.toString());
874
}
875
876
/**
877
* Answers a public Constructor object which represents the
878
* constructor described by the arguments.
879
*
880
* @param parameterTypes the types of the arguments.
881
* @return the constructor described by the arguments.
882
* @throws NoSuchMethodException if the constructor could not be found.
883
* @throws SecurityException if member access is not allowed
884
*
885
* @see #getConstructors
886
*/
887
@CallerSensitive
888
public Constructor<T> getConstructor(Class<?>... parameterTypes) throws NoSuchMethodException, SecurityException {
889
@SuppressWarnings("removal")
890
SecurityManager security = System.getSecurityManager();
891
if (security != null) {
892
ClassLoader callerClassLoader = ClassLoader.getStackClassLoader(1);
893
checkMemberAccess(security, callerClassLoader, Member.PUBLIC);
894
}
895
896
/*[PR CMVC 114820, CMVC 115873, CMVC 116166] add reflection cache */
897
if (parameterTypes == null) parameterTypes = EmptyParameters;
898
Constructor<T> cachedConstructor = lookupCachedConstructor(parameterTypes);
899
if (cachedConstructor != null && Modifier.isPublic(cachedConstructor.getModifiers())) {
900
return cachedConstructor;
901
}
902
903
/*[PR CMVC 192714,194493] prepare the class before attempting to access members */
904
J9VMInternals.prepare(this);
905
906
Constructor<T> rc;
907
// Handle the default constructor case upfront
908
if (parameterTypes.length == 0) {
909
rc = getConstructorImpl(parameterTypes, "()V"); //$NON-NLS-1$
910
} else {
911
parameterTypes = parameterTypes.clone();
912
// Build a signature for the requested method.
913
String signature = getParameterTypesSignature(true, "<init>", parameterTypes, "V"); //$NON-NLS-1$ //$NON-NLS-2$
914
rc = getConstructorImpl(parameterTypes, signature);
915
if (rc != null)
916
rc = checkParameterTypes(rc, parameterTypes);
917
}
918
if (rc == null) throw newNoSuchMethodException("<init>", parameterTypes); //$NON-NLS-1$
919
return cacheConstructor(rc);
920
}
921
922
/**
923
* Answers a public Constructor object which represents the
924
* constructor described by the arguments.
925
*
926
* @param parameterTypes the types of the arguments.
927
* @param signature the signature of the method.
928
* @return the constructor described by the arguments.
929
*
930
* @see #getConstructors
931
*/
932
private native Constructor<T> getConstructorImpl(Class<?> parameterTypes[], String signature);
933
934
/**
935
* Answers an array containing Constructor objects describing
936
* all constructors which are visible from the current execution
937
* context.
938
*
939
* @return all visible constructors starting from the receiver.
940
* @throws SecurityException if member access is not allowed
941
*
942
* @see #getMethods
943
*/
944
@CallerSensitive
945
public Constructor<?>[] getConstructors() throws SecurityException {
946
@SuppressWarnings("removal")
947
SecurityManager security = System.getSecurityManager();
948
if (security != null) {
949
ClassLoader callerClassLoader = ClassLoader.getStackClassLoader(1);
950
checkMemberAccess(security, callerClassLoader, Member.PUBLIC);
951
}
952
953
/*[PR CMVC 114820, CMVC 115873, CMVC 116166] add reflection cache */
954
Constructor<T>[] cachedConstructors = lookupCachedConstructors(CacheKey.PublicConstructorsKey);
955
if (cachedConstructors != null) {
956
return cachedConstructors;
957
}
958
959
/*[PR CMVC 192714,194493] prepare the class before attempting to access members */
960
J9VMInternals.prepare(this);
961
962
Constructor<T>[] ctors = getConstructorsImpl();
963
964
return cacheConstructors(ctors, CacheKey.PublicConstructorsKey);
965
}
966
967
/**
968
* Answers an array containing Constructor objects describing
969
* all constructors which are visible from the current execution
970
* context.
971
*
972
* @return all visible constructors starting from the receiver.
973
*
974
* @see #getMethods
975
*/
976
private native Constructor<T>[] getConstructorsImpl();
977
978
/**
979
* Answers an array containing all class members of the class
980
* which the receiver represents. Note that some of the fields
981
* which are returned may not be visible in the current
982
* execution context.
983
*
984
* @return the class' class members
985
* @throws SecurityException if member access is not allowed
986
*
987
* @see java.lang.Class
988
*/
989
@CallerSensitive
990
public Class<?>[] getDeclaredClasses() throws SecurityException {
991
@SuppressWarnings("removal")
992
SecurityManager security = System.getSecurityManager();
993
if (security != null) {
994
ClassLoader callerClassLoader = ClassLoader.getStackClassLoader(1);
995
checkNonSunProxyMemberAccess(security, callerClassLoader, Member.DECLARED);
996
}
997
998
/*[PR 97353] getClasses() calls this native directly */
999
return getDeclaredClassesImpl();
1000
}
1001
1002
/**
1003
* Answers an array containing all class members of the class
1004
* which the receiver represents. Note that some of the fields
1005
* which are returned may not be visible in the current
1006
* execution context.
1007
*
1008
* @return the class' class members
1009
*
1010
* @see java.lang.Class
1011
*/
1012
private native Class<?>[] getDeclaredClassesImpl();
1013
1014
/**
1015
* Answers a Constructor object which represents the
1016
* constructor described by the arguments.
1017
*
1018
* @param parameterTypes the types of the arguments.
1019
* @return the constructor described by the arguments.
1020
* @throws NoSuchMethodException if the constructor could not be found.
1021
* @throws SecurityException if member access is not allowed
1022
*
1023
* @see #getConstructors
1024
*/
1025
@CallerSensitive
1026
public Constructor<T> getDeclaredConstructor(Class<?>... parameterTypes) throws NoSuchMethodException, SecurityException {
1027
@SuppressWarnings("removal")
1028
SecurityManager security = System.getSecurityManager();
1029
if (security != null) {
1030
ClassLoader callerClassLoader = ClassLoader.getStackClassLoader(1);
1031
checkMemberAccess(security, callerClassLoader, Member.DECLARED);
1032
}
1033
1034
/*[PR CMVC 114820, CMVC 115873, CMVC 116166] add reflection cache */
1035
if (parameterTypes == null) parameterTypes = EmptyParameters;
1036
Constructor<T> cachedConstructor = lookupCachedConstructor(parameterTypes);
1037
if (cachedConstructor != null) {
1038
return cachedConstructor;
1039
}
1040
1041
/*[PR CMVC 192714,194493] prepare the class before attempting to access members */
1042
J9VMInternals.prepare(this);
1043
1044
Constructor<T> rc;
1045
// Handle the default constructor case upfront
1046
if (parameterTypes.length == 0) {
1047
rc = getDeclaredConstructorImpl(parameterTypes, "()V"); //$NON-NLS-1$
1048
} else {
1049
parameterTypes = parameterTypes.clone();
1050
// Build a signature for the requested method.
1051
String signature = getParameterTypesSignature(true, "<init>", parameterTypes, "V"); //$NON-NLS-1$ //$NON-NLS-2$
1052
rc = getDeclaredConstructorImpl(parameterTypes, signature);
1053
if (rc != null)
1054
rc = checkParameterTypes(rc, parameterTypes);
1055
}
1056
if (rc == null) throw newNoSuchMethodException("<init>", parameterTypes); //$NON-NLS-1$
1057
return cacheConstructor(rc);
1058
}
1059
1060
/**
1061
* Answers a Constructor object which represents the
1062
* constructor described by the arguments.
1063
*
1064
* @param parameterTypes the types of the arguments.
1065
* @param signature the signature of the method.
1066
* @return the constructor described by the arguments.
1067
*
1068
* @see #getConstructors
1069
*/
1070
private native Constructor<T> getDeclaredConstructorImpl(Class<?>[] parameterTypes, String signature);
1071
1072
/**
1073
* Answers an array containing Constructor objects describing
1074
* all constructor which are defined by the receiver. Note that
1075
* some of the fields which are returned may not be visible
1076
* in the current execution context.
1077
*
1078
* @return the receiver's constructors.
1079
* @throws SecurityException if member access is not allowed
1080
*
1081
* @see #getMethods
1082
*/
1083
@CallerSensitive
1084
public Constructor<?>[] getDeclaredConstructors() throws SecurityException {
1085
@SuppressWarnings("removal")
1086
SecurityManager security = System.getSecurityManager();
1087
if (security != null) {
1088
ClassLoader callerClassLoader = ClassLoader.getStackClassLoader(1);
1089
checkMemberAccess(security, callerClassLoader, Member.DECLARED);
1090
}
1091
1092
/*[PR CMVC 114820, CMVC 115873, CMVC 116166] add reflection cache */
1093
Constructor<T>[] cachedConstructors = lookupCachedConstructors(CacheKey.DeclaredConstructorsKey);
1094
if (cachedConstructors != null) {
1095
return cachedConstructors;
1096
}
1097
1098
/*[PR CMVC 192714,194493] prepare the class before attempting to access members */
1099
J9VMInternals.prepare(this);
1100
1101
Constructor<T>[] ctors = getDeclaredConstructorsImpl();
1102
1103
return cacheConstructors(ctors, CacheKey.DeclaredConstructorsKey);
1104
}
1105
1106
/**
1107
* Answers an array containing Constructor objects describing
1108
* all constructor which are defined by the receiver. Note that
1109
* some of the fields which are returned may not be visible
1110
* in the current execution context.
1111
*
1112
* @return the receiver's constructors.
1113
*
1114
* @see #getMethods
1115
*/
1116
private native Constructor<T>[] getDeclaredConstructorsImpl();
1117
1118
/**
1119
* Answers a Field object describing the field in the receiver
1120
* named by the argument. Note that the Constructor may not be
1121
* visible from the current execution context.
1122
*
1123
* @param name The name of the field to look for.
1124
* @return the field in the receiver named by the argument.
1125
* @throws NoSuchFieldException if the requested field could not be found
1126
* @throws SecurityException if member access is not allowed
1127
*
1128
* @see #getDeclaredFields
1129
*/
1130
@CallerSensitive
1131
public Field getDeclaredField(String name) throws NoSuchFieldException, SecurityException {
1132
@SuppressWarnings("removal")
1133
SecurityManager security = System.getSecurityManager();
1134
if (security != null) {
1135
ClassLoader callerClassLoader = ClassLoader.getStackClassLoader(1);
1136
checkMemberAccess(security, callerClassLoader, Member.DECLARED);
1137
}
1138
return getDeclaredFieldInternal(name, true);
1139
}
1140
1141
/**
1142
* A private helper method for getDeclaredField().
1143
* This is for internal usage, no security check required,
1144
* and if doCache is false, the field is to be retrieved without caching
1145
* which can avoid circular dependency at JVM bootstrapping phase.
1146
*
1147
* @param name The name of the field to look for.
1148
* @param doCache The flag to determine if caching the field.
1149
* @return the field in the receiver named by the argument.
1150
* @throws NoSuchFieldException if the requested field could not be found
1151
*/
1152
@CallerSensitive
1153
private Field getDeclaredFieldInternal(String name, boolean doCache) throws NoSuchFieldException {
1154
if (doCache) {
1155
/*[PR CMVC 114820, CMVC 115873, CMVC 116166] add reflection cache */
1156
Field cachedField = lookupCachedField(name);
1157
if (cachedField != null && cachedField.getDeclaringClass() == this) {
1158
return cachedField;
1159
}
1160
}
1161
1162
/*[PR CMVC 192714,194493] prepare the class before attempting to access members */
1163
J9VMInternals.prepare(this);
1164
1165
Field field = getDeclaredFieldImpl(name);
1166
1167
/*[PR JAZZ 102876] IBM J9VM not using Reflection.filterFields API to hide the sensitive fields */
1168
Field[] fields = Reflection.filterFields(this, new Field[] {field});
1169
if (0 == fields.length) {
1170
throw new NoSuchFieldException(name);
1171
}
1172
1173
if (doCache) {
1174
return cacheField(fields[0]);
1175
} else {
1176
return fields[0];
1177
}
1178
}
1179
1180
/**
1181
* Answers a Field object describing the field in the receiver
1182
* named by the argument. Note that the Constructor may not be
1183
* visible from the current execution context.
1184
*
1185
* @param name The name of the field to look for.
1186
* @return the field in the receiver named by the argument.
1187
* @throws NoSuchFieldException If the given field does not exist
1188
*
1189
* @see #getDeclaredFields
1190
*/
1191
private native Field getDeclaredFieldImpl(String name) throws NoSuchFieldException;
1192
1193
/**
1194
* Answers an array containing Field objects describing
1195
* all fields which are defined by the receiver. Note that
1196
* some of the fields which are returned may not be visible
1197
* in the current execution context.
1198
*
1199
* @return the receiver's fields.
1200
* @throws SecurityException If member access is not allowed
1201
*
1202
* @see #getFields
1203
*/
1204
@CallerSensitive
1205
public Field[] getDeclaredFields() throws SecurityException {
1206
@SuppressWarnings("removal")
1207
SecurityManager security = System.getSecurityManager();
1208
if (security != null) {
1209
ClassLoader callerClassLoader = ClassLoader.getStackClassLoader(1);
1210
checkMemberAccess(security, callerClassLoader, Member.DECLARED);
1211
}
1212
1213
/*[PR CMVC 114820, CMVC 115873, CMVC 116166] add reflection cache */
1214
Field[] cachedFields = lookupCachedFields(CacheKey.DeclaredFieldsKey);
1215
if (cachedFields != null) {
1216
return cachedFields;
1217
}
1218
1219
/*[PR CMVC 192714,194493] prepare the class before attempting to access members */
1220
J9VMInternals.prepare(this);
1221
1222
Field[] fields = getDeclaredFieldsImpl();
1223
1224
return cacheFields(Reflection.filterFields(this, fields), CacheKey.DeclaredFieldsKey);
1225
}
1226
1227
/**
1228
* Answers an array containing Field objects describing
1229
* all fields which are defined by the receiver. Note that
1230
* some of the fields which are returned may not be visible
1231
* in the current execution context.
1232
*
1233
* @return the receiver's fields.
1234
*
1235
* @see #getFields
1236
*/
1237
private native Field[] getDeclaredFieldsImpl();
1238
1239
/*[IF JAVA_SPEC_VERSION >= 11]*/
1240
/**
1241
* Answers a list of method objects which represent the public methods
1242
* described by the arguments. Note that the associated method may not
1243
* be visible from the current execution context.
1244
* An empty list is returned if the method can't be found.
1245
*
1246
* @param name the name of the method
1247
* @param parameterTypes the types of the arguments.
1248
* @return a list of methods described by the arguments.
1249
*
1250
* @see #getMethods
1251
*/
1252
@CallerSensitive
1253
List<Method> getDeclaredPublicMethods(String name, Class<?>... parameterTypes) {
1254
CacheKey ck = CacheKey.newDeclaredPublicMethodsKey(name, parameterTypes);
1255
List<Method> methodList = lookupCachedDeclaredPublicMethods(ck);
1256
if (methodList != null) {
1257
return methodList;
1258
}
1259
try {
1260
methodList = new ArrayList<>();
1261
getMethodHelper(false, true, methodList, name, parameterTypes);
1262
} catch (NoSuchMethodException e) {
1263
// no NoSuchMethodException expected
1264
}
1265
return cacheDeclaredPublicMethods(methodList, ck);
1266
}
1267
1268
private List<Method> lookupCachedDeclaredPublicMethods(CacheKey cacheKey) {
1269
if (!reflectCacheEnabled) return null;
1270
if (reflectCacheDebug) {
1271
reflectCacheDebugHelper(null, 0, "lookup DeclaredPublicMethods in: ", getName()); //$NON-NLS-1$
1272
}
1273
ReflectCache cache = peekReflectCache();
1274
if (cache != null) {
1275
List<Method> methods = (List<Method>) cache.find(cacheKey);
1276
if (methods != null) {
1277
// assuming internal caller won't change this method list content
1278
return methods;
1279
}
1280
}
1281
return null;
1282
}
1283
@CallerSensitive
1284
private List<Method> cacheDeclaredPublicMethods(List<Method> methods, CacheKey cacheKey) {
1285
if (!reflectCacheEnabled
1286
|| (reflectCacheAppOnly && ClassLoader.getStackClassLoader(2) == ClassLoader.bootstrapClassLoader)
1287
) {
1288
return methods;
1289
}
1290
if (reflectCacheDebug) {
1291
reflectCacheDebugHelper(null, 0, "cache DeclaredPublicMethods in: ", getName()); //$NON-NLS-1$
1292
}
1293
ReflectCache cache = null;
1294
try {
1295
cache = acquireReflectCache();
1296
for (int i = 0; i < methods.size(); i++) {
1297
Method method = methods.get(i);
1298
CacheKey key = CacheKey.newMethodKey(method.getName(), getParameterTypes(method), method.getReturnType());
1299
Method methodPut = cache.insertIfAbsent(key, method);
1300
if (method != methodPut) {
1301
methods.set(i, methodPut);
1302
}
1303
}
1304
cache.insert(cacheKey, methods);
1305
} finally {
1306
if (cache != null) {
1307
cache.release();
1308
}
1309
}
1310
return methods;
1311
}
1312
/*[ENDIF] JAVA_SPEC_VERSION >= 11 */
1313
1314
/**
1315
* A helper method for reflection debugging
1316
*
1317
* @param parameters parameters[i].getName() to be appended
1318
* @param posInsert parameters to be appended AFTER msgs[posInsert]
1319
* @param msgs a message array
1320
*/
1321
static void reflectCacheDebugHelper(Class<?>[] parameters, int posInsert, String... msgs) {
1322
StringBuilder output = new StringBuilder(200);
1323
for (int i = 0; i < msgs.length; i++) {
1324
output.append(msgs[i]);
1325
if ((parameters != null) && (i == posInsert)) {
1326
output.append('(');
1327
for (int j = 0; j < parameters.length; j++) {
1328
if (j != 0) {
1329
output.append(", "); //$NON-NLS-1$
1330
}
1331
output.append(parameters[i].getName());
1332
}
1333
output.append(')');
1334
}
1335
}
1336
System.err.println(output);
1337
}
1338
1339
/**
1340
* Answers a Method object which represents the method
1341
* described by the arguments. Note that the associated
1342
* method may not be visible from the current execution
1343
* context.
1344
*
1345
* @param name the name of the method
1346
* @param parameterTypes the types of the arguments.
1347
* @return the method described by the arguments.
1348
* @throws NoSuchMethodException if the method could not be found.
1349
* @throws SecurityException If member access is not allowed
1350
*
1351
* @see #getMethods
1352
*/
1353
@CallerSensitive
1354
public Method getDeclaredMethod(String name, Class<?>... parameterTypes) throws NoSuchMethodException, SecurityException {
1355
@SuppressWarnings("removal")
1356
SecurityManager security = System.getSecurityManager();
1357
if (security != null) {
1358
ClassLoader callerClassLoader = ClassLoader.getStackClassLoader(1);
1359
checkMemberAccess(security, callerClassLoader, Member.DECLARED);
1360
}
1361
return getMethodHelper(true, true, null, name, parameterTypes);
1362
}
1363
1364
/**
1365
* This native iterates over methods matching the provided name and signature
1366
* in the receiver class. The startingPoint parameter is passed the last
1367
* method returned (or null on the first use), and the native returns the next
1368
* matching method or null if there are no more matches.
1369
* Note that the associated method may not be visible from the
1370
* current execution context.
1371
*
1372
* @param name the name of the method
1373
* @param parameterTypes the types of the arguments.
1374
* @param partialSignature the signature of the method, without return type.
1375
* @param startingPoint the method to start searching after, or null to start at the beginning
1376
* @return the next Method described by the arguments
1377
*
1378
* @see #getMethods
1379
*/
1380
private native Method getDeclaredMethodImpl(String name, Class<?>[] parameterTypes, String partialSignature, Method startingPoint);
1381
1382
/**
1383
* Answers an array containing Method objects describing
1384
* all methods which are defined by the receiver. Note that
1385
* some of the methods which are returned may not be visible
1386
* in the current execution context.
1387
*
1388
* @throws SecurityException if member access is not allowed
1389
* @return the receiver's methods.
1390
*
1391
* @see #getMethods
1392
*/
1393
@CallerSensitive
1394
public Method[] getDeclaredMethods() throws SecurityException {
1395
@SuppressWarnings("removal")
1396
SecurityManager security = System.getSecurityManager();
1397
if (security != null) {
1398
ClassLoader callerClassLoader = ClassLoader.getStackClassLoader(1);
1399
checkMemberAccess(security, callerClassLoader, Member.DECLARED);
1400
}
1401
1402
/*[PR CMVC 114820, CMVC 115873, CMVC 116166] add reflection cache */
1403
Method[] cachedMethods = lookupCachedMethods(CacheKey.DeclaredMethodsKey);
1404
if (cachedMethods != null) {
1405
return cachedMethods;
1406
}
1407
1408
/*[PR CMVC 192714,194493] prepare the class before attempting to access members */
1409
J9VMInternals.prepare(this);
1410
1411
/*[PR CMVC 194301] do not allow reflect access to sun.misc.Unsafe.getUnsafe() */
1412
return cacheMethods(Reflection.filterMethods(this, getDeclaredMethodsImpl()), CacheKey.DeclaredMethodsKey);
1413
}
1414
1415
/**
1416
* Answers an array containing Method objects describing
1417
* all methods which are defined by the receiver. Note that
1418
* some of the methods which are returned may not be visible
1419
* in the current execution context.
1420
*
1421
* @return the receiver's methods.
1422
*
1423
* @see #getMethods
1424
*/
1425
private native Method[] getDeclaredMethodsImpl();
1426
1427
/**
1428
* Answers the class which declared the class represented
1429
* by the receiver. This will return null if the receiver
1430
* is not a member of another class.
1431
*
1432
* @return the declaring class of the receiver.
1433
*/
1434
@CallerSensitive
1435
public Class<?> getDeclaringClass() {
1436
if (cachedDeclaringClassOffset == -1) {
1437
cachedDeclaringClassOffset = getFieldOffset("cachedDeclaringClass"); //$NON-NLS-1$
1438
}
1439
if (cachedDeclaringClass == null) {
1440
Class<?> localDeclaringClass = getDeclaringClassImpl();
1441
if (localDeclaringClass == null) {
1442
localDeclaringClass = ClassReflectNullPlaceHolder.class;
1443
}
1444
writeFieldValue(cachedDeclaringClassOffset, localDeclaringClass);
1445
}
1446
1447
/**
1448
* ClassReflectNullPlaceHolder.class means the value of cachedDeclaringClass is null
1449
* @see ClassReflectNullPlaceHolder.class
1450
*/
1451
Class<?> declaringClass = cachedDeclaringClass == ClassReflectNullPlaceHolder.class ? null : cachedDeclaringClass;
1452
if (declaringClass == null) {
1453
if (!cachedCheckInnerClassAttr) {
1454
/* Check whether the enclosing class has an valid inner class entry to the current class.
1455
* Note: the entries are populated with the InnerClass attribute when creating ROM class.
1456
*/
1457
checkInnerClassAttrOfEnclosingClass();
1458
cachedCheckInnerClassAttr = true;
1459
}
1460
return declaringClass;
1461
}
1462
if (declaringClass.isClassADeclaredClass(this)) {
1463
@SuppressWarnings("removal")
1464
SecurityManager security = System.getSecurityManager();
1465
if (security != null) {
1466
ClassLoader callerClassLoader = ClassLoader.getStackClassLoader(1);
1467
declaringClass.checkMemberAccess(security, callerClassLoader, MEMBER_INVALID_TYPE);
1468
}
1469
return declaringClass;
1470
} else if (this.isClassADeclaredClass(declaringClass) || this.isClassADeclaredClass(this) || this.isCircularDeclaringClass()) {
1471
/* The execution of VM shouldn't be interrupted by corrupted InnerClasses attributes such as circular entries.
1472
* To be specific, Class A is the declaringClass of B, Class B is the declaringClass of C, ..., Class Z is the
1473
* declaringClass of A, which forms a circle in the entries, whether or not the relationships between two classes
1474
* literally exist. e.g.
1475
* The specified declaringClass is fake one (intentionally set in the class file) which actually has no
1476
* relationship with current class but the current class is the declaring class of the specified declaringClass.
1477
* Thus, there are 3 cases:
1478
* 1) A --> B (real/fake) --> A: B is the declaring class of A and is one of the inner classes of A.
1479
* 2) B --> A --> A: B is the declaring class of A while A is one of the inner classes of A itself.
1480
* 3) A --> B --> C --> ... Z --> A: keep fetching the declaring class from A ends up wit A itself.
1481
*/
1482
return null;
1483
}
1484
1485
/*[MSG "K0555", "incompatible InnerClasses attribute between \"{0}\" and \"{1}\""]*/
1486
throw new IncompatibleClassChangeError(
1487
com.ibm.oti.util.Msg.getString("K0555", this.getName(), declaringClass.getName())); //$NON-NLS-1$
1488
}
1489
1490
/**
1491
* Checks whether the current class exists in the InnerClass attribute of the specified enclosing class
1492
* when this class is not defined directly inside the enclosing class (e.g. defined inside a method).
1493
*
1494
* Note: The direct inner classes of the declaring class is already checked in getDeclaringClass()
1495
* when the enclosing class is the declaring class.
1496
*/
1497
private void checkInnerClassAttrOfEnclosingClass() {
1498
Class<?> enclosingClass = getEnclosingObjectClass();
1499
if ((enclosingClass != null) && !enclosingClass.isClassAnEnclosedClass(this)) {
1500
/*[MSG "K0555", "incompatible InnerClasses attribute between \"{0}\" and \"{1}\""]*/
1501
throw new IncompatibleClassChangeError(
1502
com.ibm.oti.util.Msg.getString("K0555", this.getName(), enclosingClass.getName())); //$NON-NLS-1$
1503
}
1504
}
1505
1506
/**
1507
* Returns true if a cycle exists from the current class to itself by repeatedly searching the declaring classes.
1508
*
1509
* @return true if the cycle exists, false otherwise.
1510
*
1511
*/
1512
private native boolean isCircularDeclaringClass();
1513
1514
/**
1515
* Returns true if the class passed in to the method is a declared class of
1516
* this class.
1517
*
1518
* @param aClass The class to validate
1519
* @return true if aClass a declared class of this class
1520
* false otherwise.
1521
*
1522
*/
1523
private native boolean isClassADeclaredClass(Class<?> aClass);
1524
1525
/**
1526
* Returns true if the class passed in to the method is an enclosed class of
1527
* this class, which includes both the declared classes and the classes defined
1528
* inside a method of this class.
1529
*
1530
* @param aClass The class to validate
1531
* @return true if aClass an enclosed class of this class
1532
* false otherwise.
1533
*
1534
*/
1535
private native boolean isClassAnEnclosedClass(Class<?> aClass);
1536
1537
/**
1538
* Answers the class which declared the class represented
1539
* by the receiver. This will return null if the receiver
1540
* is a member of another class.
1541
*
1542
* @return the declaring class of the receiver.
1543
*/
1544
private native Class<?> getDeclaringClassImpl();
1545
1546
/**
1547
* Answers a Field object describing the field in the receiver
1548
* named by the argument which must be visible from the current
1549
* execution context.
1550
*
1551
* @param name The name of the field to look for.
1552
* @return the field in the receiver named by the argument.
1553
* @throws NoSuchFieldException If the given field does not exist
1554
* @throws SecurityException If access is denied
1555
*
1556
* @see #getDeclaredFields
1557
*/
1558
@CallerSensitive
1559
public Field getField(String name) throws NoSuchFieldException, SecurityException {
1560
@SuppressWarnings("removal")
1561
SecurityManager security = System.getSecurityManager();
1562
if (security != null) {
1563
ClassLoader callerClassLoader = ClassLoader.getStackClassLoader(1);
1564
checkMemberAccess(security, callerClassLoader, Member.PUBLIC);
1565
}
1566
1567
/*[PR CMVC 114820, CMVC 115873, CMVC 116166] add reflection cache */
1568
Field cachedField = lookupCachedField(name);
1569
if (cachedField != null && Modifier.isPublic(cachedField.getModifiers())) {
1570
return cachedField;
1571
}
1572
1573
/*[PR CMVC 192714,194493] prepare the class before attempting to access members */
1574
J9VMInternals.prepare(this);
1575
1576
Field field = getFieldImpl(name);
1577
1578
if (0 == Reflection.filterFields(this, new Field[] {field}).length) {
1579
throw new NoSuchFieldException(name);
1580
}
1581
1582
return cacheField(field);
1583
}
1584
1585
/**
1586
* Answers a Field object describing the field in the receiver
1587
* named by the argument which must be visible from the current
1588
* execution context.
1589
*
1590
* @param name The name of the field to look for.
1591
* @return the field in the receiver named by the argument.
1592
* @throws NoSuchFieldException If the given field does not exist
1593
*
1594
* @see #getDeclaredFields
1595
*/
1596
private native Field getFieldImpl(String name) throws NoSuchFieldException;
1597
1598
/**
1599
* Answers an array containing Field objects describing
1600
* all fields which are visible from the current execution
1601
* context.
1602
*
1603
* @return all visible fields starting from the receiver.
1604
* @throws SecurityException If member access is not allowed
1605
*
1606
* @see #getDeclaredFields
1607
*/
1608
@CallerSensitive
1609
public Field[] getFields() throws SecurityException {
1610
@SuppressWarnings("removal")
1611
SecurityManager security = System.getSecurityManager();
1612
if (security != null) {
1613
ClassLoader callerClassLoader = ClassLoader.getStackClassLoader(1);
1614
checkMemberAccess(security, callerClassLoader, Member.PUBLIC);
1615
}
1616
1617
/*[PR CMVC 114820, CMVC 115873, CMVC 116166] add reflection cache */
1618
Field[] cachedFields = lookupCachedFields(CacheKey.PublicFieldsKey);
1619
if (cachedFields != null) {
1620
return cachedFields;
1621
}
1622
1623
/*[PR CMVC 192714,194493] prepare the class before attempting to access members */
1624
J9VMInternals.prepare(this);
1625
1626
Field[] fields = getFieldsImpl();
1627
1628
return cacheFields(Reflection.filterFields(this, fields), CacheKey.PublicFieldsKey);
1629
}
1630
1631
/**
1632
* Answers an array containing Field objects describing
1633
* all fields which are visible from the current execution
1634
* context.
1635
*
1636
* @return all visible fields starting from the receiver.
1637
*
1638
* @see #getDeclaredFields
1639
*/
1640
private native Field[] getFieldsImpl();
1641
1642
/**
1643
* Answers an array of Class objects which match the interfaces
1644
* specified in the receiver classes <code>implements</code>
1645
* declaration
1646
*
1647
* @return {@code Class<?>[]}
1648
* the interfaces the receiver claims to implement.
1649
*/
1650
public Class<?>[] getInterfaces() {
1651
if (cachedInterfacesOffset == -1) {
1652
cachedInterfacesOffset = getFieldOffset("cachedInterfaces"); //$NON-NLS-1$
1653
}
1654
if (cachedInterfaces == null) {
1655
writeFieldValue(cachedInterfacesOffset, J9VMInternals.getInterfaces(this));
1656
}
1657
Class<?>[] newInterfaces = cachedInterfaces.length == 0 ? cachedInterfaces: cachedInterfaces.clone();
1658
return newInterfaces;
1659
}
1660
1661
/**
1662
* Answers a Method object which represents the method
1663
* described by the arguments.
1664
*
1665
* @param name String
1666
* the name of the method
1667
* @param parameterTypes {@code Class<?>[]}
1668
* the types of the arguments.
1669
* @return Method
1670
* the method described by the arguments.
1671
* @throws NoSuchMethodException
1672
* if the method could not be found.
1673
* @throws SecurityException
1674
* if member access is not allowed
1675
*
1676
* @see #getMethods
1677
*/
1678
@CallerSensitive
1679
public Method getMethod(String name, Class<?>... parameterTypes) throws NoSuchMethodException, SecurityException {
1680
@SuppressWarnings("removal")
1681
SecurityManager security = System.getSecurityManager();
1682
if (security != null) {
1683
ClassLoader callerClassLoader = ClassLoader.getStackClassLoader(1);
1684
checkMemberAccess(security, callerClassLoader, Member.PUBLIC);
1685
}
1686
return getMethodHelper(true, false, null, name, parameterTypes);
1687
}
1688
1689
/**
1690
* Helper method throws NoSuchMethodException when throwException is true, otherwise returns null.
1691
*/
1692
private Method throwExceptionOrReturnNull(boolean throwException, String name, Class<?>... parameterTypes) throws NoSuchMethodException {
1693
if (throwException) {
1694
throw newNoSuchMethodException(name, parameterTypes);
1695
} else {
1696
return null;
1697
}
1698
}
1699
/**
1700
* Helper method for
1701
* public Method getDeclaredMethod(String name, Class<?>... parameterTypes)
1702
* public Method getMethod(String name, Class<?>... parameterTypes)
1703
* List<Method> getDeclaredPublicMethods(String name, Class<?>... parameterTypes)
1704
* without going thorough security checking
1705
*
1706
* @param throwException boolean
1707
* true - throw exception in this helper;
1708
* false - return null instead without throwing NoSuchMethodException
1709
* @param forDeclaredMethod boolean
1710
* true - for getDeclaredMethod(String name, Class<?>... parameterTypes)
1711
* & getDeclaredPublicMethods(String name, Class<?>... parameterTypes);
1712
* false - for getMethod(String name, Class<?>... parameterTypes);
1713
* @param name String the name of the method
1714
* @param parameterTypes Class<?>[] the types of the arguments
1715
* @param methodList List<Method> a list to store the methods described by the arguments
1716
* for getDeclaredPublicMethods()
1717
* or null for getDeclaredMethod() & getMethod()
1718
* @return Method the method described by the arguments.
1719
* @throws NoSuchMethodException if the method could not be found.
1720
*/
1721
@CallerSensitive
1722
Method getMethodHelper(
1723
boolean throwException, boolean forDeclaredMethod, List<Method> methodList, String name, Class<?>... parameterTypes)
1724
throws NoSuchMethodException {
1725
Method result;
1726
Method bestCandidate;
1727
String strSig;
1728
boolean candidateFromInterface = false;
1729
1730
/*[PR CMVC 114820, CMVC 115873, CMVC 116166] add reflection cache */
1731
if (parameterTypes == null) {
1732
parameterTypes = EmptyParameters;
1733
}
1734
if (methodList == null) {
1735
// getDeclaredPublicMethods() has to go through all methods anyway
1736
Method cachedMethod = lookupCachedMethod(name, parameterTypes);
1737
if ((cachedMethod != null)
1738
&& ((forDeclaredMethod && (cachedMethod.getDeclaringClass() == this))
1739
|| (!forDeclaredMethod && Modifier.isPublic(cachedMethod.getModifiers())))) {
1740
return cachedMethod;
1741
}
1742
}
1743
1744
/*[PR CMVC 192714,194493] prepare the class before attempting to access members */
1745
J9VMInternals.prepare(this);
1746
1747
// Handle the no parameter case upfront
1748
/*[PR 103441] should throw NullPointerException when name is null */
1749
if (name == null || parameterTypes.length == 0) {
1750
strSig = "()"; //$NON-NLS-1$
1751
parameterTypes = EmptyParameters;
1752
} else {
1753
parameterTypes = parameterTypes.clone();
1754
// Build a signature for the requested method.
1755
strSig = getParameterTypesSignature(throwException, name, parameterTypes, ""); //$NON-NLS-1$
1756
if (strSig == null) {
1757
return null;
1758
}
1759
}
1760
1761
if (forDeclaredMethod) {
1762
result = getDeclaredMethodImpl(name, parameterTypes, strSig, null);
1763
} else {
1764
if (this.isInterface()) {
1765
/* if the result is not in the current class, all superinterfaces will need to be searched */
1766
result = getDeclaredMethodImpl(name, parameterTypes, strSig, null);
1767
if (null == result) {
1768
result = getMostSpecificMethodFromAllInterfacesOfCurrentClass(null, null, name, parameterTypes);
1769
candidateFromInterface = true;
1770
}
1771
} else {
1772
result = getMethodImpl(name, parameterTypes, strSig);
1773
/* Retrieve the specified method implemented by the superclass from the top to the bottom. */
1774
if ((result != null) && result.getDeclaringClass().isInterface()) {
1775
HashMap<Class<?>, HashMap<MethodInfo, MethodInfo>> infoCache = new HashMap<>(16);
1776
result = getMostSpecificMethodFromAllInterfacesOfAllSuperclasses(infoCache, name, parameterTypes);
1777
candidateFromInterface = true;
1778
}
1779
}
1780
}
1781
1782
if (result == null) {
1783
return throwExceptionOrReturnNull(throwException, name, parameterTypes);
1784
}
1785
if (0 == Reflection.filterMethods(this, new Method[] {result}).length) {
1786
return throwExceptionOrReturnNull(throwException, name, parameterTypes);
1787
}
1788
1789
/*[PR 127079] Use declaring classloader for Methods */
1790
/*[PR CMVC 104523] ensure parameter types are visible in the receiver's class loader */
1791
if (parameterTypes.length > 0) {
1792
ClassLoader loader = forDeclaredMethod ? getClassLoaderImpl() : result.getDeclaringClass().getClassLoaderImpl();
1793
for (int i = 0; i < parameterTypes.length; ++i) {
1794
Class<?> parameterType = parameterTypes[i];
1795
if (!parameterType.isPrimitive()) {
1796
try {
1797
if (Class.forName(parameterType.getName(), false, loader) != parameterType) {
1798
return throwExceptionOrReturnNull(throwException, name, parameterTypes);
1799
}
1800
} catch(ClassNotFoundException e) {
1801
return throwExceptionOrReturnNull(throwException, name, parameterTypes);
1802
}
1803
}
1804
}
1805
}
1806
if ((methodList != null) && ((result.getModifiers() & Modifier.PUBLIC) != 0)) {
1807
methodList.add(result);
1808
}
1809
1810
/* [PR 113003] The native is called repeatedly until it returns null,
1811
* as each call returns another match if one exists. The first call uses
1812
* getMethodImpl which searches across superclasses and interfaces, but
1813
* since the spec requires that we only weigh multiple matches against
1814
* each other if they are in the same class, on subsequent calls we call
1815
* getDeclaredMethodImpl on the declaring class of the first hit.
1816
* If more than one match is found, more specific method is selected.
1817
* For methods with same signature (name, parameter types) but different return types,
1818
* Method N with return type S is more specific than M with return type R if:
1819
* S is the same as or a subtype of R.
1820
* Otherwise, the result method is chosen arbitrarily from specific methods.
1821
*/
1822
bestCandidate = result;
1823
if (!candidateFromInterface) {
1824
Class<?> declaringClass = forDeclaredMethod ? this : result.getDeclaringClass();
1825
while (true) {
1826
result = declaringClass.getDeclaredMethodImpl(name, parameterTypes, strSig, result);
1827
if (result == null) {
1828
break;
1829
}
1830
boolean publicMethod = ((result.getModifiers() & Modifier.PUBLIC) != 0);
1831
if ((methodList != null) && publicMethod) {
1832
methodList.add(result);
1833
}
1834
if (forDeclaredMethod || publicMethod) {
1835
// bestCandidate and result have same declaringClass.
1836
Class<?> candidateRetType = bestCandidate.getReturnType();
1837
Class<?> resultRetType = result.getReturnType();
1838
if ((candidateRetType != resultRetType) && candidateRetType.isAssignableFrom(resultRetType)) {
1839
bestCandidate = result;
1840
}
1841
}
1842
}
1843
}
1844
return cacheMethod(bestCandidate);
1845
}
1846
1847
/**
1848
* Helper method searches all interfaces implemented by superclasses from the top to the bottom
1849
* for the most specific method declared in one of these interfaces.
1850
*
1851
* @param infoCache
1852
* @param name the specified method's name
1853
* @param parameterTypes the types of the arguments of the specified method
1854
* @return the most specific method selected from all interfaces from each superclass of the current class;
1855
* otherwise, return the method of the first interface from the top superclass
1856
* if the return types of all specified methods are identical.
1857
*/
1858
private Method getMostSpecificMethodFromAllInterfacesOfAllSuperclasses(HashMap<Class<?>, HashMap<MethodInfo, MethodInfo>> infoCache,
1859
String name, Class<?>... parameterTypes)
1860
{
1861
Method candidateMethod = null;
1862
if (this != Object.class) {
1863
/* get to the top superclass first. if all return types end up being the same the interfaces from this superclass have priority. */
1864
Class superclz = getSuperclass();
1865
candidateMethod = superclz.getMostSpecificMethodFromAllInterfacesOfAllSuperclasses(infoCache, name, parameterTypes);
1866
1867
/* search all interfaces of current class, comparing against result from previous superclass. */
1868
candidateMethod = getMostSpecificMethodFromAllInterfacesOfCurrentClass(infoCache, candidateMethod, name, parameterTypes);
1869
}
1870
return candidateMethod;
1871
}
1872
1873
/**
1874
* Helper method searches all interfaces implemented by the current class or interface
1875
* for the most specific method declared in one of these interfaces.
1876
*
1877
* @param infoCache
1878
* @param potentialCandidate potential candidate from superclass, null if currentClass is an interface
1879
* @param name the specified method's name
1880
* @param parameterTypes the types of the arguments of the specified method
1881
* @return the most specific method selected from all interfaces;
1882
* otherwise if return types from all qualifying methods are identical, return an arbitrary method.
1883
*/
1884
private Method getMostSpecificMethodFromAllInterfacesOfCurrentClass(HashMap<Class<?>, HashMap<MethodInfo, MethodInfo>> infoCache,
1885
Method potentialCandidate, String name, Class<?>... parameterTypes)
1886
{
1887
Method bestMethod = potentialCandidate;
1888
/* if infoCache is passed in, reuse from superclass */
1889
if (null == infoCache) {
1890
infoCache = new HashMap<>(16);
1891
}
1892
HashMap<MethodInfo, MethodInfo> methodCandidates = getMethodSet(infoCache, false, true);
1893
1894
for (MethodInfo mi : methodCandidates.values()) {
1895
if (null == mi.jlrMethods) {
1896
bestMethod = getMostSpecificInterfaceMethod(name, parameterTypes, bestMethod, mi.me);
1897
} else {
1898
for (Method m: mi.jlrMethods) {
1899
bestMethod = getMostSpecificInterfaceMethod(name, parameterTypes, bestMethod, m);
1900
/*[IF JAVA_SPEC_VERSION == 8]*/
1901
// Java 8 returns any matching method found
1902
if (bestMethod != null) {
1903
break;
1904
}
1905
/*[ENDIF] JAVA_SPEC_VERSION == 8 */
1906
}
1907
}
1908
/*[IF JAVA_SPEC_VERSION == 8]*/
1909
if (bestMethod != null) {
1910
break;
1911
}
1912
/*[ENDIF] JAVA_SPEC_VERSION == 8 */
1913
}
1914
1915
return bestMethod;
1916
1917
}
1918
1919
private static Method getMostSpecificInterfaceMethod(String name, Class<?>[] parameterTypes, Method bestMethod, Method candidateMethod) {
1920
if (candidateMethod == bestMethod) {
1921
return bestMethod;
1922
}
1923
1924
/* match name and parameters to user specification */
1925
if (!candidateMethod.getDeclaringClass().isInterface()
1926
|| !candidateMethod.getName().equals(name)
1927
|| !doParameterTypesMatch(candidateMethod.getParameterTypes(), parameterTypes)
1928
) {
1929
return bestMethod;
1930
}
1931
1932
if (null == bestMethod) {
1933
bestMethod = candidateMethod;
1934
return bestMethod;
1935
}
1936
1937
Class<?> bestRetType = bestMethod.getReturnType();
1938
Class<?> candidateRetType = candidateMethod.getReturnType();
1939
1940
if (bestRetType == candidateRetType) {
1941
int bestModifiers = bestMethod.getModifiers();
1942
int candidateModifiers = candidateMethod.getModifiers();
1943
Class<?> bestDeclaringClass = bestMethod.getDeclaringClass();
1944
Class<?> candidateDeclaringClass = candidateMethod.getDeclaringClass();
1945
/* if all return types end up being the same, non-static methods take priority over static methods and sub-interfaces take
1946
priority over superinterface */
1947
if ((Modifier.isStatic(bestModifiers) && !Modifier.isStatic(candidateModifiers))
1948
|| methodAOverridesMethodB(candidateDeclaringClass, Modifier.isAbstract(candidateModifiers), candidateDeclaringClass.isInterface(),
1949
bestDeclaringClass, Modifier.isAbstract(bestModifiers), bestDeclaringClass.isInterface())
1950
) {
1951
bestMethod = candidateMethod;
1952
}
1953
} else {
1954
/* resulting method should have the most specific return type */
1955
if (bestRetType.isAssignableFrom(candidateRetType)) {
1956
bestMethod = candidateMethod;
1957
}
1958
}
1959
1960
return bestMethod;
1961
}
1962
1963
private static boolean doParameterTypesMatch(Class<?>[] paramList1, Class<?>[] paramList2) {
1964
if (paramList1.length != paramList2.length) return false;
1965
1966
for (int index = 0; index < paramList1.length; index++) {
1967
if (!paramList1[index].equals(paramList2[index])) {
1968
return false;
1969
}
1970
}
1971
1972
return true;
1973
}
1974
1975
/**
1976
* Answers a Method object which represents the first method found matching
1977
* the arguments.
1978
*
1979
* @param name String
1980
* the name of the method
1981
* @param parameterTypes Class<?>[]
1982
* the types of the arguments.
1983
* @param partialSignature String
1984
* the signature of the method, without return type.
1985
* @return Object
1986
* the first Method found matching the arguments
1987
*
1988
* @see #getMethods
1989
*/
1990
private native Method getMethodImpl(String name, Class<?>[] parameterTypes, String partialSignature);
1991
1992
/**
1993
* Answers an array containing Method objects describing
1994
* all methods which are visible from the current execution
1995
* context.
1996
*
1997
* @return Method[]
1998
* all visible methods starting from the receiver.
1999
* @throws SecurityException
2000
* if member access is not allowed
2001
*
2002
* @see #getDeclaredMethods
2003
*/
2004
@CallerSensitive
2005
public Method[] getMethods() throws SecurityException {
2006
@SuppressWarnings("removal")
2007
SecurityManager security = System.getSecurityManager();
2008
if (security != null) {
2009
ClassLoader callerClassLoader = ClassLoader.getStackClassLoader(1);
2010
checkMemberAccess(security, callerClassLoader, Member.PUBLIC);
2011
}
2012
2013
Method[] methods;
2014
2015
/*[PR CMVC 114820, CMVC 115873, CMVC 116166] add reflection cache */
2016
methods = lookupCachedMethods(CacheKey.PublicMethodsKey);
2017
if (methods != null) {
2018
return methods;
2019
}
2020
2021
if(isPrimitive()) {
2022
return new Method[0];
2023
}
2024
2025
/*[PR CMVC 192714,194493] prepare the class before attempting to access members */
2026
J9VMInternals.prepare(this);
2027
HashMap<Class<?>, HashMap<MethodInfo, MethodInfo>> infoCache = new HashMap<>(16);
2028
HashMap<MethodInfo, MethodInfo> myMethods = getMethodSet(infoCache, false, false);
2029
ArrayList<Method> myMethodList = new ArrayList<>(16);
2030
for (MethodInfo mi: myMethods.values()) { /* don't know how big this will be at the start */
2031
if (null == mi.jlrMethods) {
2032
myMethodList.add(mi.me);
2033
} else {
2034
for (Method m: mi.jlrMethods) {
2035
myMethodList.add(m);
2036
}
2037
}
2038
}
2039
methods = myMethodList.toArray(new Method[myMethodList.size()]);
2040
return cacheMethods(Reflection.filterMethods(this, methods), CacheKey.PublicMethodsKey);
2041
}
2042
2043
private HashMap<MethodInfo, MethodInfo> getMethodSet(
2044
HashMap<Class<?>, HashMap<MethodInfo, MethodInfo>> infoCache,
2045
boolean virtualOnly, boolean localInterfacesOnly) {
2046
/* virtualOnly must be false only for the bottom class of the hierarchy */
2047
HashMap<MethodInfo, MethodInfo> myMethods = infoCache.get(this);
2048
if (null == myMethods) {
2049
/* haven't visited this class. Initialize with the methods from the VTable which take priority */
2050
myMethods = new HashMap<>(16);
2051
if (!isInterface() && !localInterfacesOnly) {
2052
int vCount = 0;
2053
int sCount = 0;
2054
Method methods[] = null; /* this includes the superclass's virtual and static methods. */
2055
Set<MethodInfo> methodFilter = null;
2056
boolean noHotswap = true;
2057
do {
2058
/* atomically get the list of methods, iterate if a hotswap occurred */
2059
vCount = getVirtualMethodCountImpl(); /* returns only public methods */
2060
sCount = getStaticMethodCountImpl();
2061
methods = (Method[])Method.class.allocateAndFillArray(vCount + sCount);
2062
if (null == methods) {
2063
throw new Error("Error retrieving class methods"); //$NON-NLS-1$
2064
}
2065
noHotswap = (getVirtualMethodsImpl(methods, 0, vCount) && getStaticMethodsImpl(methods, vCount, sCount));
2066
} while (!noHotswap);
2067
/* if we are here, this is the target class, so return static and virtual methods */
2068
boolean scanInterfaces = false;
2069
for (Method m: methods) {
2070
Class<?> mDeclaringClass = m.getDeclaringClass();
2071
MethodInfo mi = new MethodInfo(m);
2072
MethodInfo prevMI = myMethods.put(mi, mi);
2073
if (prevMI != null) {
2074
/* As per Java spec:
2075
* For methods with same signature (name, parameter types) and return type,
2076
* only the most specific method should be selected.
2077
* Method N is more specific than M if:
2078
* N is declared by a class and M is declared by an interface; or
2079
* N and M are both declared by either classes or interfaces and N's
2080
* declaring type is the same as or a subtype of M's declaring type.
2081
*/
2082
Class<?> prevMIDeclaringClass = prevMI.me.getDeclaringClass();
2083
if ((mDeclaringClass.isInterface() && !prevMIDeclaringClass.isInterface())
2084
|| (mDeclaringClass.isAssignableFrom(prevMIDeclaringClass))
2085
) {
2086
myMethods.put(prevMI, prevMI);
2087
}
2088
}
2089
if (mDeclaringClass.isInterface()) {
2090
scanInterfaces = true;
2091
/* Add all the interfaces at once to preserve ordering */
2092
myMethods.remove(mi, mi);
2093
}
2094
}
2095
if (scanInterfaces) {
2096
/* methodFilter is guaranteed to be non-null at this point */
2097
addInterfaceMethods(infoCache, methodFilter, myMethods, localInterfacesOnly);
2098
}
2099
} else {
2100
if (!localInterfacesOnly || isInterface()) {
2101
/* this is an interface and doesn't have a vTable, but may have static or private methods */
2102
for (Method m: getDeclaredMethods()) {
2103
int methodModifiers = m.getModifiers();
2104
if ((virtualOnly && Modifier.isStatic(methodModifiers)) || !Modifier.isPublic(methodModifiers)){
2105
continue;
2106
}
2107
MethodInfo mi = new MethodInfo(m);
2108
myMethods.put(mi, mi);
2109
}
2110
}
2111
addInterfaceMethods(infoCache, null, myMethods, localInterfacesOnly);
2112
}
2113
infoCache.put(this, myMethods); /* save results for future use */
2114
}
2115
return myMethods;
2116
}
2117
2118
/**
2119
* Add methods defined in this class's interfaces or those of superclasses
2120
* @param infoCache Cache of previously visited method lists
2121
* @param methodFilter List of methods to include. If null, include all
2122
* @param myMethods non-null if you want to update an existing list
2123
* @return list of methods with their various declarations
2124
*/
2125
private HashMap<MethodInfo, MethodInfo> addInterfaceMethods(
2126
HashMap<Class<?>, HashMap<MethodInfo, MethodInfo>> infoCache,
2127
Set<MethodInfo> methodFilter,
2128
HashMap<MethodInfo, MethodInfo> myMethods, boolean localInterfacesOnly) {
2129
boolean addToCache = false;
2130
boolean updateList = (null != myMethods);
2131
if (!updateList) {
2132
myMethods = infoCache.get(this);
2133
}
2134
if (null == myMethods) {
2135
/* haven't visited this class */
2136
myMethods = new HashMap<>();
2137
addToCache = true;
2138
updateList = true;
2139
}
2140
if (updateList) {
2141
Class mySuperclass = getSuperclass();
2142
if (!isInterface() && (Object.class != mySuperclass)) {
2143
/* some interface methods are visible via the superclass */
2144
HashMap<MethodInfo, MethodInfo> superclassMethods = mySuperclass.addInterfaceMethods(infoCache, methodFilter, null, localInterfacesOnly);
2145
for (MethodInfo otherInfo: superclassMethods.values()) {
2146
if ((null == methodFilter) || methodFilter.contains(otherInfo)) {
2147
addMethod(myMethods, otherInfo);
2148
}
2149
}
2150
}
2151
for (Class intf: getInterfaces()) {
2152
HashMap<MethodInfo, MethodInfo> intfMethods = intf.getMethodSet(infoCache, true, localInterfacesOnly);
2153
for (MethodInfo otherInfo: intfMethods.values()) {
2154
if ((null == methodFilter) || methodFilter.contains(otherInfo)) {
2155
addMethod(myMethods, otherInfo);
2156
}
2157
}
2158
}
2159
}
2160
if (addToCache) {
2161
infoCache.put(this, myMethods);
2162
/* save results for future use */
2163
}
2164
return myMethods;
2165
}
2166
2167
/* this is called only to add methods from implemented interfaces of a class or superinterfaces of an interface */
2168
private void addMethod(HashMap<MethodInfo, MethodInfo> myMethods, MethodInfo otherMi) {
2169
MethodInfo oldMi = myMethods.get(otherMi);
2170
if (null == oldMi) {
2171
/* haven't seen this method's name & sig */
2172
oldMi = new MethodInfo(otherMi);
2173
/* create a new MethodInfo object and add mi's Method objects to it */
2174
myMethods.put(oldMi, oldMi);
2175
} else {
2176
/* NB: the vTable has an abstract method for each method declared in the implemented interfaces */
2177
oldMi.update(otherMi); /* add the new method as appropriate */
2178
}
2179
}
2180
2181
private native int getVirtualMethodCountImpl();
2182
private native boolean getVirtualMethodsImpl(Method[] array, int start, int count);
2183
private native int getStaticMethodCountImpl();
2184
private native boolean getStaticMethodsImpl(Method[] array, int start, int count);
2185
private native Object[] allocateAndFillArray(int size);
2186
2187
/**
2188
* Answers an integer which is the receiver's modifiers.
2189
* Note that the constants which describe the bits which are
2190
* returned are implemented in class java.lang.reflect.Modifier
2191
* which may not be available on the target.
2192
*
2193
* @return the receiver's modifiers
2194
*/
2195
public int getModifiers() {
2196
/*[PR CMVC 89071, 89373] Return SYNTHETIC, ANNOTATION, ENUM modifiers */
2197
int rawModifiers = getModifiersImpl();
2198
if (isArray()) {
2199
rawModifiers &= Modifier.PUBLIC | Modifier.PRIVATE | Modifier.PROTECTED |
2200
Modifier.ABSTRACT | Modifier.FINAL;
2201
} else {
2202
rawModifiers &= Modifier.PUBLIC | Modifier.PRIVATE | Modifier.PROTECTED |
2203
Modifier.STATIC | Modifier.FINAL | Modifier.INTERFACE |
2204
Modifier.ABSTRACT | SYNTHETIC | ENUM | ANNOTATION;
2205
}
2206
return rawModifiers;
2207
}
2208
2209
private native int getModifiersImpl();
2210
2211
/*[IF Sidecar19-SE]*/
2212
/**
2213
* Answers the module to which the receiver belongs.
2214
* If this class doesn't belong to a named module, the unnamedModule of the classloader
2215
* loaded this class is returned;
2216
* If this class represents an array type, the module for the element type is returned;
2217
* If this class represents a primitive type or void, module java.base is returned.
2218
*
2219
* @return the module to which the receiver belongs
2220
*/
2221
public Module getModule()
2222
{
2223
return module;
2224
}
2225
/*[ENDIF] Sidecar19-SE */
2226
2227
/**
2228
* Answers the name of the class which the receiver represents.
2229
* For a description of the format which is used, see the class
2230
* definition of java.lang.Class.
2231
*
2232
* @return the receiver's name.
2233
*
2234
* @see java.lang.Class
2235
*/
2236
public String getName() {
2237
/*[PR CMVC 105714] Remove classNameMap (PR 115275) and always use getClassNameStringImpl() */
2238
String name = classNameString;
2239
if (name != null){
2240
return name;
2241
}
2242
//must have been null to set it
2243
return VM.getClassNameImpl(this, true);
2244
}
2245
2246
/**
2247
* Answers the ProtectionDomain of the receiver.
2248
* <p>
2249
* Note: In order to conserve space in embedded targets, we allow this
2250
* method to answer null for classes in the system protection domain
2251
* (i.e. for system classes). System classes are always given full
2252
* permissions (i.e. AllPermission). This is not changeable via the
2253
* java.security.Policy.
2254
*
2255
* @return ProtectionDomain
2256
* the receiver's ProtectionDomain.
2257
*
2258
* @see java.lang.Class
2259
*/
2260
public ProtectionDomain getProtectionDomain() {
2261
@SuppressWarnings("removal")
2262
SecurityManager security = System.getSecurityManager();
2263
if (security != null) {
2264
security.checkPermission(sun.security.util.SecurityConstants.GET_PD_PERMISSION);
2265
}
2266
return getProtectionDomainInternal();
2267
}
2268
2269
ProtectionDomain getProtectionDomainInternal() {
2270
ProtectionDomain result = getPDImpl();
2271
if (result != null) {
2272
return result;
2273
}
2274
if (AllPermissionsPD == null) {
2275
allocateAllPermissionsPD();
2276
}
2277
return AllPermissionsPD;
2278
}
2279
2280
private void allocateAllPermissionsPD() {
2281
Permissions collection = new Permissions();
2282
collection.add(sun.security.util.SecurityConstants.ALL_PERMISSION);
2283
AllPermissionsPD = new ProtectionDomain(null, collection);
2284
}
2285
2286
/**
2287
* Answers the ProtectionDomain of the receiver.
2288
* <p>
2289
* This method is for internal use only.
2290
*
2291
* @return ProtectionDomain
2292
* the receiver's ProtectionDomain.
2293
*
2294
* @see java.lang.Class
2295
*/
2296
ProtectionDomain getPDImpl() {
2297
/*[PR CMVC 125822] Move RAM class fields onto the heap to fix hotswap crash */
2298
return protectionDomain;
2299
}
2300
2301
/**
2302
* Helper method to get the name of the package of incoming non-array class.
2303
* returns an empty string if the class is in an unnamed package.
2304
*
2305
* @param clz a non-array class.
2306
* @return the package name of incoming non-array class.
2307
*/
2308
private static String getNonArrayClassPackageName(Class<?> clz) {
2309
String name = clz.getName();
2310
int index = name.lastIndexOf('.');
2311
if (index >= 0) {
2312
return name.substring(0, index).intern();
2313
}
2314
return ""; //$NON-NLS-1$
2315
}
2316
2317
/**
2318
* Answers the name of the package to which the receiver belongs.
2319
* For example, Object.class.getPackageName() returns "java.lang".
2320
* Returns "java.lang" if this class represents a primitive type or void,
2321
* and the element type's package name in the case of an array type.
2322
*
2323
* @return String the receiver's package name
2324
*
2325
* @see #getPackage
2326
*/
2327
/*[IF Sidecar19-SE]*/
2328
public
2329
/*[ENDIF] Sidecar19-SE */
2330
String getPackageName() {
2331
String packageName = this.packageNameString;
2332
if (null == packageName) {
2333
/*[IF Sidecar19-SE]*/
2334
if (isPrimitive()) {
2335
packageName = "java.lang"; //$NON-NLS-1$
2336
} else if (isArray()) {
2337
Class<?> componentType = getComponentType();
2338
while (componentType.isArray()) {
2339
componentType = componentType.getComponentType();
2340
}
2341
if (componentType.isPrimitive()) {
2342
packageName = "java.lang"; //$NON-NLS-1$
2343
} else {
2344
packageName = getNonArrayClassPackageName(componentType);
2345
}
2346
} else {
2347
packageName = getNonArrayClassPackageName(this);
2348
}
2349
/*[ELSE] Sidecar19-SE */
2350
packageName = getNonArrayClassPackageName(this);
2351
/*[ENDIF] Sidecar19-SE */
2352
this.packageNameString = packageName;
2353
}
2354
return packageName;
2355
}
2356
2357
/**
2358
* Answers a URL referring to the
2359
* resource specified by resName. The mapping between
2360
* the resource name and the URL is managed by the
2361
* class's class loader.
2362
*
2363
* @param resName the name of the resource.
2364
* @return a stream on the resource.
2365
*
2366
* @see java.lang.ClassLoader
2367
*/
2368
/*[IF Sidecar19-SE]*/
2369
@CallerSensitive
2370
/*[ENDIF] Sidecar19-SE */
2371
public URL getResource(String resName) {
2372
ClassLoader loader = this.getClassLoaderImpl();
2373
String absoluteResName = this.toResourceName(resName);
2374
URL result = null;
2375
/*[IF Sidecar19-SE]*/
2376
Module thisModule = getModule();
2377
if (useModularSearch(absoluteResName, thisModule, System.getCallerClass())) {
2378
try {
2379
result = loader.findResource(thisModule.getName(), absoluteResName);
2380
} catch (IOException e) {
2381
return null;
2382
}
2383
}
2384
if (null == result)
2385
/*[ENDIF] Sidecar19-SE */
2386
{
2387
if (loader == ClassLoader.bootstrapClassLoader) {
2388
result =ClassLoader.getSystemResource(absoluteResName);
2389
} else {
2390
result =loader.getResource(absoluteResName);
2391
}
2392
}
2393
return result;
2394
}
2395
2396
/**
2397
* Answers a read-only stream on the contents of the
2398
* resource specified by resName. The mapping between
2399
* the resource name and the stream is managed by the
2400
* class's class loader.
2401
*
2402
* @param resName the name of the resource.
2403
* @return a stream on the resource.
2404
*
2405
* @see java.lang.ClassLoader
2406
*/
2407
/*[IF Sidecar19-SE]*/
2408
@CallerSensitive
2409
/*[ENDIF] Sidecar19-SE */
2410
public InputStream getResourceAsStream(String resName) {
2411
ClassLoader loader = this.getClassLoaderImpl();
2412
String absoluteResName = this.toResourceName(resName);
2413
InputStream result = null;
2414
/*[IF Sidecar19-SE]*/
2415
Module thisModule = getModule();
2416
2417
if (useModularSearch(absoluteResName, thisModule, System.getCallerClass())) {
2418
try {
2419
result = thisModule.getResourceAsStream(absoluteResName);
2420
} catch (IOException e) {
2421
return null;
2422
}
2423
}
2424
if (null == result)
2425
/*[ENDIF] Sidecar19-SE */
2426
{
2427
if (loader == ClassLoader.bootstrapClassLoader) {
2428
result = ClassLoader.getSystemResourceAsStream(absoluteResName);
2429
} else {
2430
result = loader.getResourceAsStream(absoluteResName);
2431
}
2432
}
2433
return result;
2434
}
2435
2436
/*[IF Sidecar19-SE]*/
2437
/**
2438
* Indicate if the package should be looked up in a module or via the class path.
2439
* Look up the resource in the module if the module is named
2440
* and is the same module as the caller or the package is open to the caller.
2441
* The default package (i.e. resources at the root of the module) is considered open.
2442
*
2443
* @param absoluteResName name of resource, including package
2444
* @param thisModule module of the current class
2445
* @param callerClass class of method calling getResource() or getResourceAsStream()
2446
* @return true if modular lookup should be used.
2447
*/
2448
private boolean useModularSearch(String absoluteResName, Module thisModule, Class<?> callerClass) {
2449
boolean visible = false;
2450
2451
if (thisModule.isNamed()) {
2452
// When the caller class is null, assuming it is loaded by module java.base.
2453
// See https://github.com/eclipse-openj9/openj9/issues/8993 for more info.
2454
final Module callerModule = callerClass == null ? Class.class.getModule() : callerClass.getModule();
2455
visible = (thisModule == callerModule);
2456
if (!visible) {
2457
visible = absoluteResName.endsWith(".class"); //$NON-NLS-1$
2458
if (!visible) {
2459
// extract the package name
2460
int lastSlash = absoluteResName.lastIndexOf('/');
2461
if (-1 == lastSlash) { // no package name
2462
visible = true;
2463
} else {
2464
String result = absoluteResName.substring(0, lastSlash).replace('/', '.');
2465
visible = thisModule.isOpen(result, callerModule);
2466
}
2467
}
2468
}
2469
}
2470
return visible;
2471
}
2472
/*[ENDIF] Sidecar19-SE */
2473
2474
2475
/**
2476
* Answers a String object which represents the class's
2477
* signature, as described in the class definition of
2478
* java.lang.Class.
2479
*
2480
* @return the signature of the class.
2481
*
2482
* @see java.lang.Class
2483
*/
2484
private String getSignature() {
2485
if(isArray()) return getName(); // Array classes are named with their signature
2486
if(isPrimitive()) {
2487
// Special cases for each base type.
2488
if(this == void.class) return "V"; //$NON-NLS-1$
2489
if(this == boolean.class) return "Z"; //$NON-NLS-1$
2490
if(this == byte.class) return "B"; //$NON-NLS-1$
2491
if(this == char.class) return "C"; //$NON-NLS-1$
2492
if(this == short.class) return "S"; //$NON-NLS-1$
2493
if(this == int.class) return "I"; //$NON-NLS-1$
2494
if(this == long.class) return "J"; //$NON-NLS-1$
2495
if(this == float.class) return "F"; //$NON-NLS-1$
2496
if(this == double.class) return "D"; //$NON-NLS-1$
2497
}
2498
2499
// General case.
2500
// Create a buffer of the correct size
2501
String name = getName();
2502
return new StringBuilder(name.length() + 2).
2503
append('L').append(name).append(';').toString();
2504
}
2505
2506
/**
2507
* Answers the signers for the class represented by the
2508
* receiver, or null if there are no signers.
2509
*
2510
* @return the signers of the receiver.
2511
*
2512
* @see #getMethods
2513
*/
2514
public Object[] getSigners() {
2515
/*[PR CMVC 93861] allow setSigners() for bootstrap classes */
2516
return getClassLoaderImpl().getSigners(this);
2517
}
2518
2519
/**
2520
* Answers the Class which represents the receiver's
2521
* superclass. For Classes which represent base types,
2522
* interfaces, and for java.lang.Object the method
2523
* answers null.
2524
*
2525
* @return the receiver's superclass.
2526
*/
2527
public Class<? super T> getSuperclass()
2528
{
2529
return J9VMInternals.getSuperclass(this);
2530
}
2531
2532
/**
2533
* Answers true if the receiver represents an array class.
2534
*
2535
* @return <code>true</code>
2536
* if the receiver represents an array class
2537
* <code>false</code>
2538
* if it does not represent an array class
2539
*/
2540
public native boolean isArray();
2541
2542
/**
2543
* Answers true if the type represented by the argument
2544
* can be converted via an identity conversion or a widening
2545
* reference conversion (i.e. if either the receiver or the
2546
* argument represent primitive types, only the identity
2547
* conversion applies).
2548
*
2549
* @return <code>true</code>
2550
* the argument can be assigned into the receiver
2551
* <code>false</code>
2552
* the argument cannot be assigned into the receiver
2553
* @param cls Class
2554
* the class to test
2555
* @throws NullPointerException
2556
* if the parameter is null
2557
*
2558
*/
2559
public native boolean isAssignableFrom(Class<?> cls);
2560
2561
/**
2562
* Answers true if the argument is non-null and can be
2563
* cast to the type of the receiver. This is the runtime
2564
* version of the <code>instanceof</code> operator.
2565
*
2566
* @return <code>true</code>
2567
* the argument can be cast to the type of the receiver
2568
* <code>false</code>
2569
* the argument is null or cannot be cast to the
2570
* type of the receiver
2571
*
2572
* @param object Object
2573
* the object to test
2574
*/
2575
public native boolean isInstance(Object object);
2576
2577
/**
2578
* Answers true if the receiver represents an interface.
2579
*
2580
* @return <code>true</code>
2581
* if the receiver represents an interface
2582
* <code>false</code>
2583
* if it does not represent an interface
2584
*/
2585
public boolean isInterface() {
2586
// This code has been inlined in toGenericString. toGenericString
2587
// must be modified to reflect any changes to this implementation.
2588
return !isArray() && (getModifiersImpl() & 512 /* AccInterface */) != 0;
2589
}
2590
2591
/**
2592
* Answers true if the receiver represents a base type.
2593
*
2594
* @return <code>true</code>
2595
* if the receiver represents a base type
2596
* <code>false</code>
2597
* if it does not represent a base type
2598
*/
2599
public native boolean isPrimitive();
2600
2601
/*[IF INLINE-TYPES]*/
2602
/**
2603
* Answers true if the receiver represents a primitive class type. Array classes
2604
* return false.
2605
*
2606
* @return true if receiver is primitive class type, and false otherwise.
2607
*/
2608
public native boolean isPrimitiveClass();
2609
2610
/**
2611
* Answers true if the receiver represents a value class type. Array classes
2612
* return false.
2613
*
2614
* @return true if receiver is a value class type, and false otherwise.
2615
*/
2616
public native boolean isValue();
2617
2618
/**
2619
* ToDo: add comments for public methods - https://github.com/eclipse-openj9/openj9/issues/13615
2620
*/
2621
public Class<?> asPrimaryType() {
2622
// ToDo: this is a temporary implementation - https://github.com/eclipse-openj9/openj9/issues/13615
2623
return this;
2624
}
2625
public Class<?> asValueType() {
2626
// ToDo: this is a temporary implementation - https://github.com/eclipse-openj9/openj9/issues/13615
2627
return this;
2628
}
2629
public boolean isPrimaryType() {
2630
// ToDo: this is a temporary implementation - https://github.com/eclipse-openj9/openj9/issues/13615
2631
return true;
2632
}
2633
public boolean isPrimitiveValueType() {
2634
// ToDo: this is a temporary implementation - https://github.com/eclipse-openj9/openj9/issues/13615
2635
return false;
2636
}
2637
/*[ENDIF] INLINE-TYPES */
2638
2639
/**
2640
* Answers a new instance of the class represented by the
2641
* receiver, created by invoking the default (i.e. zero-argument)
2642
* constructor. If there is no such constructor, or if the
2643
* creation fails (either because of a lack of available memory or
2644
* because an exception is thrown by the constructor), an
2645
* InstantiationException is thrown. If the default constructor
2646
* exists, but is not accessible from the context where this
2647
* message is sent, an IllegalAccessException is thrown.
2648
*
2649
* @return a new instance of the class represented by the receiver.
2650
* @throws IllegalAccessException if the constructor is not visible to the sender.
2651
* @throws InstantiationException if the instance could not be created.
2652
*/
2653
@CallerSensitive
2654
/*[IF Sidecar19-SE]*/
2655
@Deprecated(forRemoval=false, since="9")
2656
/*[ENDIF]*/
2657
public T newInstance() throws IllegalAccessException, InstantiationException {
2658
@SuppressWarnings("removal")
2659
SecurityManager security = System.getSecurityManager();
2660
if (security != null) {
2661
ClassLoader callerClassLoader = ClassLoader.getStackClassLoader(1);
2662
checkNonSunProxyMemberAccess(security, callerClassLoader, Member.PUBLIC);
2663
}
2664
2665
/*[IF JAVA_SPEC_VERSION >= 12]*/
2666
Class<?> callerClazz = getStackClass(1);
2667
if (callerClazz.classLoader == ClassLoader.bootstrapClassLoader) {
2668
/* newInstanceImpl() is required for all bootstrap classes to avoid an infinite loop
2669
* when calling copyConstructor.invoke() in cacheConstructor() at the bootstrap stage
2670
* as the constructors of bootstrap classes are not yet cached for use at that time.
2671
*/
2672
return (T)J9VMInternals.newInstanceImpl(this);
2673
} else {
2674
try {
2675
Constructor<?> ctr = getDeclaredConstructor();
2676
reflectionFactory = getReflectionFactory();
2677
return (T)reflectionFactory.newInstance(ctr, null, callerClazz);
2678
} catch (NoSuchMethodException e) {
2679
InstantiationException instantiationEx = new InstantiationException();
2680
throw (InstantiationException)instantiationEx.initCause(e);
2681
} catch (InvocationTargetException e) {
2682
getUnsafe().throwException(e.getCause());
2683
return null; //unreachable but required in compilation
2684
}
2685
}
2686
/*[ELSE] JAVA_SPEC_VERSION >= 12*/
2687
return (T)J9VMInternals.newInstanceImpl(this);
2688
/*[ENDIF] JAVA_SPEC_VERSION >= 12*/
2689
}
2690
2691
/**
2692
* Used as a prototype for the jit.
2693
*
2694
* @param callerClass
2695
* @return the object
2696
* @throws InstantiationException
2697
*/
2698
/*[PR CMVC 114139]InstantiationException has wrong detail message */
2699
private Object newInstancePrototype(Class<?> callerClass) throws InstantiationException {
2700
/*[PR 96623]*/
2701
throw new InstantiationException(this);
2702
}
2703
2704
2705
/**
2706
* Answers a string describing a path to the receiver's appropriate
2707
* package specific subdirectory, with the argument appended if the
2708
* argument did not begin with a slash. If it did, answer just the
2709
* argument with the leading slash removed.
2710
*
2711
* @return String
2712
* the path to the resource.
2713
* @param resName String
2714
* the name of the resource.
2715
*
2716
* @see #getResource
2717
* @see #getResourceAsStream
2718
*/
2719
private String toResourceName(String resName) {
2720
// Turn package name into a directory path
2721
if (resName.length() > 0 && resName.charAt(0) == '/')
2722
return resName.substring(1);
2723
2724
Class<?> thisObject = this;
2725
while (thisObject.isArray()) {
2726
thisObject = thisObject.getComponentType();
2727
}
2728
2729
String qualifiedClassName = thisObject.getName();
2730
int classIndex = qualifiedClassName.lastIndexOf('.');
2731
if (classIndex == -1) return resName; // from a default package
2732
return qualifiedClassName.substring(0, classIndex + 1).replace('.', '/') + resName;
2733
}
2734
2735
/**
2736
* Answers a string containing a concise, human-readable
2737
* description of the receiver.
2738
*
2739
* @return a printable representation for the receiver.
2740
*/
2741
@Override
2742
public String toString() {
2743
// Note change from 1.1.7 to 1.2: For primitive types,
2744
// return just the type name.
2745
if (isPrimitive()) return getName();
2746
return (isInterface() ? "interface " : "class ") + getName(); //$NON-NLS-1$ //$NON-NLS-2$
2747
}
2748
2749
/**
2750
* Returns a formatted string describing this Class. The string has
2751
* the following format:
2752
* <i>modifier1 modifier2 ... kind name&lt;typeparam1, typeparam2, ...&gt;</i>.
2753
* kind is one of <code>class</code>, <code>enum</code>, <code>interface</code>,
2754
* <code>&#64;interface</code>, or
2755
* the empty string for primitive types. The type parameter list is
2756
* omitted if there are no type parameters.
2757
/*[IF Sidecar19-SE]
2758
* For array classes, the string has the following format instead:
2759
* <i>name&lt;typeparam1, typeparam2, ...&gt;</i> followed by a number of
2760
* <code>[]</code> pairs, one pair for each dimension of the array.
2761
/*[ENDIF]
2762
*
2763
* @return a formatted string describing this class
2764
* @since 1.8
2765
*/
2766
public String toGenericString() {
2767
if (isPrimitive()) return getName();
2768
2769
StringBuilder result = new StringBuilder();
2770
int modifiers = getModifiers();
2771
2772
// Checks for isInterface, isAnnotation and isEnum have been inlined
2773
// in order to avoid multiple calls to isArray and getModifiers
2774
boolean isArray = isArray();
2775
boolean isInterface = !isArray && (0 != (modifiers & Modifier.INTERFACE));
2776
2777
// Get kind of type before modifying the modifiers
2778
String kindOfType;
2779
if ((!isArray) && ((modifiers & ANNOTATION) != 0)) {
2780
kindOfType = "@interface "; //$NON-NLS-1$
2781
} else if (isInterface) {
2782
kindOfType = "interface "; //$NON-NLS-1$
2783
} else if ((!isArray) && ((modifiers & ENUM) != 0) && (getSuperclass() == Enum.class)) {
2784
kindOfType = "enum "; //$NON-NLS-1$
2785
/*[IF JAVA_SPEC_VERSION >= 14]*/
2786
} else if (isRecord()) {
2787
kindOfType = "record "; //$NON-NLS-1$
2788
/*[ENDIF] JAVA_SPEC_VERSION >= 14 */
2789
} else {
2790
kindOfType = "class "; //$NON-NLS-1$
2791
}
2792
2793
// Remove "interface" from modifiers (is included as kind of type)
2794
if (isInterface) {
2795
modifiers -= Modifier.INTERFACE;
2796
}
2797
2798
// Build generic string
2799
/*[IF Sidecar19-SE]*/
2800
if (isArray) {
2801
int depth = 0;
2802
Class inner = this;
2803
Class component = this;
2804
do {
2805
inner = inner.getComponentType();
2806
if (inner != null) {
2807
component = inner;
2808
depth += 1;
2809
}
2810
} while (inner != null);
2811
result.append(component.getName());
2812
component.appendTypeParameters(result);
2813
for (int i = 0; i < depth; i++) {
2814
result.append('[').append(']');
2815
}
2816
return result.toString();
2817
}
2818
/*[ENDIF]*/
2819
result.append(Modifier.toString(modifiers));
2820
if (result.length() > 0) {
2821
result.append(' ');
2822
}
2823
result.append(kindOfType);
2824
result.append(getName());
2825
2826
appendTypeParameters(result);
2827
return result.toString();
2828
}
2829
2830
// Add type parameters to stringbuilder if present
2831
private void appendTypeParameters(StringBuilder nameBuilder) {
2832
TypeVariable<?>[] typeVariables = getTypeParameters();
2833
if (0 != typeVariables.length) {
2834
nameBuilder.append('<');
2835
boolean comma = false;
2836
for (TypeVariable<?> t : typeVariables) {
2837
if (comma) nameBuilder.append(',');
2838
nameBuilder.append(t);
2839
comma = true;
2840
/*[IF JAVA_SPEC_VERSION >= 12]*/
2841
Type[] types = t.getBounds();
2842
if (types.length == 1 && types[0].equals(Object.class)) {
2843
// skip in case the only bound is java.lang.Object
2844
} else {
2845
String prefix = " extends "; //$NON-NLS-1$
2846
for (Type type : types) {
2847
nameBuilder.append(prefix).append(type.getTypeName());
2848
prefix = " & "; //$NON-NLS-1$
2849
}
2850
}
2851
/*[ENDIF] JAVA_SPEC_VERSION >= 12 */
2852
}
2853
nameBuilder.append('>');
2854
}
2855
}
2856
2857
/**
2858
* Returns the Package of which this class is a member.
2859
* A class has a Package iff it was loaded from a SecureClassLoader.
2860
*
2861
* @return Package the Package of which this class is a member
2862
* or null in the case of primitive or array types
2863
*/
2864
public Package getPackage() {
2865
if (isArray() || isPrimitive()) {
2866
return null;
2867
}
2868
String packageName = getPackageName();
2869
if (null == packageName) {
2870
return null;
2871
} else {
2872
/*[IF Sidecar19-SE]*/
2873
if (this.classLoader == ClassLoader.bootstrapClassLoader) {
2874
return jdk.internal.loader.BootLoader.getDefinedPackage(packageName);
2875
} else {
2876
return getClassLoaderImpl().getDefinedPackage(packageName);
2877
}
2878
/*[ELSE]
2879
return getClassLoaderImpl().getPackage(packageName);
2880
/*[ENDIF]*/
2881
}
2882
}
2883
2884
static Class<?> getPrimitiveClass(String name) {
2885
if (name.equals("float")) //$NON-NLS-1$
2886
return new float[0].getClass().getComponentType();
2887
if (name.equals("double")) //$NON-NLS-1$
2888
return new double[0].getClass().getComponentType();
2889
if (name.equals("int")) //$NON-NLS-1$
2890
return new int[0].getClass().getComponentType();
2891
if (name.equals("long")) //$NON-NLS-1$
2892
return new long[0].getClass().getComponentType();
2893
if (name.equals("char")) //$NON-NLS-1$
2894
return new char[0].getClass().getComponentType();
2895
if (name.equals("byte")) //$NON-NLS-1$
2896
return new byte[0].getClass().getComponentType();
2897
if (name.equals("boolean")) //$NON-NLS-1$
2898
return new boolean[0].getClass().getComponentType();
2899
if (name.equals("short")) //$NON-NLS-1$
2900
return new short[0].getClass().getComponentType();
2901
if (name.equals("void")) { //$NON-NLS-1$
2902
try {
2903
java.lang.reflect.Method method = Runnable.class.getMethod("run", EmptyParameters); //$NON-NLS-1$
2904
return method.getReturnType();
2905
} catch (Exception e) {
2906
com.ibm.oti.vm.VM.dumpString("Cannot initialize Void.TYPE\n"); //$NON-NLS-1$
2907
}
2908
}
2909
throw new Error("Unknown primitive type: " + name); //$NON-NLS-1$
2910
}
2911
2912
/**
2913
* Returns the assertion status for this class.
2914
* Assertion is enabled/disabled based on
2915
* classloader default, package or class default at runtime
2916
*
2917
* @since 1.4
2918
*
2919
* @return the assertion status for this class
2920
*/
2921
public boolean desiredAssertionStatus() {
2922
ClassLoader cldr = getClassLoaderImpl();
2923
if (cldr != null) {
2924
/*[PR CMVC 80253] package assertion status not checked */
2925
return cldr.getClassAssertionStatus(getName());
2926
}
2927
return false;
2928
}
2929
2930
/**
2931
* Answer the class at depth.
2932
*
2933
* Notes:
2934
* 1) This method operates on the defining classes of methods on stack.
2935
* NOT the classes of receivers.
2936
*
2937
* 2) The item at index zero describes the caller of this method.
2938
*
2939
* @param depth
2940
* @return the class at the given depth
2941
*/
2942
@CallerSensitive
2943
static final native Class<?> getStackClass(int depth);
2944
2945
/**
2946
* Walk the stack and answer an array containing the maxDepth
2947
* most recent classes on the stack of the calling thread.
2948
*
2949
* Starting with the caller of the caller of getStackClasses(), return an
2950
* array of not more than maxDepth Classes representing the classes of
2951
* running methods on the stack (including native methods). Frames
2952
* representing the VM implementation of java.lang.reflect are not included
2953
* in the list. If stopAtPrivileged is true, the walk will terminate at any
2954
* frame running one of the following methods:
2955
*
2956
* <code><ul>
2957
* <li>java/security/AccessController.doPrivileged(Ljava/security/PrivilegedAction;)Ljava/lang/Object;</li>
2958
* <li>java/security/AccessController.doPrivileged(Ljava/security/PrivilegedExceptionAction;)Ljava/lang/Object;</li>
2959
* <li>java/security/AccessController.doPrivileged(Ljava/security/PrivilegedAction;Ljava/security/AccessControlContext;)Ljava/lang/Object;</li>
2960
* <li>java/security/AccessController.doPrivileged(Ljava/security/PrivilegedExceptionAction;Ljava/security/AccessControlContext;)Ljava/lang/Object;</li>
2961
* </ul></code>
2962
*
2963
* If one of the doPrivileged methods is found, the walk terminate and that frame is NOT included in the returned array.
2964
*
2965
* Notes: <ul>
2966
* <li> This method operates on the defining classes of methods on stack.
2967
* NOT the classes of receivers. </li>
2968
*
2969
* <li> The item at index zero in the result array describes the caller of
2970
* the caller of this method. </li>
2971
*</ul>
2972
*
2973
* @param maxDepth maximum depth to walk the stack, -1 for the entire stack
2974
* @param stopAtPrivileged stop at privileged classes
2975
* @return the array of the most recent classes on the stack
2976
*/
2977
@CallerSensitive
2978
static final native Class<?>[] getStackClasses(int maxDepth, boolean stopAtPrivileged);
2979
2980
2981
/**
2982
* Called from JVM_ClassDepth.
2983
* Answers the index in the stack of the first method which
2984
* is contained in a class called <code>name</code>. If no
2985
* methods from this class are in the stack, return -1.
2986
*
2987
* @param name String
2988
* the name of the class to look for.
2989
* @return int
2990
* the depth in the stack of a the first
2991
* method found.
2992
*/
2993
@CallerSensitive
2994
static int classDepth (String name) {
2995
Class<?>[] classes = getStackClasses(-1, false);
2996
for (int i=1; i<classes.length; i++)
2997
if (classes[i].getName().equals(name))
2998
return i - 1;
2999
return -1;
3000
}
3001
3002
/**
3003
* Called from JVM_ClassLoaderDepth.
3004
* Answers the index in the stack of the first class
3005
* whose class loader is not a system class loader.
3006
*
3007
* @return the frame index of the first method whose class was loaded by a non-system class loader.
3008
*/
3009
@CallerSensitive
3010
static int classLoaderDepth() {
3011
// Now, check if there are any non-system class loaders in
3012
// the stack up to the first privileged method (or the end
3013
// of the stack.
3014
Class<?>[] classes = getStackClasses(-1, true);
3015
for (int i=1; i<classes.length; i++) {
3016
ClassLoader cl = classes[i].getClassLoaderImpl();
3017
if (!cl.isASystemClassLoader()) return i - 1;
3018
}
3019
return -1;
3020
}
3021
3022
/**
3023
* Called from JVM_CurrentClassLoader.
3024
* Answers the class loader of the first class in the stack
3025
* whose class loader is not a system class loader.
3026
*
3027
* @return the most recent non-system class loader.
3028
*/
3029
@CallerSensitive
3030
static ClassLoader currentClassLoader() {
3031
// Now, check if there are any non-system class loaders in
3032
// the stack up to the first privileged method (or the end
3033
// of the stack.
3034
Class<?>[] classes = getStackClasses(-1, true);
3035
for (int i=1; i<classes.length; i++) {
3036
ClassLoader cl = classes[i].getClassLoaderImpl();
3037
if (!cl.isASystemClassLoader()) return cl;
3038
}
3039
return null;
3040
}
3041
3042
/**
3043
* Called from JVM_CurrentLoadedClass.
3044
* Answers the first class in the stack which was loaded
3045
* by a class loader which is not a system class loader.
3046
*
3047
* @return the most recent class loaded by a non-system class loader.
3048
*/
3049
@CallerSensitive
3050
static Class<?> currentLoadedClass() {
3051
// Now, check if there are any non-system class loaders in
3052
// the stack up to the first privileged method (or the end
3053
// of the stack.
3054
Class<?>[] classes = getStackClasses(-1, true);
3055
for (int i=1; i<classes.length; i++) {
3056
ClassLoader cl = classes[i].getClassLoaderImpl();
3057
if (!cl.isASystemClassLoader()) return classes[i];
3058
}
3059
return null;
3060
}
3061
3062
/**
3063
* Return the specified Annotation for this Class. Inherited Annotations
3064
* are searched.
3065
*
3066
* @param annotation the Annotation type
3067
* @return the specified Annotation or null
3068
*
3069
* @since 1.5
3070
*/
3071
public <A extends Annotation> A getAnnotation(Class<A> annotation) {
3072
if (annotation == null) throw new NullPointerException();
3073
LinkedHashMap<Class<? extends Annotation>, Annotation> map = getAnnotationCache().annotationMap;
3074
if (map != null) {
3075
return (A)map.get(annotation);
3076
}
3077
return null;
3078
}
3079
3080
/**
3081
* Return the directly declared Annotations for this Class, including the Annotations
3082
* inherited from superclasses.
3083
* If an annotation type has been included before, then next occurrences will not be included.
3084
*
3085
* Repeated annotations are not included since they will be stored in their container annotation.
3086
* But container annotations are included. (If a container annotation is repeatable and it is repeated,
3087
* then these container annotations' container annotation is included. )
3088
* @return an array of Annotation
3089
*
3090
* @since 1.5
3091
*/
3092
public Annotation[] getAnnotations() {
3093
LinkedHashMap<Class<? extends Annotation>, Annotation> map = getAnnotationCache().annotationMap;
3094
if (map != null) {
3095
Collection<Annotation> annotations = map.values();
3096
return annotations.toArray(new Annotation[annotations.size()]);
3097
}
3098
return EMPTY_ANNOTATION_ARRAY;
3099
}
3100
3101
/**
3102
* Looks through directly declared annotations for this class, not including Annotations inherited from superclasses.
3103
*
3104
* @param annotation the Annotation to search for
3105
* @return directly declared annotation of specified annotation type.
3106
*
3107
* @since 1.8
3108
*/
3109
public <A extends Annotation> A getDeclaredAnnotation(Class<A> annotation) {
3110
if (annotation == null) throw new NullPointerException();
3111
LinkedHashMap<Class<? extends Annotation>, Annotation> map = getAnnotationCache().directAnnotationMap;
3112
if (map != null) {
3113
return (A)map.get(annotation);
3114
}
3115
return null;
3116
}
3117
3118
/**
3119
* Return the annotated types for the implemented interfaces.
3120
* @return array, possibly empty, of AnnotatedTypes
3121
*/
3122
public AnnotatedType[] getAnnotatedInterfaces() {
3123
return TypeAnnotationParser.buildAnnotatedInterfaces(this);
3124
}
3125
3126
/**
3127
* Return the annotated superclass of this class.
3128
* @return null if this class is Object, an interface, a primitive type, or an array type. Otherwise return (possibly empty) AnnotatedType.
3129
*/
3130
public AnnotatedType getAnnotatedSuperclass() {
3131
if (this.equals(Object.class) || this.isInterface() || this.isPrimitive() || this.isArray()) {
3132
return null;
3133
}
3134
return TypeAnnotationParser.buildAnnotatedSupertype(this);
3135
}
3136
3137
/**
3138
* Answers the type name of the class which the receiver represents.
3139
*
3140
* @return the fully qualified type name, with brackets if an array class
3141
*
3142
* @since 1.8
3143
*/
3144
@Override
3145
public String getTypeName() {
3146
if (isArray()) {
3147
StringBuilder nameBuffer = new StringBuilder("[]"); //$NON-NLS-1$
3148
Class<?> componentType = getComponentType();
3149
while (componentType.isArray()) {
3150
nameBuffer.append("[]"); //$NON-NLS-1$
3151
componentType = componentType.getComponentType();
3152
}
3153
nameBuffer.insert(0, componentType.getName());
3154
return nameBuffer.toString();
3155
} else {
3156
return getName();
3157
}
3158
}
3159
3160
/**
3161
* Returns the annotations only for this Class, not including Annotations inherited from superclasses.
3162
* It includes all the directly declared annotations.
3163
* Repeated annotations are not included but their container annotation does.
3164
*
3165
* @return an array of declared annotations
3166
*
3167
*
3168
* @since 1.5
3169
*/
3170
public Annotation[] getDeclaredAnnotations() {
3171
LinkedHashMap<Class<? extends Annotation>, Annotation> map = getAnnotationCache().directAnnotationMap;
3172
if (map != null) {
3173
Collection<Annotation> annotations = map.values();
3174
return annotations.toArray(new Annotation[annotations.size()]);
3175
}
3176
return EMPTY_ANNOTATION_ARRAY;
3177
}
3178
3179
/**
3180
* Gets the specified type annotations of this class.
3181
* <br>
3182
* Terms used for annotations :<br><br>
3183
* Repeatable Annotation :
3184
* <p>An annotation which can be used more than once for the same class declaration.
3185
* Repeatable annotations are annotated with Repeatable annotation which tells the
3186
* container annotation for this repeatable annotation.</p>
3187
* Example
3188
* <pre><code>
3189
* {@literal @}interface ContainerAnnotation {RepeatableAnn[] value();}
3190
* {@literal @}Repeatable(ContainerAnnotation.class)
3191
* </code></pre>
3192
* Container Annotation:
3193
* <p>Container annotation stores the repeated annotations in its array-valued element.
3194
* Using repeatable annotations more than once makes them stored in their container annotation.
3195
* In this case, container annotation is visible directly on class declaration, but not the repeated annotations.</p>
3196
* Repeated Annotation:
3197
* <p>A repeatable annotation which is used more than once for the same class.</p>
3198
* Directly Declared Annotation :
3199
* <p>All non repeatable annotations are directly declared annotations.
3200
* As for repeatable annotations, they can be directly declared annotation if and only if they are used once.
3201
* Repeated annotations are not directly declared in class declaration, but their container annotation does.</p>
3202
*
3203
* -------------------------------------------------------------------------------------------------------
3204
*
3205
* <p>If the specified type is not repeatable annotation, then returned array size will be 0 or 1.
3206
* 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>
3207
*
3208
* It does not search through super classes.
3209
*
3210
* @param annotationClass the annotation type to search for
3211
* @return array of declared annotations in the specified annotation type
3212
*
3213
* @since 1.8
3214
*/
3215
public <A extends Annotation> A[] getDeclaredAnnotationsByType(Class<A> annotationClass) {
3216
ArrayList<A> annotationsList = internalGetDeclaredAnnotationsByType(annotationClass);
3217
return annotationsList.toArray((A[])Array.newInstance(annotationClass, annotationsList.size()));
3218
}
3219
3220
private <A extends Annotation> ArrayList<A> internalGetDeclaredAnnotationsByType(Class<A> annotationClass) {
3221
AnnotationCache currentAnnotationCache = getAnnotationCache();
3222
ArrayList<A> annotationsList = new ArrayList<>();
3223
3224
LinkedHashMap<Class<? extends Annotation>, Annotation> map = currentAnnotationCache.directAnnotationMap;
3225
if (map != null) {
3226
Repeatable repeatable = annotationClass.getDeclaredAnnotation(Repeatable.class);
3227
if (repeatable == null) {
3228
A annotation = (A)map.get(annotationClass);
3229
if (annotation != null) {
3230
annotationsList.add(annotation);
3231
}
3232
} else {
3233
Class<? extends Annotation> containerType = repeatable.value();
3234
// if the annotation and its container are both present, the order must be maintained
3235
for (Map.Entry<Class<? extends Annotation>, Annotation> entry : map.entrySet()) {
3236
Class<? extends Annotation> annotationType = entry.getKey();
3237
if (annotationType == annotationClass) {
3238
annotationsList.add((A)entry.getValue());
3239
} else if (annotationType == containerType) {
3240
A[] containedAnnotations = (A[])getAnnotationsArrayFromValue(entry.getValue(), containerType, annotationClass);
3241
if (containedAnnotations != null) {
3242
annotationsList.addAll(Arrays.asList(containedAnnotations));
3243
}
3244
}
3245
}
3246
}
3247
}
3248
3249
return annotationsList;
3250
}
3251
3252
/**
3253
* Gets the specified type annotations of this class.
3254
* If the specified type is not repeatable annotation, then returned array size will be 0 or 1.
3255
* If specified type is repeatable annotation, then all the annotations of that type will be returned. Array size might be 0, 1 or more.
3256
*
3257
* It searches through superclasses until it finds the inherited specified annotationClass.
3258
*
3259
* @param annotationClass the annotation type to search for
3260
* @return array of declared annotations in the specified annotation type
3261
*
3262
* @since 1.8
3263
*/
3264
public <A extends Annotation> A[] getAnnotationsByType(Class<A> annotationClass)
3265
{
3266
ArrayList<A> annotationsList = internalGetDeclaredAnnotationsByType(annotationClass);
3267
3268
if (annotationClass.isInheritedAnnotationType()) {
3269
Class<?> sc = this;
3270
while (0 == annotationsList.size()) {
3271
sc = sc.getSuperclass();
3272
if (null == sc) break;
3273
ArrayList<A> superAnnotations = sc.internalGetDeclaredAnnotationsByType(annotationClass);
3274
if (superAnnotations != null) {
3275
annotationsList.addAll(superAnnotations);
3276
}
3277
}
3278
}
3279
return annotationsList.toArray((A[])Array.newInstance(annotationClass, annotationsList.size()));
3280
}
3281
3282
AnnotationVars getAnnotationVars() {
3283
AnnotationVars tempAnnotationVars = annotationVars;
3284
if (tempAnnotationVars == null) {
3285
if (annotationVarsOffset == -1) {
3286
try {
3287
Field annotationVarsField = Class.class.getDeclaredField("annotationVars"); //$NON-NLS-1$
3288
annotationVarsOffset = getUnsafe().objectFieldOffset(annotationVarsField);
3289
} catch (NoSuchFieldException e) {
3290
throw newInternalError(e);
3291
}
3292
}
3293
tempAnnotationVars = new AnnotationVars();
3294
synchronized (this) {
3295
if (annotationVars == null) {
3296
// Lazy initialization of a non-volatile field. Ensure the Object is initialized
3297
// and flushed to memory before assigning to the annotationVars field.
3298
/*[IF Sidecar19-SE]
3299
getUnsafe().putObjectRelease(this, annotationVarsOffset, tempAnnotationVars);
3300
/*[ELSE]*/
3301
getUnsafe().putOrderedObject(this, annotationVarsOffset, tempAnnotationVars);
3302
/*[ENDIF]*/
3303
} else {
3304
tempAnnotationVars = annotationVars;
3305
}
3306
}
3307
}
3308
return tempAnnotationVars;
3309
}
3310
3311
private MethodHandle getValueMethod(final Class<? extends Annotation> containedType) {
3312
final AnnotationVars localAnnotationVars = getAnnotationVars();
3313
MethodHandle valueMethod = localAnnotationVars.valueMethod;
3314
if (valueMethod == null) {
3315
final MethodType methodType = MethodType.methodType(Array.newInstance(containedType, 0).getClass());
3316
valueMethod = AccessController.doPrivileged(new PrivilegedAction<MethodHandle>() {
3317
@Override
3318
public MethodHandle run() {
3319
try {
3320
MethodHandles.Lookup localImplLookup = implLookup;
3321
if (localImplLookup == null) {
3322
Field privilegedLookupField = MethodHandles.Lookup.class.getDeclaredField("IMPL_LOOKUP"); //$NON-NLS-1$
3323
privilegedLookupField.setAccessible(true);
3324
localImplLookup = (MethodHandles.Lookup)privilegedLookupField.get(MethodHandles.Lookup.class);
3325
Field implLookupField = Class.class.getDeclaredField("implLookup"); //$NON-NLS-1$
3326
long implLookupOffset = getUnsafe().staticFieldOffset(implLookupField);
3327
// Lazy initialization of a non-volatile field. Ensure the Object is initialized
3328
// and flushed to memory before assigning to the implLookup field.
3329
/*[IF Sidecar19-SE]
3330
getUnsafe().putObjectRelease(Class.class, implLookupOffset, localImplLookup);
3331
/*[ELSE]*/
3332
getUnsafe().putOrderedObject(Class.class, implLookupOffset, localImplLookup);
3333
/*[ENDIF]*/
3334
}
3335
MethodHandle handle = localImplLookup.findVirtual(Class.this, "value", methodType); //$NON-NLS-1$
3336
if (AnnotationVars.valueMethodOffset == -1) {
3337
Field valueMethodField = AnnotationVars.class.getDeclaredField("valueMethod"); //$NON-NLS-1$
3338
AnnotationVars.valueMethodOffset = getUnsafe().objectFieldOffset(valueMethodField);
3339
}
3340
// Lazy initialization of a non-volatile field. Ensure the Object is initialized
3341
// and flushed to memory before assigning to the valueMethod field.
3342
/*[IF Sidecar19-SE]
3343
getUnsafe().putObjectRelease(localAnnotationVars, AnnotationVars.valueMethodOffset, handle);
3344
/*[ELSE]*/
3345
getUnsafe().putOrderedObject(localAnnotationVars, AnnotationVars.valueMethodOffset, handle);
3346
/*[ENDIF]*/
3347
return handle;
3348
} catch (NoSuchMethodException e) {
3349
return null;
3350
} catch (IllegalAccessException | NoSuchFieldException e) {
3351
throw newInternalError(e);
3352
}
3353
}
3354
});
3355
}
3356
return valueMethod;
3357
}
3358
3359
private MetadataCache getMetadataCache() {
3360
if (metadataCache == null) {
3361
/*[IF JAVA_SPEC_VERSION >= 11]
3362
metadataCacheOffset = getUnsafe().objectFieldOffset(Class.class, "metadataCache"); //$NON-NLS-1$
3363
/*[ELSE] JAVA_SPEC_VERSION >= 11 */
3364
try {
3365
Field field = Class.class.getDeclaredFieldInternal("metadataCache", false); //$NON-NLS-1$
3366
metadataCacheOffset = getUnsafe().objectFieldOffset(field);
3367
} catch (NoSuchFieldException e) {
3368
throw newInternalError(e);
3369
}
3370
/*[ENDIF] JAVA_SPEC_VERSION >= 11 */
3371
writeFieldValue(metadataCacheOffset, new MetadataCache());
3372
}
3373
return metadataCache;
3374
}
3375
3376
private String cacheSimpleName(String simpleName) {
3377
MetadataCache cache = getMetadataCache();
3378
3379
if (cache.cachedSimpleName == null || cache.cachedSimpleName.get() == null) {
3380
MetadataCache.cachedSimpleNameOffset = getFieldOffset(
3381
MetadataCache.class, "cachedSimpleName", MetadataCache.cachedSimpleNameOffset); //$NON-NLS-1$
3382
3383
writeFieldValue(cache, MetadataCache.cachedSimpleNameOffset, new SoftReference<>(simpleName));
3384
}
3385
3386
return simpleName;
3387
}
3388
3389
private String cacheCanonicalName(String canonicalName) {
3390
MetadataCache cache = getMetadataCache();
3391
3392
if (cache.cachedCanonicalName == null || cache.cachedCanonicalName.get() == null) {
3393
MetadataCache.cachedCanonicalNameOffset = getFieldOffset(
3394
MetadataCache.class, "cachedCanonicalName", MetadataCache.cachedCanonicalNameOffset); //$NON-NLS-1$
3395
3396
writeFieldValue(cache, MetadataCache.cachedCanonicalNameOffset, new SoftReference<>(canonicalName));
3397
}
3398
3399
return canonicalName;
3400
}
3401
3402
/**
3403
* This helper method atomically writes the given {@code fieldValue} to the
3404
* field specified by the {@code fieldOffset} of the {@code target} object
3405
*/
3406
private static void writeFieldValue(Object target, long fieldOffset, Object fieldValue) {
3407
/*[IF JAVA_SPEC_VERSION >= 11]
3408
getUnsafe().putObjectRelease(target, fieldOffset, fieldValue);
3409
/*[ELSE] JAVA_SPEC_VERSION >= 11 */
3410
getUnsafe().putOrderedObject(target, fieldOffset, fieldValue);
3411
/*[ENDIF] JAVA_SPEC_VERSION >= 11 */
3412
}
3413
3414
private void writeFieldValue(long fieldOffset, Object fieldValue) {
3415
writeFieldValue(this, fieldOffset, fieldValue);
3416
}
3417
3418
private static long getFieldOffset(Class<?> hostClass, String fieldName, long initialOffset) {
3419
if (initialOffset == -1) {
3420
try {
3421
Field field = hostClass.getDeclaredField(fieldName);
3422
return getUnsafe().objectFieldOffset(field);
3423
} catch (NoSuchFieldException e) {
3424
throw newInternalError(e);
3425
}
3426
}
3427
return initialOffset;
3428
}
3429
3430
private static long getFieldOffset(String fieldName) {
3431
return getFieldOffset(Class.class, fieldName, -1);
3432
}
3433
3434
/**
3435
* Gets the array of containedType from the value() method.
3436
*
3437
* @param container the annotation which is the container of the repeated annotation
3438
* @param containerType the annotationType() of the container. This implements the value() method.
3439
* @param containedType the annotationType() stored in the container
3440
* @return Annotation array if the given annotation has a value() method which returns an array of the containedType. Otherwise, return null.
3441
*/
3442
private static Annotation[] getAnnotationsArrayFromValue(Annotation container, Class<? extends Annotation> containerType, Class<? extends Annotation> containedType) {
3443
try {
3444
MethodHandle valueMethod = containerType.getValueMethod(containedType);
3445
if (valueMethod != null) {
3446
Object children = valueMethod.invoke(container);
3447
/*
3448
* Check whether value is Annotation array or not
3449
*/
3450
if (children instanceof Annotation[]) {
3451
return (Annotation[])children;
3452
}
3453
}
3454
return null;
3455
} catch (Error | RuntimeException e) {
3456
throw e;
3457
} catch (Throwable t) {
3458
throw new RuntimeException(t);
3459
}
3460
}
3461
3462
private boolean isInheritedAnnotationType() {
3463
LinkedHashMap<Class<? extends Annotation>, Annotation> map = getAnnotationCache().directAnnotationMap;
3464
if (map != null) {
3465
return map.get(Inherited.class) != null;
3466
}
3467
return false;
3468
}
3469
3470
private LinkedHashMap<Class<? extends Annotation>, Annotation> buildAnnotations(LinkedHashMap<Class<? extends Annotation>, Annotation> directAnnotationsMap) {
3471
Class<?> superClass = getSuperclass();
3472
if (superClass == null) {
3473
return directAnnotationsMap;
3474
}
3475
LinkedHashMap<Class<? extends Annotation>, Annotation> superAnnotations = superClass.getAnnotationCache().annotationMap;
3476
LinkedHashMap<Class<? extends Annotation>, Annotation> annotationsMap = null;
3477
if (superAnnotations != null) {
3478
for (Map.Entry<Class<? extends Annotation>, Annotation> entry : superAnnotations.entrySet()) {
3479
Class<? extends Annotation> annotationType = entry.getKey();
3480
// if the annotation is Inherited store the annotation
3481
if (annotationType.isInheritedAnnotationType()) {
3482
if (annotationsMap == null) {
3483
annotationsMap = new LinkedHashMap<>((superAnnotations.size() + (directAnnotationsMap != null ? directAnnotationsMap.size() : 0)) * 4 / 3);
3484
}
3485
annotationsMap.put(annotationType, entry.getValue());
3486
}
3487
}
3488
}
3489
if (annotationsMap == null) {
3490
return directAnnotationsMap;
3491
}
3492
if (directAnnotationsMap != null) {
3493
annotationsMap.putAll(directAnnotationsMap);
3494
}
3495
return annotationsMap;
3496
}
3497
3498
/**
3499
* Gets all the direct annotations.
3500
* It does not include repeated annotations for this class, it includes their container annotation(s).
3501
*
3502
* @return array of all the direct annotations.
3503
*/
3504
private AnnotationCache getAnnotationCache() {
3505
AnnotationCache annotationCacheResult = annotationCache;
3506
3507
if (annotationCacheResult == null) {
3508
byte[] annotationsData = getDeclaredAnnotationsData();
3509
if (annotationsData == null) {
3510
annotationCacheResult = new AnnotationCache(null, buildAnnotations(null));
3511
} else {
3512
long offset = Unsafe.ARRAY_BYTE_BASE_OFFSET + ((annotationsData.length * Unsafe.ARRAY_BYTE_INDEX_SCALE) - VM.FJ9OBJECT_SIZE);
3513
long ramCPAddr = 0;
3514
if (VM.FJ9OBJECT_SIZE == 4) {
3515
/* Compressed object refs */
3516
ramCPAddr = Integer.toUnsignedLong(unsafe.getInt(annotationsData, offset));
3517
} else {
3518
ramCPAddr = unsafe.getLong(annotationsData, offset);
3519
}
3520
Object internalCP = VM.getVMLangAccess().createInternalConstantPool(ramCPAddr);
3521
3522
Annotation[] directAnnotations = sun.reflect.annotation.AnnotationParser.toArray(
3523
sun.reflect.annotation.AnnotationParser.parseAnnotations(
3524
annotationsData,
3525
getConstantPool(internalCP),
3526
this));
3527
3528
LinkedHashMap<Class<? extends Annotation>, Annotation> directAnnotationsMap = new LinkedHashMap<>(directAnnotations.length * 4 / 3);
3529
for (Annotation annotation : directAnnotations) {
3530
Class<? extends Annotation> annotationType = annotation.annotationType();
3531
directAnnotationsMap.put(annotationType, annotation);
3532
}
3533
annotationCacheResult = new AnnotationCache(directAnnotationsMap, buildAnnotations(directAnnotationsMap));
3534
}
3535
3536
// Don't bother with synchronization. Since it is just a cache, it doesn't matter if it gets overwritten
3537
// because multiple threads create the cache at the same time
3538
long localAnnotationCacheOffset = annotationCacheOffset;
3539
if (localAnnotationCacheOffset == -1) {
3540
try {
3541
Field annotationCacheField = Class.class.getDeclaredField("annotationCache"); //$NON-NLS-1$
3542
localAnnotationCacheOffset = getUnsafe().objectFieldOffset(annotationCacheField);
3543
annotationCacheOffset = localAnnotationCacheOffset;
3544
} catch (NoSuchFieldException e) {
3545
throw newInternalError(e);
3546
}
3547
}
3548
// Lazy initialization of a non-volatile field. Ensure the Object is initialized
3549
// and flushed to memory before assigning to the annotationCache field.
3550
/*[IF Sidecar19-SE]*/
3551
getUnsafe().putObjectRelease(this, localAnnotationCacheOffset, annotationCacheResult);
3552
/*[ELSE]*/
3553
getUnsafe().putOrderedObject(this, localAnnotationCacheOffset, annotationCacheResult);
3554
/*[ENDIF]*/
3555
}
3556
return annotationCacheResult;
3557
}
3558
3559
3560
private native byte[] getDeclaredAnnotationsData();
3561
3562
/**
3563
* Answer if this class is an Annotation.
3564
*
3565
* @return true if this class is an Annotation
3566
*
3567
* @since 1.5
3568
*/
3569
public boolean isAnnotation() {
3570
// This code has been inlined in toGenericString. toGenericString
3571
// must be modified to reflect any changes to this implementation.
3572
/*[PR CMVC 89373] Ensure Annotation subclass is not annotation */
3573
return !isArray() && (getModifiersImpl() & ANNOTATION) != 0;
3574
}
3575
3576
/**
3577
* Answer if the specified Annotation exists for this Class. Inherited
3578
* Annotations are searched.
3579
*
3580
* @param annotation the Annotation type
3581
* @return true if the specified Annotation exists
3582
*
3583
* @since 1.5
3584
*/
3585
public boolean isAnnotationPresent(Class<? extends Annotation> annotation) {
3586
if (annotation == null) throw new NullPointerException();
3587
return getAnnotation(annotation) != null;
3588
}
3589
3590
/**
3591
* Cast this Class to a subclass of the specified Class.
3592
* @param <U> the type for casting to
3593
* @param cls the Class to cast to
3594
* @return this Class, cast to a subclass of the specified Class
3595
*
3596
* @throws ClassCastException if this Class is not the same or a subclass
3597
* of the specified Class
3598
*
3599
* @since 1.5
3600
*/
3601
public <U> Class<? extends U> asSubclass(Class<U> cls) {
3602
if (!cls.isAssignableFrom(this))
3603
throw new ClassCastException(this.toString());
3604
return (Class<? extends U>)this;
3605
}
3606
3607
/**
3608
* Cast the specified object to this Class.
3609
*
3610
* @param object the object to cast
3611
*
3612
* @return the specified object, cast to this Class
3613
*
3614
* @throws ClassCastException if the specified object cannot be cast
3615
* to this Class
3616
*
3617
* @since 1.5
3618
*/
3619
public T cast(Object object) {
3620
if ((object != null) && !this.isInstance(object)) {
3621
/*[MSG "K0336", "Cannot cast {0} to {1}"]*/
3622
throw new ClassCastException(com.ibm.oti.util.Msg.getString("K0336", object.getClass().getName(), getName())); //$NON-NLS-1$
3623
}
3624
return (T)object;
3625
}
3626
3627
/**
3628
* Answer if this Class is an enum.
3629
*
3630
* @return true if this Class is an enum
3631
*
3632
* @since 1.5
3633
*/
3634
public boolean isEnum() {
3635
// This code has been inlined in toGenericString. toGenericString
3636
// must be modified to reflect any changes to this implementation.
3637
/*[PR CMVC 89071] Ensure class with enum access flag (modifier) !isEnum() */
3638
return !isArray() && (getModifiersImpl() & ENUM) != 0 &&
3639
getSuperclass() == Enum.class;
3640
}
3641
3642
private EnumVars<T> getEnumVars() {
3643
EnumVars<T> tempEnumVars = enumVars;
3644
if (tempEnumVars == null) {
3645
long localEnumVarsOffset = enumVarsOffset;
3646
if (localEnumVarsOffset == -1) {
3647
Field enumVarsField;
3648
try {
3649
enumVarsField = Class.class.getDeclaredField("enumVars"); //$NON-NLS-1$
3650
localEnumVarsOffset = getUnsafe().objectFieldOffset(enumVarsField);
3651
enumVarsOffset = localEnumVarsOffset;
3652
} catch (NoSuchFieldException e) {
3653
throw newInternalError(e);
3654
}
3655
}
3656
// Don't bother with synchronization to determine if the field is already assigned. Since it is just a cache,
3657
// it doesn't matter if it gets overwritten because multiple threads create the cache at the same time
3658
tempEnumVars = new EnumVars<>();
3659
// Lazy initialization of a non-volatile field. Ensure the Object is initialized
3660
// and flushed to memory before assigning to the enumVars field.
3661
/*[IF Sidecar19-SE]
3662
getUnsafe().putObjectRelease(this, localEnumVarsOffset, tempEnumVars);
3663
/*[ELSE]*/
3664
getUnsafe().putOrderedObject(this, localEnumVarsOffset, tempEnumVars);
3665
/*[ENDIF]*/
3666
}
3667
return tempEnumVars;
3668
}
3669
3670
/**
3671
*
3672
* @return Map keyed by enum name, of uncloned and cached enum constants in this class
3673
*/
3674
Map<String, T> enumConstantDirectory() {
3675
EnumVars<T> localEnumVars = getEnumVars();
3676
Map<String, T> map = localEnumVars.cachedEnumConstantDirectory;
3677
if (null == map) {
3678
/*[PR CMVC 189091] Perf: EnumSet.allOf() is slow */
3679
T[] enums = getEnumConstantsShared();
3680
if (enums == null) {
3681
/*[PR CMVC 189257] Class#valueOf throws NPE instead of IllegalArgEx for nonEnum Classes */
3682
/*
3683
* Class#valueOf() is the caller of this method,
3684
* according to the spec it throws IllegalArgumentException if the class is not an Enum.
3685
*/
3686
/*[MSG "K0564", "{0} is not an Enum"]*/
3687
throw new IllegalArgumentException(com.ibm.oti.util.Msg.getString("K0564", getName())); //$NON-NLS-1$
3688
}
3689
map = new HashMap<>(enums.length * 4 / 3);
3690
for (int i = 0; i < enums.length; i++) {
3691
map.put(((Enum<?>) enums[i]).name(), enums[i]);
3692
}
3693
3694
if (EnumVars.enumDirOffset == -1) {
3695
try {
3696
Field enumDirField = EnumVars.class.getDeclaredField("cachedEnumConstantDirectory"); //$NON-NLS-1$
3697
EnumVars.enumDirOffset = getUnsafe().objectFieldOffset(enumDirField);
3698
} catch (NoSuchFieldException e) {
3699
throw newInternalError(e);
3700
}
3701
}
3702
// Lazy initialization of a non-volatile field. Ensure the Object is initialized
3703
// and flushed to memory before assigning to the cachedEnumConstantDirectory field.
3704
/*[IF Sidecar19-SE]
3705
getUnsafe().putObjectRelease(localEnumVars, EnumVars.enumDirOffset, map);
3706
/*[ELSE]*/
3707
getUnsafe().putOrderedObject(localEnumVars, EnumVars.enumDirOffset, map);
3708
/*[ENDIF]*/
3709
}
3710
return map;
3711
}
3712
3713
/**
3714
* Answer the shared uncloned array of enum constants for this Class. Returns null if
3715
* this class is not an enum.
3716
*
3717
* @return the array of enum constants, or null
3718
*
3719
* @since 1.5
3720
*/
3721
/*[PR CMVC 189091] Perf: EnumSet.allOf() is slow */
3722
T[] getEnumConstantsShared() {
3723
/*[PR CMVC 188840] Perf: Class.getEnumConstants() is slow */
3724
EnumVars<T> localEnumVars = getEnumVars();
3725
T[] enums = localEnumVars.cachedEnumConstants;
3726
if (null == enums && isEnum()) {
3727
try {
3728
final PrivilegedExceptionAction<Method> privilegedAction = new PrivilegedExceptionAction<Method>() {
3729
@Override
3730
public Method run() throws Exception {
3731
Method method = getMethod("values"); //$NON-NLS-1$
3732
/*[PR CMVC 83171] caused ClassCastException: <enum class> not an enum]*/
3733
// the enum class may not be visible
3734
method.setAccessible(true);
3735
return method;
3736
}
3737
};
3738
3739
Method values = AccessController.doPrivileged(privilegedAction);
3740
enums = (T[])values.invoke(this);
3741
3742
long localEnumConstantsOffset = EnumVars.enumConstantsOffset;
3743
if (localEnumConstantsOffset == -1) {
3744
try {
3745
Field enumConstantsField = EnumVars.class.getDeclaredField("cachedEnumConstants"); //$NON-NLS-1$
3746
localEnumConstantsOffset = getUnsafe().objectFieldOffset(enumConstantsField);
3747
EnumVars.enumConstantsOffset = localEnumConstantsOffset;
3748
} catch (NoSuchFieldException e) {
3749
throw newInternalError(e);
3750
}
3751
}
3752
// Lazy initialization of a non-volatile field. Ensure the Object is initialized
3753
// and flushed to memory before assigning to the cachedEnumConstants field.
3754
/*[IF Sidecar19-SE]
3755
getUnsafe().putObjectRelease(localEnumVars, localEnumConstantsOffset, enums);
3756
/*[ELSE]*/
3757
getUnsafe().putOrderedObject(localEnumVars, localEnumConstantsOffset, enums);
3758
/*[ENDIF]*/
3759
} catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException | PrivilegedActionException e) {
3760
enums = null;
3761
}
3762
}
3763
3764
return enums;
3765
}
3766
3767
/**
3768
* Answer the array of enum constants for this Class. Returns null if
3769
* this class is not an enum.
3770
*
3771
* @return the array of enum constants, or null
3772
*
3773
* @since 1.5
3774
*/
3775
public T[] getEnumConstants() {
3776
/*[PR CMVC 188840] Perf: Class.getEnumConstants() is slow */
3777
/*[PR CMVC 189091] Perf: EnumSet.allOf() is slow */
3778
/*[PR CMVC 192837] JAVA8:JCK: NPE at j.l.Class.getEnumConstants */
3779
T[] enumConstants = getEnumConstantsShared();
3780
if (null != enumConstants) {
3781
return enumConstants.clone();
3782
} else {
3783
return null;
3784
}
3785
}
3786
3787
/**
3788
* Answer if this Class is synthetic. A synthetic Class is created by
3789
* the compiler.
3790
*
3791
* @return true if this Class is synthetic.
3792
*
3793
* @since 1.5
3794
*/
3795
public boolean isSynthetic() {
3796
return !isArray() && (getModifiersImpl() & SYNTHETIC) != 0;
3797
}
3798
3799
private native String getGenericSignature();
3800
3801
private CoreReflectionFactory getFactory() {
3802
return CoreReflectionFactory.make(this, ClassScope.make(this));
3803
}
3804
3805
private ClassRepositoryHolder getClassRepositoryHolder() {
3806
ClassRepositoryHolder localClassRepositoryHolder = classRepoHolder;
3807
if (localClassRepositoryHolder == null) {
3808
synchronized(this) {
3809
localClassRepositoryHolder = classRepoHolder;
3810
if (localClassRepositoryHolder == null) {
3811
String signature = getGenericSignature();
3812
if (signature == null) {
3813
localClassRepositoryHolder = ClassRepositoryHolder.NullSingleton;
3814
} else {
3815
ClassRepository classRepo = ClassRepository.make(signature, getFactory());
3816
localClassRepositoryHolder = new ClassRepositoryHolder(classRepo);
3817
}
3818
classRepoHolder = localClassRepositoryHolder;
3819
}
3820
}
3821
}
3822
return localClassRepositoryHolder;
3823
}
3824
3825
3826
/**
3827
* Answers an array of TypeVariable for the generic parameters declared
3828
* on this Class.
3829
*
3830
* @return the TypeVariable[] for the generic parameters
3831
*
3832
* @since 1.5
3833
*/
3834
@SuppressWarnings("unchecked")
3835
public TypeVariable<Class<T>>[] getTypeParameters() {
3836
ClassRepositoryHolder holder = getClassRepositoryHolder();
3837
ClassRepository repository = holder.classRepository;
3838
if (repository == null) return new TypeVariable[0];
3839
return (TypeVariable<Class<T>>[])repository.getTypeParameters();
3840
}
3841
3842
/**
3843
* Answers an array of Type for the Class objects which match the
3844
* interfaces specified in the receiver classes <code>implements</code>
3845
* declaration.
3846
*
3847
* @return Type[]
3848
* the interfaces the receiver claims to implement.
3849
*
3850
* @since 1.5
3851
*/
3852
public Type[] getGenericInterfaces() {
3853
ClassRepositoryHolder holder = getClassRepositoryHolder();
3854
ClassRepository repository = holder.classRepository;
3855
if (repository == null) return getInterfaces();
3856
return repository.getSuperInterfaces();
3857
}
3858
3859
/**
3860
* Answers the Type for the Class which represents the receiver's
3861
* superclass. For classes which represent base types,
3862
* interfaces, and for java.lang.Object the method
3863
* answers null.
3864
*
3865
* @return the Type for the receiver's superclass.
3866
*
3867
* @since 1.5
3868
*/
3869
public Type getGenericSuperclass() {
3870
ClassRepositoryHolder holder = getClassRepositoryHolder();
3871
ClassRepository repository = holder.classRepository;
3872
if (repository == null) return getSuperclass();
3873
if (isInterface()) return null;
3874
return repository.getSuperclass();
3875
}
3876
3877
private native Object getEnclosingObject();
3878
3879
/**
3880
* If this Class is defined inside a constructor, return the Constructor.
3881
*
3882
* @return the enclosing Constructor or null
3883
* @throws SecurityException if declared member access or package access is not allowed
3884
*
3885
* @since 1.5
3886
*
3887
* @see #isAnonymousClass()
3888
* @see #isLocalClass()
3889
*/
3890
@CallerSensitive
3891
public Constructor<?> getEnclosingConstructor() throws SecurityException {
3892
Constructor<?> constructor = null;
3893
Object enclosing = getEnclosingObject();
3894
if (enclosing instanceof Constructor<?>) {
3895
constructor = (Constructor<?>) enclosing;
3896
@SuppressWarnings("removal")
3897
SecurityManager security = System.getSecurityManager();
3898
if (security != null) {
3899
ClassLoader callerClassLoader = ClassLoader.getStackClassLoader(1);
3900
constructor.getDeclaringClass().checkMemberAccess(security, callerClassLoader, Member.DECLARED);
3901
}
3902
/*[PR CMVC 201439] To remove CheckPackageAccess call from getEnclosingMethod of J9 */
3903
}
3904
return constructor;
3905
}
3906
3907
/**
3908
* If this Class is defined inside a method, return the Method.
3909
*
3910
* @return the enclosing Method or null
3911
* @throws SecurityException if declared member access or package access is not allowed
3912
*
3913
* @since 1.5
3914
*
3915
* @see #isAnonymousClass()
3916
* @see #isLocalClass()
3917
*/
3918
@CallerSensitive
3919
public Method getEnclosingMethod() throws SecurityException {
3920
Method method = null;
3921
Object enclosing = getEnclosingObject();
3922
if (enclosing instanceof Method) {
3923
method = (Method)enclosing;
3924
@SuppressWarnings("removal")
3925
SecurityManager security = System.getSecurityManager();
3926
if (security != null) {
3927
ClassLoader callerClassLoader = ClassLoader.getStackClassLoader(1);
3928
method.getDeclaringClass().checkMemberAccess(security, callerClassLoader, Member.DECLARED);
3929
}
3930
/*[PR CMVC 201439] To remove CheckPackageAccess call from getEnclosingMethod of J9 */
3931
}
3932
return method;
3933
}
3934
3935
private native Class<?> getEnclosingObjectClass();
3936
3937
/**
3938
* Return the enclosing Class of this Class. Unlike getDeclaringClass(),
3939
* this method works on any nested Class, not just classes nested directly
3940
* in other classes.
3941
*
3942
* @return the enclosing Class or null
3943
* @throws SecurityException if package access is not allowed
3944
*
3945
* @since 1.5
3946
*
3947
* @see #getDeclaringClass()
3948
* @see #isAnonymousClass()
3949
* @see #isLocalClass()
3950
* @see #isMemberClass()
3951
*/
3952
@CallerSensitive
3953
public Class<?> getEnclosingClass() throws SecurityException {
3954
Class<?> enclosingClass = getDeclaringClass();
3955
if (enclosingClass == null) {
3956
if (cachedEnclosingClassOffset == -1) {
3957
cachedEnclosingClassOffset = getFieldOffset("cachedEnclosingClass"); //$NON-NLS-1$
3958
}
3959
if (cachedEnclosingClass == null) {
3960
Class<?> localEnclosingClass = getEnclosingObjectClass();
3961
if (localEnclosingClass == null){
3962
localEnclosingClass = ClassReflectNullPlaceHolder.class;
3963
}
3964
writeFieldValue(cachedEnclosingClassOffset, localEnclosingClass);
3965
}
3966
/**
3967
* ClassReflectNullPlaceHolder.class means the value of cachedEnclosingClass is null
3968
* @see ClassReflectNullPlaceHolder.class
3969
*/
3970
enclosingClass = cachedEnclosingClass == ClassReflectNullPlaceHolder.class ? null: cachedEnclosingClass;
3971
}
3972
if (enclosingClass != null) {
3973
@SuppressWarnings("removal")
3974
SecurityManager security = System.getSecurityManager();
3975
if (security != null) {
3976
ClassLoader callerClassLoader = ClassLoader.getStackClassLoader(1);
3977
enclosingClass.checkMemberAccess(security, callerClassLoader, MEMBER_INVALID_TYPE);
3978
}
3979
}
3980
3981
return enclosingClass;
3982
}
3983
3984
private native String getSimpleNameImpl();
3985
3986
/**
3987
* Return the simple name of this Class. The simple name does not include
3988
* the package or the name of the enclosing class. The simple name of an
3989
* anonymous class is "".
3990
*
3991
* @return the simple name
3992
*
3993
* @since 1.5
3994
*
3995
* @see #isAnonymousClass()
3996
*/
3997
public String getSimpleName() {
3998
MetadataCache cache = getMetadataCache();
3999
if (cache.cachedSimpleName != null) {
4000
String cachedSimpleName = cache.cachedSimpleName.get();
4001
if (cachedSimpleName != null) {
4002
return cachedSimpleName;
4003
}
4004
}
4005
4006
int arrayCount = 0;
4007
Class<?> baseType = this;
4008
if (isArray()) {
4009
arrayCount = 1;
4010
while ((baseType = baseType.getComponentType()).isArray()) {
4011
arrayCount++;
4012
}
4013
}
4014
String simpleName = baseType.getSimpleNameImpl();
4015
String fullName = baseType.getName();
4016
if (simpleName == null) {
4017
/**
4018
* It is a base class, an anonymous class, or a hidden class.
4019
* Call getEnclosingClass() instead of getEnclosingObjectClass() to check getDeclaringClass() first. Hidden class test expects
4020
* NoClassDefFoundError from getDeclaringClass().
4021
*/
4022
Class<?> parent = baseType.getEnclosingClass();
4023
if (parent != null) {
4024
simpleName = ""; //$NON-NLS-1$
4025
} else {
4026
// remove the package name
4027
int index = fullName.lastIndexOf('.');
4028
if (index != -1) {
4029
simpleName = fullName.substring(index+1);
4030
} else {
4031
// no periods in fully qualified name, thus simple name is also the full name
4032
simpleName = fullName;
4033
}
4034
}
4035
}
4036
/*[IF !Sidecar19-SE]*/
4037
/* In Java 8, the simple name needs to match the full name*/
4038
else if (!fullName.endsWith(simpleName)) {
4039
Class<?> parent = baseType.getEnclosingObjectClass();
4040
int index = fullName.lastIndexOf('.') + 1;
4041
if (parent == null) {
4042
parent = getDeclaringClassImpl();
4043
}
4044
if (parent != null) {
4045
/* Nested classes have names which consist of the parent class name followed by a '$', followed by
4046
* the simple name. Some nested classes have additional characters between the parent class name
4047
* and the simple name of the nested class.
4048
*/
4049
String parentName = parent.getName();
4050
if (fullName.startsWith(parentName) && (fullName.charAt(parentName.length()) == '$')) {
4051
index = fullName.lastIndexOf('$') + 1;
4052
// a local class simple name is preceded by a sequence of digits
4053
while (index < fullName.length() && !Character.isJavaIdentifierStart(fullName.charAt(index))) {
4054
index++;
4055
}
4056
}
4057
}
4058
if (index != -1) {
4059
simpleName = fullName.substring(index);
4060
}
4061
}
4062
/*[ENDIF] !Sidecar19-SE*/
4063
if (arrayCount > 0) {
4064
StringBuilder result = new StringBuilder(simpleName);
4065
for (int i=0; i<arrayCount; i++) {
4066
result.append("[]"); //$NON-NLS-1$
4067
}
4068
return result.toString();
4069
}
4070
return cacheSimpleName(simpleName);
4071
}
4072
4073
/**
4074
* Return the canonical name of this Class. The canonical name is null
4075
* for a local or anonymous class. The canonical name includes the package
4076
* and the name of the enclosing class.
4077
*
4078
* @return the canonical name or null
4079
*
4080
* @since 1.5
4081
*
4082
* @see #isAnonymousClass()
4083
* @see #isLocalClass()
4084
*/
4085
public String getCanonicalName() {
4086
MetadataCache cache = getMetadataCache();
4087
if (cache.cachedCanonicalName != null) {
4088
String cachedCanonicalName = cache.cachedCanonicalName.get();
4089
if (cachedCanonicalName != null) {
4090
return cachedCanonicalName;
4091
}
4092
}
4093
4094
int arrayCount = 0;
4095
Class<?> baseType = this;
4096
if (isArray()) {
4097
arrayCount = 1;
4098
while ((baseType = baseType.getComponentType()).isArray()) {
4099
arrayCount++;
4100
}
4101
}
4102
/*[IF JAVA_SPEC_VERSION >= 15]*/
4103
if (baseType.isHidden()) {
4104
/* Canonical name is always null for hidden classes. */
4105
return null;
4106
}
4107
/*[ENDIF] JAVA_SPEC_VERSION >= 15 */
4108
if (baseType.getEnclosingObjectClass() != null) {
4109
// local or anonymous class
4110
return null;
4111
}
4112
String canonicalName;
4113
Class<?> declaringClass = baseType.getDeclaringClass();
4114
if (declaringClass == null) {
4115
canonicalName = baseType.getName();
4116
} else {
4117
/*[PR 119256] The canonical name of a member class of a local class should be null */
4118
String declaringClassCanonicalName = declaringClass.getCanonicalName();
4119
if (declaringClassCanonicalName == null) return null;
4120
// remove the enclosingClass from the name, including the $
4121
String simpleName = baseType.getName().substring(declaringClass.getName().length() + 1);
4122
canonicalName = declaringClassCanonicalName + '.' + simpleName;
4123
}
4124
4125
if (arrayCount > 0) {
4126
StringBuilder result = new StringBuilder(canonicalName);
4127
for (int i=0; i<arrayCount; i++) {
4128
result.append("[]"); //$NON-NLS-1$
4129
}
4130
return result.toString();
4131
}
4132
return cacheCanonicalName(canonicalName);
4133
}
4134
4135
/**
4136
* Answer if this Class is anonymous. An unnamed Class defined
4137
* inside a method.
4138
*
4139
* @return true if this Class is anonymous.
4140
*
4141
* @since 1.5
4142
*
4143
* @see #isLocalClass()
4144
*/
4145
public boolean isAnonymousClass() {
4146
return getSimpleNameImpl() == null && getEnclosingObjectClass() != null;
4147
}
4148
4149
/**
4150
* Answer if this Class is local. A named Class defined inside
4151
* a method.
4152
*
4153
* @return true if this Class is local.
4154
*
4155
* @since 1.5
4156
*
4157
* @see #isAnonymousClass()
4158
*/
4159
public boolean isLocalClass() {
4160
return getEnclosingObjectClass() != null && getSimpleNameImpl() != null;
4161
}
4162
4163
/**
4164
* Answer if this Class is a member Class. A Class defined inside another
4165
* Class.
4166
*
4167
* @return true if this Class is local.
4168
*
4169
* @since 1.5
4170
*
4171
* @see #isLocalClass()
4172
*/
4173
public boolean isMemberClass() {
4174
return getEnclosingObjectClass() == null && getDeclaringClass() != null;
4175
}
4176
4177
/**
4178
* Compute the signature for get*Method()
4179
*
4180
* @param throwException if NoSuchMethodException is thrown
4181
* @param name the name of the method
4182
* @param parameterTypes the types of the arguments
4183
* @return the signature string
4184
* @throws NoSuchMethodException if one of the parameter types cannot be found in the local class loader
4185
*
4186
* @see #getDeclaredMethod
4187
* @see #getMethod
4188
*/
4189
private String getParameterTypesSignature(boolean throwException, String name, Class<?>[] parameterTypes, String returnTypeSignature) throws NoSuchMethodException {
4190
int total = 2;
4191
String[] sigs = new String[parameterTypes.length];
4192
for(int i = 0; i < parameterTypes.length; i++) {
4193
Class<?> parameterType = parameterTypes[i];
4194
/*[PR 103441] should throw NoSuchMethodException */
4195
if (parameterType != null) {
4196
sigs[i] = parameterType.getSignature();
4197
total += sigs[i].length();
4198
} else {
4199
if (throwException) {
4200
throw newNoSuchMethodException(name, parameterTypes);
4201
} else {
4202
return null;
4203
}
4204
}
4205
}
4206
total += returnTypeSignature.length();
4207
StringBuilder signature = new StringBuilder(total);
4208
signature.append('(');
4209
for(int i = 0; i < parameterTypes.length; i++)
4210
signature.append(sigs[i]);
4211
signature.append(')').append(returnTypeSignature);
4212
return signature.toString();
4213
}
4214
4215
/*[IF JAVA_SPEC_VERSION == 8]*/
4216
/*[PR CMVC 114820, CMVC 115873, CMVC 116166] add reflection cache */
4217
private static Method copyMethod, copyField, copyConstructor;
4218
private static Field methodParameterTypesField;
4219
private static Field constructorParameterTypesField;
4220
private static final Object[] NoArgs = new Object[0];
4221
/*[ENDIF] JAVA_SPEC_VERSION == 8 */
4222
4223
/*[PR JAZZ 107786] constructorParameterTypesField should be initialized regardless of reflectCacheEnabled or not */
4224
static void initCacheIds(boolean cacheEnabled, boolean cacheDebug) {
4225
reflectCacheEnabled = cacheEnabled;
4226
reflectCacheDebug = cacheDebug;
4227
/*[IF JAVA_SPEC_VERSION == 8]*/
4228
AccessController.doPrivileged(new PrivilegedAction<Void>() {
4229
@Override
4230
public Void run() {
4231
doInitCacheIds();
4232
return null;
4233
}
4234
});
4235
/*[ENDIF] JAVA_SPEC_VERSION == 8 */
4236
}
4237
static void setReflectCacheAppOnly(boolean cacheAppOnly) {
4238
reflectCacheAppOnly = cacheAppOnly;
4239
}
4240
/*[IF JAVA_SPEC_VERSION == 8]*/
4241
@SuppressWarnings("nls")
4242
static void doInitCacheIds() {
4243
/*
4244
* We cannot just call getDeclaredField() because that method includes a call
4245
* to Reflection.filterFields() which will remove the fields needed here.
4246
* The remaining required behavior of getDeclaredField() is inlined here.
4247
* The security checks are omitted (they would be redundant). Caching is
4248
* not done (we're in the process of initializing the caching mechanisms).
4249
* We must ensure the classes that own the fields of interest are prepared.
4250
*/
4251
J9VMInternals.prepare(Constructor.class);
4252
J9VMInternals.prepare(Method.class);
4253
try {
4254
constructorParameterTypesField = Constructor.class.getDeclaredFieldImpl("parameterTypes");
4255
methodParameterTypesField = Method.class.getDeclaredFieldImpl("parameterTypes");
4256
} catch (NoSuchFieldException e) {
4257
throw newInternalError(e);
4258
}
4259
constructorParameterTypesField.setAccessible(true);
4260
methodParameterTypesField.setAccessible(true);
4261
if (reflectCacheEnabled) {
4262
copyConstructor = getAccessibleMethod(Constructor.class, "copy");
4263
copyMethod = getAccessibleMethod(Method.class, "copy");
4264
copyField = getAccessibleMethod(Field.class, "copy");
4265
}
4266
}
4267
/*[ENDIF] JAVA_SPEC_VERSION == 8 */
4268
private static Method getAccessibleMethod(Class<?> cls, String name) {
4269
try {
4270
Method method = cls.getDeclaredMethod(name, EmptyParameters);
4271
method.setAccessible(true);
4272
return method;
4273
} catch (NoSuchMethodException e) {
4274
throw newInternalError(e);
4275
}
4276
}
4277
4278
/*[PR RTC 104994 redesign getMethods]*/
4279
/**
4280
* represents all methods of a given name and signature visible from a given class or interface.
4281
*
4282
*/
4283
private class MethodInfo {
4284
ArrayList<Method> jlrMethods;
4285
Method me;
4286
private final int myHash;
4287
private Class<?>[] paramTypes;
4288
private Class<?> returnType;
4289
private java.lang.String methodName;
4290
4291
public MethodInfo(Method myMethod) {
4292
me = myMethod;
4293
methodName = myMethod.getName();
4294
myHash = methodName.hashCode();
4295
this.paramTypes = null;
4296
this.returnType = null;
4297
jlrMethods = null;
4298
}
4299
4300
public MethodInfo(MethodInfo otherMi) {
4301
this.me = otherMi.me;
4302
this.methodName = otherMi.methodName;
4303
this.paramTypes = otherMi.paramTypes;
4304
this.returnType = otherMi.returnType;
4305
this.myHash = otherMi.myHash;
4306
4307
if (null != otherMi.jlrMethods) {
4308
jlrMethods = (ArrayList<Method>) otherMi.jlrMethods.clone();
4309
} else {
4310
jlrMethods = null;
4311
}
4312
4313
}
4314
4315
private void initializeTypes() {
4316
paramTypes = getParameterTypes(me);
4317
returnType = me.getReturnType();
4318
}
4319
4320
/** (non-Javadoc)
4321
* @param that another MethodInfo object
4322
* @return true if the methods have the same name and signature
4323
* @note does not compare the defining class, permissions, exceptions, etc.
4324
*/
4325
@Override
4326
public boolean equals(Object that) {
4327
if (this == that) {
4328
return true;
4329
}
4330
if (!that.getClass().equals(this.getClass())) {
4331
return false;
4332
}
4333
@SuppressWarnings("unchecked")
4334
MethodInfo otherMethod = (MethodInfo) that;
4335
if (!methodName.equals(otherMethod.methodName)) {
4336
return false;
4337
}
4338
if (null == returnType) {
4339
initializeTypes();
4340
}
4341
if (null == otherMethod.returnType) {
4342
otherMethod.initializeTypes();
4343
}
4344
if (!returnType.equals(otherMethod.returnType)) {
4345
return false;
4346
}
4347
Class<?>[] m1Parms = paramTypes;
4348
Class<?>[] m2Parms = otherMethod.paramTypes;
4349
if (m1Parms.length != m2Parms.length) {
4350
return false;
4351
}
4352
for (int i = 0; i < m1Parms.length; i++) {
4353
if (m1Parms[i] != m2Parms[i]) {
4354
return false;
4355
}
4356
}
4357
return true;
4358
}
4359
4360
/**
4361
* Add a method to the list. newMethod may be discarded if it is masked by an incumbent method in the list.
4362
* Also, an incumbent method may be removed if newMethod masks it.
4363
* In general, a target class inherits a method from its direct superclass or directly implemented interfaces unless:
4364
* - the method is static or private and the declaring class is not the target class
4365
* - the target class declares the method (concrete or abstract)
4366
* - the method is default and a superclass of the target class contains a concrete implementation of the method
4367
* - a more specific implemented interface contains a concrete implementation
4368
* @param newMethod method to be added.
4369
*/
4370
void update(Method newMethod) {
4371
int newModifiers = newMethod.getModifiers();
4372
if (!Modifier.isPublic(newModifiers)) { /* can't see the method */
4373
return;
4374
}
4375
Class<?> newMethodClass = newMethod.getDeclaringClass();
4376
boolean newMethodIsAbstract = Modifier.isAbstract(newModifiers);
4377
boolean newMethodClassIsInterface = newMethodClass.isInterface();
4378
4379
if (null == jlrMethods) {
4380
/* handle the common case of a single declaration */
4381
if (!newMethod.equals(me)) {
4382
Class<?> incumbentMethodClass = me.getDeclaringClass();
4383
if (Class.this != incumbentMethodClass) {
4384
boolean incumbentIsAbstract = Modifier.isAbstract(me.getModifiers());
4385
boolean incumbentClassIsInterface = incumbentMethodClass.isInterface();
4386
if (methodAOverridesMethodB(newMethodClass, newMethodIsAbstract, newMethodClassIsInterface,
4387
incumbentMethodClass, incumbentIsAbstract, incumbentClassIsInterface)
4388
) {
4389
me = newMethod;
4390
} else if (!methodAOverridesMethodB(incumbentMethodClass, incumbentIsAbstract, incumbentClassIsInterface,
4391
newMethodClass, newMethodIsAbstract, newMethodClassIsInterface)
4392
) {
4393
/* we need to store both */
4394
jlrMethods = new ArrayList<>(2);
4395
jlrMethods.add(me);
4396
jlrMethods.add(newMethod);
4397
}
4398
}
4399
}
4400
} else {
4401
int methodCursor = 0;
4402
boolean addMethod = true;
4403
boolean replacedMethod = false;
4404
while (methodCursor < jlrMethods.size()) {
4405
int increment = 1;
4406
Method m = jlrMethods.get(methodCursor);
4407
if (newMethod.equals(m)) { /* already have this method */
4408
addMethod = false;
4409
} else {
4410
Class<?> incumbentMethodClass = m.getDeclaringClass();
4411
if (Class.this == incumbentMethodClass) {
4412
addMethod = false;
4413
} else {
4414
boolean incumbentIsAbstract = Modifier.isAbstract(m.getModifiers());
4415
boolean incumbentClassIsInterface = incumbentMethodClass.isInterface();
4416
if (methodAOverridesMethodB(newMethodClass, newMethodIsAbstract, newMethodClassIsInterface,
4417
incumbentMethodClass, incumbentIsAbstract, incumbentClassIsInterface)
4418
) {
4419
if (!replacedMethod) {
4420
/* preserve ordering by removing old and appending new instead of directly replacing. */
4421
jlrMethods.remove(methodCursor);
4422
jlrMethods.add(newMethod);
4423
increment = 0;
4424
replacedMethod = true;
4425
} else {
4426
jlrMethods.remove(methodCursor);
4427
increment = 0;
4428
/* everything slid over one slot */
4429
}
4430
addMethod = false;
4431
} else if (methodAOverridesMethodB(incumbentMethodClass, incumbentIsAbstract, incumbentClassIsInterface,
4432
newMethodClass, newMethodIsAbstract, newMethodClassIsInterface)
4433
) {
4434
addMethod = false;
4435
}
4436
}
4437
}
4438
methodCursor += increment;
4439
}
4440
if (addMethod) {
4441
jlrMethods.add(newMethod);
4442
}
4443
}
4444
}
4445
4446
public void update(MethodInfo otherMi) {
4447
if (null == otherMi.jlrMethods) {
4448
update(otherMi.me);
4449
} else for (Method m: otherMi.jlrMethods) {
4450
update(m);
4451
}
4452
}
4453
@Override
4454
public int hashCode() {
4455
return myHash;
4456
}
4457
4458
}
4459
4460
static boolean methodAOverridesMethodB(Class<?> methodAClass, boolean methodAIsAbstract, boolean methodAClassIsInterface,
4461
Class<?> methodBClass, boolean methodBIsAbstract, boolean methodBClassIsInterface) {
4462
return (methodBIsAbstract && methodBClassIsInterface && !methodAIsAbstract && !methodAClassIsInterface) ||
4463
(methodBClass.isAssignableFrom(methodAClass)
4464
/*[IF !Sidecar19-SE]*/
4465
/*
4466
* In Java 8, abstract methods in subinterfaces do not hide abstract methods in superinterfaces.
4467
* This is fixed in Java 9.
4468
*/
4469
&& (!methodAClassIsInterface || !methodAIsAbstract)
4470
/*[ENDIF]*/
4471
);
4472
}
4473
4474
/*[PR 125873] Improve reflection cache */
4475
private static final class ReflectRef extends SoftReference<Object> implements Runnable {
4476
private static final ReferenceQueue<Object> queue = new ReferenceQueue<>();
4477
private final ReflectCache cache;
4478
final CacheKey key;
4479
ReflectRef(ReflectCache cache, CacheKey key, Object value) {
4480
super(value, queue);
4481
this.cache = cache;
4482
this.key = key;
4483
}
4484
@Override
4485
public void run() {
4486
cache.handleCleared(this);
4487
}
4488
}
4489
4490
/*[IF]*/
4491
/*
4492
* Keys for constructors, fields and methods are all mutually distinct so we can
4493
* distinguish them in a single map. The key for a field has parameterTypes == null
4494
* while parameterTypes can't be null for constructors or methods. The key for a
4495
* constructor has an empty name which is not legal in a class file (for any feature).
4496
* The Public* and Declared* keys have names that can't collide with any other normal
4497
* key (derived from a legal class).
4498
*/
4499
/*[ENDIF]*/
4500
private static final class CacheKey {
4501
/*[PR CMVC 163440] java.lang.Class$CacheKey.PRIME should be static */
4502
private static final int PRIME = 31;
4503
private static int hashCombine(int partial, int itemHash) {
4504
return partial * PRIME + itemHash;
4505
}
4506
private static int hashCombine(int partial, Object item) {
4507
return hashCombine(partial, item == null ? 0 : item.hashCode());
4508
}
4509
4510
static CacheKey newConstructorKey(Class<?>[] parameterTypes) {
4511
return new CacheKey("", parameterTypes, null); //$NON-NLS-1$
4512
}
4513
static CacheKey newFieldKey(String fieldName, Class<?> type) {
4514
return new CacheKey(fieldName, null, type);
4515
}
4516
static CacheKey newMethodKey(String methodName, Class<?>[] parameterTypes, Class<?> returnType) {
4517
return new CacheKey(methodName, parameterTypes, returnType);
4518
}
4519
/*[IF JAVA_SPEC_VERSION >= 11]*/
4520
static CacheKey newDeclaredPublicMethodsKey(String methodName, Class<?>[] parameterTypes) {
4521
return new CacheKey("#m" + methodName, parameterTypes, null); //$NON-NLS-1$
4522
}
4523
/*[ENDIF] JAVA_SPEC_VERSION >= 11 */
4524
4525
static final CacheKey PublicConstructorsKey = new CacheKey("/c", EmptyParameters, null); //$NON-NLS-1$
4526
static final CacheKey PublicFieldsKey = newFieldKey("/f", null); //$NON-NLS-1$
4527
static final CacheKey PublicMethodsKey = new CacheKey("/m", EmptyParameters, null); //$NON-NLS-1$
4528
4529
static final CacheKey DeclaredConstructorsKey = new CacheKey(".c", EmptyParameters, null); //$NON-NLS-1$
4530
static final CacheKey DeclaredFieldsKey = newFieldKey(".f", null); //$NON-NLS-1$
4531
static final CacheKey DeclaredMethodsKey = new CacheKey(".m", EmptyParameters, null); //$NON-NLS-1$
4532
4533
private final String name;
4534
private final Class<?>[] parameterTypes;
4535
private final Class<?> returnType;
4536
private final int hashCode;
4537
private CacheKey(String name, Class<?>[] parameterTypes, Class<?> returnType) {
4538
super();
4539
int hash = hashCombine(name.hashCode(), returnType);
4540
if (parameterTypes != null) {
4541
for (Class<?> parameterType : parameterTypes) {
4542
hash = hashCombine(hash, parameterType);
4543
}
4544
}
4545
this.name = name;
4546
this.parameterTypes = parameterTypes;
4547
this.returnType = returnType;
4548
this.hashCode = hash;
4549
}
4550
@Override
4551
public boolean equals(Object obj) {
4552
if (this == obj) {
4553
return true;
4554
}
4555
CacheKey that = (CacheKey) obj;
4556
if (this.returnType == that.returnType
4557
&& sameTypes(this.parameterTypes, that.parameterTypes)) {
4558
return this.name.equals(that.name);
4559
}
4560
return false;
4561
}
4562
@Override
4563
public int hashCode() {
4564
return hashCode;
4565
}
4566
}
4567
4568
private static Class<?>[] getParameterTypes(Constructor<?> constructor) {
4569
/*[IF JAVA_SPEC_VERSION >= 11]*/
4570
reflectionFactory = getReflectionFactory();
4571
return reflectionFactory.getExecutableSharedParameterTypes(constructor);
4572
/*[ELSE] JAVA_SPEC_VERSION >= 11*/
4573
try {
4574
if (null != constructorParameterTypesField) {
4575
return (Class<?>[]) constructorParameterTypesField.get(constructor);
4576
} else {
4577
return constructor.getParameterTypes();
4578
}
4579
} catch (IllegalAccessException | IllegalArgumentException e) {
4580
throw newInternalError(e);
4581
}
4582
/*[ENDIF] JAVA_SPEC_VERSION >= 11 */
4583
}
4584
4585
static Class<?>[] getParameterTypes(Method method) {
4586
/*[IF JAVA_SPEC_VERSION >= 11]*/
4587
reflectionFactory = getReflectionFactory();
4588
return reflectionFactory.getExecutableSharedParameterTypes(method);
4589
/*[ELSE] JAVA_SPEC_VERSION >= 11*/
4590
try {
4591
if (null != methodParameterTypesField) {
4592
return (Class<?>[]) methodParameterTypesField.get(method);
4593
} else {
4594
return method.getParameterTypes();
4595
}
4596
} catch (IllegalAccessException | IllegalArgumentException e) {
4597
throw newInternalError(e);
4598
}
4599
/*[ENDIF] JAVA_SPEC_VERSION >= 11 */
4600
}
4601
4602
/*[PR 125873] Improve reflection cache */
4603
private static final class ReflectCache extends ConcurrentHashMap<CacheKey, ReflectRef> {
4604
private static final long serialVersionUID = 6551549321039776630L;
4605
4606
private final Class<?> owner;
4607
private final AtomicInteger useCount;
4608
4609
ReflectCache(Class<?> owner) {
4610
super();
4611
this.owner = owner;
4612
this.useCount = new AtomicInteger();
4613
}
4614
4615
ReflectCache acquire() {
4616
useCount.incrementAndGet();
4617
return this;
4618
}
4619
4620
void handleCleared(ReflectRef ref) {
4621
boolean removed = false;
4622
if (remove(ref.key, ref) && isEmpty()) {
4623
if (useCount.get() == 0) {
4624
owner.setReflectCache(null);
4625
removed = true;
4626
}
4627
}
4628
if (reflectCacheDebug) {
4629
if (removed) {
4630
System.err.println("Removed reflect cache for: " + this); //$NON-NLS-1$
4631
} else {
4632
System.err.println("Retained reflect cache for: " + this + ", size: " + size()); //$NON-NLS-1$ //$NON-NLS-2$
4633
}
4634
}
4635
}
4636
4637
Object find(CacheKey key) {
4638
ReflectRef ref = get(key);
4639
return ref != null ? ref.get() : null;
4640
}
4641
4642
void insert(CacheKey key, Object value) {
4643
put(key, new ReflectRef(this, key, value));
4644
}
4645
4646
<T> T insertIfAbsent(CacheKey key, T value) {
4647
ReflectRef newRef = new ReflectRef(this, key, value);
4648
for (;;) {
4649
ReflectRef oldRef = putIfAbsent(key, newRef);
4650
if (oldRef == null) {
4651
return value;
4652
}
4653
T oldValue = (T) oldRef.get();
4654
if (oldValue != null) {
4655
return oldValue;
4656
}
4657
// The entry addressed by key has been cleared, but not yet removed from this map.
4658
// One thread will successfully replace the entry; the value stored will be shared.
4659
if (replace(key, oldRef, newRef)) {
4660
return value;
4661
}
4662
}
4663
}
4664
4665
void release() {
4666
useCount.decrementAndGet();
4667
}
4668
4669
}
4670
4671
private transient ReflectCache reflectCache;
4672
private static long reflectCacheOffset = -1;
4673
4674
private ReflectCache acquireReflectCache() {
4675
ReflectCache cache = reflectCache;
4676
if (cache == null) {
4677
Unsafe theUnsafe = getUnsafe();
4678
long cacheOffset = getReflectCacheOffset();
4679
ReflectCache newCache = new ReflectCache(this);
4680
do {
4681
// Some thread will insert this new cache making it available to all.
4682
/*[IF Sidecar19-SE]*/
4683
if (theUnsafe.compareAndSetObject(this, cacheOffset, null, newCache)) {
4684
/*[ELSE]
4685
if (theUnsafe.compareAndSwapObject(this, cacheOffset, null, newCache)) {
4686
/*[ENDIF]*/
4687
cache = newCache;
4688
break;
4689
}
4690
cache = (ReflectCache) theUnsafe.getObject(this, cacheOffset);
4691
} while (cache == null);
4692
}
4693
return cache.acquire();
4694
}
4695
private static long getReflectCacheOffset() {
4696
long cacheOffset = reflectCacheOffset;
4697
if (cacheOffset < 0) {
4698
try {
4699
// Bypass the reflection cache to avoid infinite recursion.
4700
Field reflectCacheField = Class.class.getDeclaredFieldImpl("reflectCache"); //$NON-NLS-1$
4701
cacheOffset = getUnsafe().objectFieldOffset(reflectCacheField);
4702
reflectCacheOffset = cacheOffset;
4703
} catch (NoSuchFieldException e) {
4704
throw newInternalError(e);
4705
}
4706
}
4707
return cacheOffset;
4708
}
4709
void setReflectCache(ReflectCache cache) {
4710
// Lazy initialization of a non-volatile field. Ensure the Object is initialized
4711
// and flushed to memory before assigning to the annotationCache field.
4712
/*[IF Sidecar19-SE]
4713
getUnsafe().putObjectRelease(this, getReflectCacheOffset(), cache);
4714
/*[ELSE]*/
4715
getUnsafe().putOrderedObject(this, getReflectCacheOffset(), cache);
4716
/*[ENDIF]*/
4717
}
4718
4719
private ReflectCache peekReflectCache() {
4720
return reflectCache;
4721
}
4722
4723
static InternalError newInternalError(Exception cause) {
4724
return new InternalError(cause);
4725
}
4726
4727
private Method lookupCachedMethod(String methodName, Class<?>[] parameters) {
4728
if (!reflectCacheEnabled) return null;
4729
if (reflectCacheDebug) {
4730
reflectCacheDebugHelper(null, 0, "lookup Method: ", getName(), ".", methodName); //$NON-NLS-1$ //$NON-NLS-2$
4731
}
4732
ReflectCache cache = peekReflectCache();
4733
if (cache != null) {
4734
// use a null returnType to find the Method with the largest depth
4735
Method method = (Method) cache.find(CacheKey.newMethodKey(methodName, parameters, null));
4736
if (method != null) {
4737
try {
4738
Class<?>[] orgParams = getParameterTypes(method);
4739
// ensure the parameter classes are identical
4740
if (sameTypes(parameters, orgParams)) {
4741
/*[IF JAVA_SPEC_VERSION >= 11]*/
4742
reflectionFactory = getReflectionFactory();
4743
return (Method) reflectionFactory.copyMethod(method);
4744
/*[ELSE] JAVA_SPEC_VERSION >= 11*/
4745
return (Method) copyMethod.invoke(method, NoArgs);
4746
/*[ENDIF] JAVA_SPEC_VERSION >= 11 */
4747
}
4748
} catch (IllegalArgumentException
4749
/*[IF JAVA_SPEC_VERSION == 8]*/
4750
| IllegalAccessException | InvocationTargetException
4751
/*[ENDIF] JAVA_SPEC_VERSION == 8 */
4752
e) {
4753
throw newInternalError(e);
4754
}
4755
}
4756
}
4757
return null;
4758
}
4759
4760
@CallerSensitive
4761
private Method cacheMethod(Method method) {
4762
if (!reflectCacheEnabled) return method;
4763
if (reflectCacheAppOnly && ClassLoader.getStackClassLoader(2) == ClassLoader.bootstrapClassLoader) {
4764
return method;
4765
}
4766
/*[IF JAVA_SPEC_VERSION == 8]*/
4767
if (copyMethod == null) return method;
4768
/*[ENDIF] JAVA_SPEC_VERSION == 8 */
4769
if (reflectCacheDebug) {
4770
reflectCacheDebugHelper(null, 0, "cache Method: ", getName(), ".", method.getName()); //$NON-NLS-1$ //$NON-NLS-2$
4771
}
4772
try {
4773
Class<?>[] parameterTypes = getParameterTypes(method);
4774
CacheKey key = CacheKey.newMethodKey(method.getName(), parameterTypes, method.getReturnType());
4775
Class<?> declaringClass = method.getDeclaringClass();
4776
ReflectCache cache = declaringClass.acquireReflectCache();
4777
try {
4778
/*[PR CMVC 116493] store inherited methods in their declaringClass */
4779
method = cache.insertIfAbsent(key, method);
4780
} finally {
4781
if (declaringClass != this) {
4782
cache.release();
4783
cache = acquireReflectCache();
4784
}
4785
}
4786
try {
4787
// cache the Method with the largest depth with a null returnType
4788
CacheKey lookupKey = CacheKey.newMethodKey(method.getName(), parameterTypes, null);
4789
cache.insert(lookupKey, method);
4790
} finally {
4791
cache.release();
4792
}
4793
/*[IF JAVA_SPEC_VERSION >= 11]*/
4794
reflectionFactory = getReflectionFactory();
4795
return (Method) reflectionFactory.copyMethod(method);
4796
/*[ELSE] JAVA_SPEC_VERSION >= 11*/
4797
return (Method) copyMethod.invoke(method, NoArgs);
4798
/*[ENDIF] JAVA_SPEC_VERSION >= 11 */
4799
} catch (IllegalArgumentException
4800
/*[IF JAVA_SPEC_VERSION == 8]*/
4801
| IllegalAccessException | InvocationTargetException
4802
/*[ENDIF] JAVA_SPEC_VERSION == 8 */
4803
e) {
4804
throw newInternalError(e);
4805
}
4806
}
4807
4808
private Field lookupCachedField(String fieldName) {
4809
if (!reflectCacheEnabled) return null;
4810
if (reflectCacheDebug) {
4811
reflectCacheDebugHelper(null, 0, "lookup Field: ", getName(), ".", fieldName); //$NON-NLS-1$ //$NON-NLS-2$
4812
}
4813
ReflectCache cache = peekReflectCache();
4814
if (cache != null) {
4815
/*[PR 124746] Field cache cannot handle same field name with multiple types */
4816
Field field = (Field) cache.find(CacheKey.newFieldKey(fieldName, null));
4817
if (field != null) {
4818
try {
4819
/*[IF JAVA_SPEC_VERSION >= 11]*/
4820
reflectionFactory = getReflectionFactory();
4821
return (Field) reflectionFactory.copyField(field);
4822
/*[ELSE] JAVA_SPEC_VERSION >= 11*/
4823
return (Field) copyField.invoke(field, NoArgs);
4824
/*[ENDIF] JAVA_SPEC_VERSION >= 11 */
4825
} catch (IllegalArgumentException
4826
/*[IF JAVA_SPEC_VERSION == 8]*/
4827
| IllegalAccessException | InvocationTargetException
4828
/*[ENDIF] JAVA_SPEC_VERSION == 8 */
4829
e) {
4830
throw newInternalError(e);
4831
}
4832
}
4833
}
4834
return null;
4835
}
4836
4837
@CallerSensitive
4838
private Field cacheField(Field field) {
4839
if (!reflectCacheEnabled) return field;
4840
if (reflectCacheAppOnly && ClassLoader.getStackClassLoader(2) == ClassLoader.bootstrapClassLoader) {
4841
return field;
4842
}
4843
/*[IF JAVA_SPEC_VERSION == 8]*/
4844
if (copyField == null) return field;
4845
/*[ENDIF] JAVA_SPEC_VERSION == 8 */
4846
if (reflectCacheDebug) {
4847
reflectCacheDebugHelper(null, 0, "cache Field: ", getName(), ".", field.getName()); //$NON-NLS-1$ //$NON-NLS-2$
4848
}
4849
/*[PR 124746] Field cache cannot handle same field name with multiple types */
4850
CacheKey typedKey = CacheKey.newFieldKey(field.getName(), field.getType());
4851
Class<?> declaringClass = field.getDeclaringClass();
4852
ReflectCache cache = declaringClass.acquireReflectCache();
4853
try {
4854
field = cache.insertIfAbsent(typedKey, field);
4855
/*[PR 124746] Field cache cannot handle same field name with multiple types */
4856
if (declaringClass == this) {
4857
// cache the Field returned from getField() with a null returnType
4858
CacheKey lookupKey = CacheKey.newFieldKey(field.getName(), null);
4859
cache.insert(lookupKey, field);
4860
}
4861
} finally {
4862
cache.release();
4863
}
4864
try {
4865
/*[IF JAVA_SPEC_VERSION >= 11]*/
4866
reflectionFactory = getReflectionFactory();
4867
return (Field) reflectionFactory.copyField(field);
4868
/*[ELSE] JAVA_SPEC_VERSION >= 11*/
4869
return (Field) copyField.invoke(field, NoArgs);
4870
/*[ENDIF] JAVA_SPEC_VERSION >= 11 */
4871
} catch (IllegalArgumentException
4872
/*[IF JAVA_SPEC_VERSION == 8]*/
4873
| IllegalAccessException | InvocationTargetException
4874
/*[ENDIF] JAVA_SPEC_VERSION == 8 */
4875
e) {
4876
throw newInternalError(e);
4877
}
4878
}
4879
4880
private Constructor<T> lookupCachedConstructor(Class<?>[] parameters) {
4881
if (!reflectCacheEnabled) return null;
4882
4883
if (reflectCacheDebug) {
4884
reflectCacheDebugHelper(parameters, 1, "lookup Constructor: ", getName()); //$NON-NLS-1$
4885
}
4886
ReflectCache cache = peekReflectCache();
4887
if (cache != null) {
4888
Constructor<?> constructor = (Constructor<?>) cache.find(CacheKey.newConstructorKey(parameters));
4889
if (constructor != null) {
4890
Class<?>[] orgParams = getParameterTypes(constructor);
4891
try {
4892
// ensure the parameter classes are identical
4893
if (sameTypes(orgParams, parameters)) {
4894
/*[IF JAVA_SPEC_VERSION >= 11]*/
4895
reflectionFactory = getReflectionFactory();
4896
return (Constructor<T>) reflectionFactory.copyConstructor(constructor);
4897
/*[ELSE] JAVA_SPEC_VERSION >= 11*/
4898
return (Constructor<T>) copyConstructor.invoke(constructor, NoArgs);
4899
/*[ENDIF] JAVA_SPEC_VERSION >= 11 */
4900
}
4901
} catch (IllegalArgumentException
4902
/*[IF JAVA_SPEC_VERSION == 8]*/
4903
| IllegalAccessException | InvocationTargetException
4904
/*[ENDIF] JAVA_SPEC_VERSION == 8 */
4905
e) {
4906
throw newInternalError(e);
4907
}
4908
}
4909
}
4910
return null;
4911
}
4912
4913
@CallerSensitive
4914
private Constructor<T> cacheConstructor(Constructor<T> constructor) {
4915
if (!reflectCacheEnabled) return constructor;
4916
if (reflectCacheAppOnly && ClassLoader.getStackClassLoader(2) == ClassLoader.bootstrapClassLoader) {
4917
return constructor;
4918
}
4919
/*[IF JAVA_SPEC_VERSION == 8]*/
4920
if (copyConstructor == null) return constructor;
4921
/*[ENDIF] JAVA_SPEC_VERSION == 8 */
4922
if (reflectCacheDebug) {
4923
reflectCacheDebugHelper(constructor.getParameterTypes(), 1, "cache Constructor: ", getName()); //$NON-NLS-1$
4924
}
4925
ReflectCache cache = acquireReflectCache();
4926
try {
4927
CacheKey key = CacheKey.newConstructorKey(getParameterTypes(constructor));
4928
cache.insert(key, constructor);
4929
} finally {
4930
cache.release();
4931
}
4932
try {
4933
/*[IF JAVA_SPEC_VERSION >= 11]*/
4934
reflectionFactory = getReflectionFactory();
4935
return (Constructor<T>) reflectionFactory.copyConstructor(constructor);
4936
/*[ELSE] JAVA_SPEC_VERSION >= 11*/
4937
return (Constructor<T>) copyConstructor.invoke(constructor, NoArgs);
4938
/*[ENDIF] JAVA_SPEC_VERSION >= 11 */
4939
} catch (IllegalArgumentException
4940
/*[IF JAVA_SPEC_VERSION == 8]*/
4941
| IllegalAccessException | InvocationTargetException
4942
/*[ENDIF] JAVA_SPEC_VERSION == 8 */
4943
e) {
4944
throw newInternalError(e);
4945
}
4946
}
4947
4948
private static Method[] copyMethods(Method[] methods) {
4949
Method[] result = new Method[methods.length];
4950
try {
4951
/*[IF JAVA_SPEC_VERSION >= 11]*/
4952
reflectionFactory = getReflectionFactory();
4953
/*[ENDIF] JAVA_SPEC_VERSION >= 11 */
4954
for (int i=0; i<methods.length; i++) {
4955
/*[IF JAVA_SPEC_VERSION >= 11]*/
4956
result[i] = (Method) reflectionFactory.copyMethod(methods[i]);
4957
/*[ELSE] JAVA_SPEC_VERSION >= 11*/
4958
result[i] = (Method) copyMethod.invoke(methods[i], NoArgs);
4959
/*[ENDIF] JAVA_SPEC_VERSION >= 11 */
4960
}
4961
return result;
4962
} catch (IllegalArgumentException
4963
/*[IF JAVA_SPEC_VERSION == 8]*/
4964
| IllegalAccessException | InvocationTargetException
4965
/*[ENDIF] JAVA_SPEC_VERSION == 8 */
4966
e) {
4967
throw newInternalError(e);
4968
}
4969
}
4970
4971
private Method[] lookupCachedMethods(CacheKey cacheKey) {
4972
if (!reflectCacheEnabled) return null;
4973
4974
if (reflectCacheDebug) {
4975
reflectCacheDebugHelper(null, 0, "lookup Methods in: ", getName()); //$NON-NLS-1$
4976
}
4977
ReflectCache cache = peekReflectCache();
4978
if (cache != null) {
4979
Method[] methods = (Method[]) cache.find(cacheKey);
4980
if (methods != null) {
4981
return copyMethods(methods);
4982
}
4983
}
4984
return null;
4985
}
4986
4987
@CallerSensitive
4988
private Method[] cacheMethods(Method[] methods, CacheKey cacheKey) {
4989
if (!reflectCacheEnabled) return methods;
4990
if (reflectCacheAppOnly && ClassLoader.getStackClassLoader(2) == ClassLoader.bootstrapClassLoader) {
4991
return methods;
4992
}
4993
/*[IF JAVA_SPEC_VERSION == 8]*/
4994
if (copyMethod == null) return methods;
4995
/*[ENDIF] JAVA_SPEC_VERSION == 8 */
4996
if (reflectCacheDebug) {
4997
reflectCacheDebugHelper(null, 0, "cache Methods in: ", getName()); //$NON-NLS-1$
4998
}
4999
ReflectCache cache = null;
5000
Class<?> cacheOwner = null;
5001
try {
5002
for (int i = 0; i < methods.length; ++i) {
5003
Method method = methods[i];
5004
CacheKey key = CacheKey.newMethodKey(method.getName(), getParameterTypes(method), method.getReturnType());
5005
Class<?> declaringClass = method.getDeclaringClass();
5006
if (cacheOwner != declaringClass || cache == null) {
5007
if (cache != null) {
5008
cache.release();
5009
cache = null;
5010
}
5011
cache = declaringClass.acquireReflectCache();
5012
cacheOwner = declaringClass;
5013
}
5014
methods[i] = cache.insertIfAbsent(key, method);
5015
}
5016
if (cache != null && cacheOwner != this) {
5017
cache.release();
5018
cache = null;
5019
}
5020
if (cache == null) {
5021
cache = acquireReflectCache();
5022
}
5023
cache.insert(cacheKey, methods);
5024
} finally {
5025
if (cache != null) {
5026
cache.release();
5027
}
5028
}
5029
return copyMethods(methods);
5030
}
5031
5032
private static Field[] copyFields(Field[] fields) {
5033
Field[] result = new Field[fields.length];
5034
try {
5035
/*[IF JAVA_SPEC_VERSION >= 11]*/
5036
reflectionFactory = getReflectionFactory();
5037
/*[ENDIF] JAVA_SPEC_VERSION >= 11 */
5038
for (int i=0; i<fields.length; i++) {
5039
/*[IF JAVA_SPEC_VERSION >= 11]*/
5040
result[i] = (Field) reflectionFactory.copyField(fields[i]);
5041
/*[ELSE] JAVA_SPEC_VERSION >= 11*/
5042
result[i] = (Field) copyField.invoke(fields[i], NoArgs);
5043
/*[ENDIF] JAVA_SPEC_VERSION >= 11 */
5044
}
5045
return result;
5046
} catch (IllegalArgumentException
5047
/*[IF JAVA_SPEC_VERSION == 8]*/
5048
| IllegalAccessException | InvocationTargetException
5049
/*[ENDIF] JAVA_SPEC_VERSION == 8 */
5050
e) {
5051
throw newInternalError(e);
5052
}
5053
}
5054
5055
private Field[] lookupCachedFields(CacheKey cacheKey) {
5056
if (!reflectCacheEnabled) return null;
5057
5058
if (reflectCacheDebug) {
5059
reflectCacheDebugHelper(null, 0, "lookup Fields in: ", getName()); //$NON-NLS-1$
5060
}
5061
ReflectCache cache = peekReflectCache();
5062
if (cache != null) {
5063
Field[] fields = (Field[]) cache.find(cacheKey);
5064
if (fields != null) {
5065
return copyFields(fields);
5066
}
5067
}
5068
return null;
5069
}
5070
5071
@CallerSensitive
5072
private Field[] cacheFields(Field[] fields, CacheKey cacheKey) {
5073
if (!reflectCacheEnabled) return fields;
5074
if (reflectCacheAppOnly && ClassLoader.getStackClassLoader(2) == ClassLoader.bootstrapClassLoader) {
5075
return fields;
5076
}
5077
/*[IF JAVA_SPEC_VERSION == 8]*/
5078
if (copyField == null) return fields;
5079
/*[ENDIF] JAVA_SPEC_VERSION == 8 */
5080
if (reflectCacheDebug) {
5081
reflectCacheDebugHelper(null, 0, "cache Fields in: ", getName()); //$NON-NLS-1$
5082
}
5083
ReflectCache cache = null;
5084
Class<?> cacheOwner = null;
5085
try {
5086
for (int i = 0; i < fields.length; ++i) {
5087
/*[PR 124746] Field cache cannot handle same field name with multiple types */
5088
Field field = fields[i];
5089
Class<?> declaringClass = field.getDeclaringClass();
5090
if (cacheOwner != declaringClass || cache == null) {
5091
if (cache != null) {
5092
cache.release();
5093
cache = null;
5094
}
5095
cache = declaringClass.acquireReflectCache();
5096
cacheOwner = declaringClass;
5097
}
5098
fields[i] = cache.insertIfAbsent(CacheKey.newFieldKey(field.getName(), field.getType()), field);
5099
}
5100
if (cache != null && cacheOwner != this) {
5101
cache.release();
5102
cache = null;
5103
}
5104
if (cache == null) {
5105
cache = acquireReflectCache();
5106
}
5107
cache.insert(cacheKey, fields);
5108
} finally {
5109
if (cache != null) {
5110
cache.release();
5111
}
5112
}
5113
return copyFields(fields);
5114
}
5115
5116
private static <T> Constructor<T>[] copyConstructors(Constructor<T>[] constructors) {
5117
Constructor<T>[] result = new Constructor[constructors.length];
5118
try {
5119
/*[IF JAVA_SPEC_VERSION >= 11]*/
5120
reflectionFactory = getReflectionFactory();
5121
/*[ENDIF] JAVA_SPEC_VERSION >= 11 */
5122
for (int i=0; i<constructors.length; i++) {
5123
/*[IF JAVA_SPEC_VERSION >= 11]*/
5124
result[i] = (Constructor<T>) reflectionFactory.copyConstructor(constructors[i]);
5125
/*[ELSE] JAVA_SPEC_VERSION >= 11*/
5126
result[i] = (Constructor<T>) copyConstructor.invoke(constructors[i], NoArgs);
5127
/*[ENDIF] JAVA_SPEC_VERSION >= 11 */
5128
}
5129
return result;
5130
} catch (IllegalArgumentException
5131
/*[IF JAVA_SPEC_VERSION == 8]*/
5132
| IllegalAccessException | InvocationTargetException
5133
/*[ENDIF] JAVA_SPEC_VERSION == 8 */
5134
e) {
5135
throw newInternalError(e);
5136
}
5137
}
5138
5139
private Constructor<T>[] lookupCachedConstructors(CacheKey cacheKey) {
5140
if (!reflectCacheEnabled) return null;
5141
5142
if (reflectCacheDebug) {
5143
reflectCacheDebugHelper(null, 0, "lookup Constructors in: ", getName()); //$NON-NLS-1$
5144
}
5145
ReflectCache cache = peekReflectCache();
5146
if (cache != null) {
5147
Constructor<T>[] constructors = (Constructor<T>[]) cache.find(cacheKey);
5148
if (constructors != null) {
5149
return copyConstructors(constructors);
5150
}
5151
}
5152
return null;
5153
}
5154
5155
@CallerSensitive
5156
private Constructor<T>[] cacheConstructors(Constructor<T>[] constructors, CacheKey cacheKey) {
5157
if (!reflectCacheEnabled) return constructors;
5158
if (reflectCacheAppOnly && ClassLoader.getStackClassLoader(2) == ClassLoader.bootstrapClassLoader) {
5159
return constructors;
5160
}
5161
/*[IF JAVA_SPEC_VERSION == 8]*/
5162
if (copyConstructor == null) return constructors;
5163
/*[ENDIF] JAVA_SPEC_VERSION == 8 */
5164
if (reflectCacheDebug) {
5165
reflectCacheDebugHelper(null, 0, "cache Constructors in: ", getName()); //$NON-NLS-1$
5166
}
5167
ReflectCache cache = acquireReflectCache();
5168
try {
5169
for (int i=0; i<constructors.length; i++) {
5170
CacheKey key = CacheKey.newConstructorKey(getParameterTypes(constructors[i]));
5171
constructors[i] = cache.insertIfAbsent(key, constructors[i]);
5172
}
5173
cache.insert(cacheKey, constructors);
5174
} finally {
5175
cache.release();
5176
}
5177
return copyConstructors(constructors);
5178
}
5179
5180
private static <T> Constructor<T> checkParameterTypes(Constructor<T> constructor, Class<?>[] parameterTypes) {
5181
Class<?>[] constructorParameterTypes = getParameterTypes(constructor);
5182
return sameTypes(constructorParameterTypes, parameterTypes) ? constructor : null;
5183
}
5184
5185
static boolean sameTypes(Class<?>[] aTypes, Class<?>[] bTypes) {
5186
if (aTypes == null) {
5187
if (bTypes == null) {
5188
return true;
5189
}
5190
} else if (bTypes != null) {
5191
int length = aTypes.length;
5192
if (length == bTypes.length) {
5193
for (int i = 0; i < length; ++i) {
5194
if (aTypes[i] != bTypes[i]) {
5195
return false;
5196
}
5197
}
5198
return true;
5199
}
5200
}
5201
return false;
5202
}
5203
5204
Object getMethodHandleCache() {
5205
return methodHandleCache;
5206
}
5207
5208
Object setMethodHandleCache(Object cache) {
5209
Object result = methodHandleCache;
5210
if (null == result) {
5211
synchronized (this) {
5212
result = methodHandleCache;
5213
if (null == result) {
5214
methodHandleCache = cache;
5215
result = cache;
5216
}
5217
}
5218
}
5219
return result;
5220
}
5221
5222
ConstantPool getConstantPool(Object internalCP) {
5223
return VM.getVMLangAccess().getConstantPool(internalCP);
5224
}
5225
5226
/*[IF Sidecar19-SE]*/
5227
Map<Class<? extends Annotation>, Annotation> getDeclaredAnnotationMap() {
5228
throw new Error("Class.getDeclaredAnnotationMap() unimplemented"); //$NON-NLS-1$
5229
}
5230
byte[] getRawAnnotations() {
5231
throw new Error("Class.getRawAnnotations() unimplemented"); //$NON-NLS-1$
5232
}
5233
byte[] getRawTypeAnnotations() {
5234
throw new Error("Class.getRawTypeAnnotations() unimplemented"); //$NON-NLS-1$
5235
}
5236
static byte[] getExecutableTypeAnnotationBytes(Executable exec) {
5237
throw new Error("Class.getExecutableTypeAnnotationBytes() unimplemented"); //$NON-NLS-1$
5238
}
5239
/*[ENDIF] Sidecar19-SE*/
5240
5241
/*[IF JAVA_SPEC_VERSION >= 11]*/
5242
/**
5243
* Answers the host class of the receiver's nest.
5244
*
5245
* @return the host class of the receiver.
5246
*/
5247
private native Class<?> getNestHostImpl();
5248
5249
/**
5250
* Answers the nest member classes of the receiver's nest host.
5251
*
5252
* @return the host class of the receiver.
5253
*
5254
* @implNote This implementation does not remove duplicate nest members if they are present.
5255
*/
5256
private native Class<?>[] getNestMembersImpl();
5257
5258
/**
5259
* Answers the host class of the receiver's nest.
5260
*
5261
* @throws SecurityException if nestHost is not same as the current class, a security manager
5262
* is present, the classloader of the caller is not the same or an ancestor of nestHost
5263
* class, and checkPackageAccess() denies access
5264
* @return the host class of the receiver.
5265
*/
5266
@CallerSensitive
5267
public Class<?> getNestHost() throws SecurityException {
5268
if (nestHost == null) {
5269
nestHost = getNestHostImpl();
5270
}
5271
/* The specification requires that if:
5272
* - the returned class is not the current class
5273
* - a security manager is present
5274
* - the caller's class loader is not the same or an ancestor of the returned class
5275
* - s.checkPackageAccess() disallows access to the package of the returned class
5276
* then throw a SecurityException.
5277
*/
5278
if (nestHost != this) {
5279
@SuppressWarnings("removal")
5280
SecurityManager securityManager = System.getSecurityManager();
5281
if (securityManager != null) {
5282
ClassLoader callerClassLoader = ClassLoader.getCallerClassLoader();
5283
ClassLoader nestHostClassLoader = nestHost.internalGetClassLoader();
5284
if (!doesClassLoaderDescendFrom(nestHostClassLoader, callerClassLoader)) {
5285
String nestHostPackageName = nestHost.getPackageName();
5286
if ((nestHostPackageName != null) && (nestHostPackageName != "")) {
5287
securityManager.checkPackageAccess(nestHostPackageName);
5288
}
5289
}
5290
}
5291
}
5292
return nestHost;
5293
}
5294
5295
/**
5296
* Returns true if the class passed has the same nest top as this class.
5297
*
5298
* @param that The class to compare
5299
* @return true if class is a nestmate of this class; false otherwise.
5300
*
5301
*/
5302
public boolean isNestmateOf(Class<?> that) {
5303
Class<?> thisNestHost = this.nestHost;
5304
if (thisNestHost == null) {
5305
thisNestHost = this.getNestHostImpl();
5306
}
5307
Class<?> thatNestHost = that.nestHost;
5308
if (thatNestHost == null) {
5309
thatNestHost = that.getNestHostImpl();
5310
}
5311
return (thisNestHost == thatNestHost);
5312
}
5313
5314
/**
5315
* Answers the nest member classes of the receiver's nest host.
5316
*
5317
* @throws SecurityException if a SecurityManager is present and package access is not allowed
5318
/*[IF JAVA_SPEC_VERSION < 15]
5319
* @throws LinkageError if there is any problem loading or validating a nest member or the nest host
5320
/*[ENDIF]
5321
* @throws SecurityException if a returned class is not the current class, a security manager is enabled,
5322
* the caller's class loader is not the same or an ancestor of that returned class, and the
5323
* checkPackageAccess() denies access
5324
* @return the host class of the receiver.
5325
*/
5326
@CallerSensitive
5327
public Class<?>[] getNestMembers() throws
5328
/*[IF JAVA_SPEC_VERSION < 15] */
5329
LinkageError,
5330
/*[ENDIF] JAVA_SPEC_VERSION < 15 */
5331
SecurityException {
5332
if (isArray() || isPrimitive()) {
5333
/* By spec, Class objects representing array types or primitive types
5334
* belong to the nest consisting only of itself.
5335
*/
5336
return new Class<?>[] { this };
5337
}
5338
5339
Class<?>[] members = getNestMembersImpl();
5340
/* Skip security check for the Class object that belongs to the nest consisting only of itself */
5341
if (members.length > 1) {
5342
@SuppressWarnings("removal")
5343
SecurityManager securityManager = System.getSecurityManager();
5344
if (securityManager != null) {
5345
/* All classes in a nest must be in the same runtime package and therefore same classloader */
5346
ClassLoader nestMemberClassLoader = this.internalGetClassLoader();
5347
ClassLoader callerClassLoader = ClassLoader.getCallerClassLoader();
5348
if (!doesClassLoaderDescendFrom(nestMemberClassLoader, callerClassLoader)) {
5349
String nestMemberPackageName = this.getPackageName();
5350
if ((nestMemberPackageName != null) && (nestMemberPackageName != "")) { //$NON-NLS-1$
5351
securityManager.checkPackageAccess(nestMemberPackageName);
5352
}
5353
}
5354
}
5355
}
5356
5357
return members;
5358
}
5359
/*[ENDIF] JAVA_SPEC_VERSION >= 11 */
5360
5361
/*[IF JAVA_SPEC_VERSION >= 12]*/
5362
/**
5363
* Create class of an array. The component type will be this Class instance.
5364
*
5365
* @return array class where the component type is this Class instance
5366
*/
5367
public Class<?> arrayType() {
5368
if (this == void.class) {
5369
throw new IllegalArgumentException();
5370
}
5371
return arrayTypeImpl();
5372
}
5373
5374
private native Class<?> arrayTypeImpl();
5375
5376
/**
5377
* Answers a Class object which represents the receiver's component type if the receiver
5378
* represents an array type. The component type of an array type is the type of the elements
5379
* of the array.
5380
*
5381
* @return the component type of the receiver. Returns null if the receiver does
5382
* not represent an array.
5383
*/
5384
public Class<?> componentType() {
5385
return getComponentType();
5386
}
5387
5388
/**
5389
* Returns the nominal descriptor of this Class instance, or an empty Optional
5390
* if construction is not possible.
5391
*
5392
* @return Optional with a nominal descriptor of Class instance
5393
*/
5394
public Optional<ClassDesc> describeConstable() {
5395
/*[IF JAVA_SPEC_VERSION >= 15]*/
5396
Class<?> clazz = this;
5397
if (isArray()) {
5398
clazz = getComponentType();
5399
while (clazz.isArray()) {
5400
clazz = clazz.getComponentType();
5401
}
5402
}
5403
if (clazz.isHidden()) {
5404
/* It is always an empty Optional for hidden classes. */
5405
return Optional.empty();
5406
}
5407
/*[ENDIF] JAVA_SPEC_VERSION >= 15 */
5408
5409
ClassDesc classDescriptor = ClassDesc.ofDescriptor(this.descriptorString());
5410
return Optional.of(classDescriptor);
5411
}
5412
5413
/**
5414
* Return field descriptor of Class instance.
5415
*
5416
* @return field descriptor of Class instance
5417
*/
5418
public String descriptorString() {
5419
/* see MethodTypeHelper.getBytecodeStringName */
5420
5421
if (this.isPrimitive()) {
5422
if (this == int.class) {
5423
return "I"; //$NON-NLS-1$
5424
} else if (this == long.class) {
5425
return "J"; //$NON-NLS-1$
5426
} else if (this == byte.class) {
5427
return "B"; //$NON-NLS-1$
5428
} else if (this == boolean.class) {
5429
return "Z"; //$NON-NLS-1$
5430
} else if (this == void.class) {
5431
return "V"; //$NON-NLS-1$
5432
} else if (this == char.class) {
5433
return "C"; //$NON-NLS-1$
5434
} else if (this == double.class) {
5435
return "D"; //$NON-NLS-1$
5436
} else if (this == float.class) {
5437
return "F"; //$NON-NLS-1$
5438
} else if (this == short.class) {
5439
return "S"; //$NON-NLS-1$
5440
}
5441
}
5442
String name = this.getName().replace('.', '/');
5443
/*[IF JAVA_SPEC_VERSION >= 15]*/
5444
Class<?> clazz = this;
5445
if (isArray()) {
5446
clazz = getComponentType();
5447
while (clazz.isArray()) {
5448
clazz = clazz.getComponentType();
5449
}
5450
}
5451
if (clazz.isHidden()) {
5452
/* descriptor String of hidden class is something like: "Lpackage/ClassName.romaddress;". */
5453
int index = name.lastIndexOf('/');
5454
name = name.substring(0, index)+ '.' + name.substring(index + 1,name.length());
5455
}
5456
/*[ENDIF] JAVA_SPEC_VERSION >= 15 */
5457
if (this.isArray()) {
5458
}
5459
/*[IF INLINE-TYPES]*/
5460
else if (this.isPrimitiveClass()) {
5461
name = new StringBuilder(name.length() + 2).
5462
append('Q').append(name).append(';').toString();
5463
}
5464
/*[ENDIF] INLINE-TYPES */
5465
else {
5466
name = new StringBuilder(name.length() + 2).
5467
append('L').append(name).append(';').toString();
5468
}
5469
return name;
5470
}
5471
/*[ENDIF] JAVA_SPEC_VERSION >= 12 */
5472
5473
/*[IF JAVA_SPEC_VERSION >= 14]*/
5474
/**
5475
* Returns true if the class instance is a record.
5476
*
5477
* @return true for a record class, false otherwise
5478
*/
5479
public boolean isRecord() {
5480
/*[IF JAVA_SPEC_VERSION >= 16]*/
5481
Class superclazz = getSuperclass();
5482
return ((superclazz == Record.class) && isRecordImpl());
5483
/*[ELSE] JAVA_SPEC_VERSION >= 16*/
5484
return isRecordImpl();
5485
/*[ENDIF] JAVA_SPEC_VERSION >= 16*/
5486
}
5487
5488
private native boolean isRecordImpl();
5489
5490
/**
5491
* Returns an array of RecordComponent objects for a record class.
5492
*
5493
* @return array of RecordComponent objects, one for each component in the record.
5494
* For a class that is not a record, null is returned.
5495
* For a record with no components an empty array is returned.
5496
*
5497
* @throws SecurityException if declared member access or package access is not allowed
5498
*/
5499
@CallerSensitive
5500
public RecordComponent[] getRecordComponents() {
5501
@SuppressWarnings("removal")
5502
SecurityManager security = System.getSecurityManager();
5503
if (security != null) {
5504
ClassLoader callerClassLoader = ClassLoader.getStackClassLoader(1);
5505
checkMemberAccess(security, callerClassLoader, Member.DECLARED);
5506
}
5507
5508
if (!isRecord()) {
5509
return null;
5510
}
5511
5512
return getRecordComponentsImpl();
5513
}
5514
5515
private native RecordComponent[] getRecordComponentsImpl();
5516
/*[ENDIF] JAVA_SPEC_VERSION >= 14 */
5517
5518
/*[IF JAVA_SPEC_VERSION >= 15]*/
5519
/**
5520
* Returns true if class or interface is sealed.
5521
*
5522
* @return true if class is sealed, false otherwise
5523
*/
5524
public native boolean isSealed();
5525
5526
private native boolean isHiddenImpl();
5527
/**
5528
* Returns true if the class is a hidden class.
5529
*
5530
* @return true for a hidden class, false otherwise
5531
*/
5532
public boolean isHidden() {
5533
return isHiddenImpl();
5534
}
5535
5536
/**
5537
* Returns the classData stored in the class.
5538
*
5539
* @return the classData (Object).
5540
*/
5541
Object getClassData() {
5542
return classData;
5543
}
5544
5545
private native String[] permittedSubclassesImpl();
5546
/*[ENDIF] JAVA_SPEC_VERSION >= 15 */
5547
5548
/*[IF JAVA_SPEC_VERSION >= 16]*/
5549
/**
5550
* Returns the permitted subclasses related to the calling sealed class as an array
5551
* of Class objects. If the calling class is not a sealed class, is an array class,
5552
* or is primitive, then this method returns null instead.
5553
* The order of any classes returned in the array is unspecified, and any classes
5554
* that cannot be loaded are not included in the returned array. The returned array
5555
* may be empty if there are no permitted subclasses.
5556
*
5557
* @return array of Class objects if permitted subclasses exist or null if not a sealed class.
5558
*
5559
* @throws SecurityException if access to any of the classes returned in the array is denied
5560
*
5561
* @since 16
5562
*/
5563
@CallerSensitive
5564
public Class<?>[] getPermittedSubclasses() throws SecurityException {
5565
if (!isSealed()) {
5566
return null;
5567
}
5568
Class<?>[] localPermittedSubclasses = cachedPermittedSubclasses;
5569
if (null == localPermittedSubclasses) {
5570
String[] permittedSubclassesNames = permittedSubclassesImpl();
5571
ArrayList<Class<?>> permittedSubclasses = new ArrayList<>(permittedSubclassesNames.length);
5572
5573
for (int i = 0; i < permittedSubclassesNames.length; i++) {
5574
String subclassName = permittedSubclassesNames[i];
5575
try {
5576
Class<?> permitted = forNameImpl(subclassName, false, this.classLoader);
5577
permittedSubclasses.add(permitted);
5578
} catch (ClassNotFoundException e) {
5579
// do nothing if class not found
5580
}
5581
}
5582
localPermittedSubclasses = permittedSubclasses.toArray(new Class<?>[0]);
5583
5584
long localPermittedSubclassesCacheOffset = cachedPermittedSubclassesOffset;
5585
if (-1 == localPermittedSubclassesCacheOffset) {
5586
localPermittedSubclassesCacheOffset = getUnsafe().objectFieldOffset(Class.class, "cachedPermittedSubclasses");
5587
cachedPermittedSubclassesOffset = localPermittedSubclassesCacheOffset;
5588
}
5589
getUnsafe().putObjectRelease(this, localPermittedSubclassesCacheOffset, localPermittedSubclasses);
5590
}
5591
5592
@SuppressWarnings("removal")
5593
SecurityManager sm = System.getSecurityManager();
5594
if (null != sm) {
5595
HashSet<String> packages = new HashSet<>();
5596
ClassLoader callerClassLoader = ClassLoader.getCallerClassLoader();
5597
for (int i = 0; i < localPermittedSubclasses.length; i++) {
5598
ClassLoader subClassLoader = localPermittedSubclasses[i].internalGetClassLoader();
5599
if (sun.reflect.misc.ReflectUtil.needsPackageAccessCheck(callerClassLoader, subClassLoader)) {
5600
String pkgName = localPermittedSubclasses[i].getPackageName();
5601
if ((pkgName != null) && (pkgName != "")) {
5602
packages.add(pkgName);
5603
}
5604
}
5605
}
5606
for (String pkgName : packages) {
5607
sm.checkPackageAccess(pkgName);
5608
}
5609
}
5610
5611
return localPermittedSubclasses;
5612
}
5613
/*[ENDIF] JAVA_SPEC_VERSION >= 16 */
5614
5615
/*[IF JAVA_SPEC_VERSION >= 11]*/
5616
@SuppressWarnings("removal")
5617
private static ReflectionFactory getReflectionFactory() {
5618
if (reflectionFactory == null) {
5619
reflectionFactory = AccessController.doPrivileged(new ReflectionFactory.GetReflectionFactoryAction());
5620
}
5621
return reflectionFactory;
5622
}
5623
/*[ENDIF] JAVA_SPEC_VERSION >= 11 */
5624
5625
}
5626
5627