Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/openjdk-multiarch-jdk8u
Path: blob/aarch64-shenandoah-jdk8u272-b10/jdk/src/share/classes/sun/reflect/ReflectionFactory.java
38829 views
1
/*
2
* Copyright (c) 2001, 2013, Oracle and/or its affiliates. All rights reserved.
3
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4
*
5
* This code is free software; you can redistribute it and/or modify it
6
* under the terms of the GNU General Public License version 2 only, as
7
* published by the Free Software Foundation. Oracle designates this
8
* particular file as subject to the "Classpath" exception as provided
9
* by Oracle in the LICENSE file that accompanied this code.
10
*
11
* This code is distributed in the hope that it will be useful, but WITHOUT
12
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14
* version 2 for more details (a copy is included in the LICENSE file that
15
* accompanied this code).
16
*
17
* You should have received a copy of the GNU General Public License version
18
* 2 along with this work; if not, write to the Free Software Foundation,
19
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20
*
21
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22
* or visit www.oracle.com if you need additional information or have any
23
* questions.
24
*/
25
26
package sun.reflect;
27
28
import java.io.Externalizable;
29
import java.io.ObjectInputStream;
30
import java.io.ObjectOutputStream;
31
import java.io.ObjectStreamClass;
32
import java.io.OptionalDataException;
33
import java.io.Serializable;
34
import java.lang.invoke.MethodHandle;
35
import java.lang.invoke.MethodHandles;
36
import java.lang.reflect.Field;
37
import java.lang.reflect.Executable;
38
import java.lang.reflect.InvocationTargetException;
39
import java.lang.reflect.Method;
40
import java.lang.reflect.Constructor;
41
import java.lang.reflect.Modifier;
42
import java.security.AccessController;
43
import java.security.Permission;
44
import java.security.PrivilegedAction;
45
import java.util.Objects;
46
47
import sun.reflect.misc.ReflectUtil;
48
49
50
/** <P> The master factory for all reflective objects, both those in
51
java.lang.reflect (Fields, Methods, Constructors) as well as their
52
delegates (FieldAccessors, MethodAccessors, ConstructorAccessors).
53
</P>
54
55
<P> The methods in this class are extremely unsafe and can cause
56
subversion of both the language and the verifier. For this reason,
57
they are all instance methods, and access to the constructor of
58
this factory is guarded by a security check, in similar style to
59
{@link sun.misc.Unsafe}. </P>
60
*/
61
62
public class ReflectionFactory {
63
64
private static boolean initted = false;
65
private static final Permission reflectionFactoryAccessPerm
66
= new RuntimePermission("reflectionFactoryAccess");
67
private static final ReflectionFactory soleInstance = new ReflectionFactory();
68
// Provides access to package-private mechanisms in java.lang.reflect
69
private static volatile LangReflectAccess langReflectAccess;
70
71
/* Method for static class initializer <clinit>, or null */
72
private static volatile Method hasStaticInitializerMethod;
73
74
//
75
// "Inflation" mechanism. Loading bytecodes to implement
76
// Method.invoke() and Constructor.newInstance() currently costs
77
// 3-4x more than an invocation via native code for the first
78
// invocation (though subsequent invocations have been benchmarked
79
// to be over 20x faster). Unfortunately this cost increases
80
// startup time for certain applications that use reflection
81
// intensively (but only once per class) to bootstrap themselves.
82
// To avoid this penalty we reuse the existing JVM entry points
83
// for the first few invocations of Methods and Constructors and
84
// then switch to the bytecode-based implementations.
85
//
86
// Package-private to be accessible to NativeMethodAccessorImpl
87
// and NativeConstructorAccessorImpl
88
private static boolean noInflation = false;
89
private static int inflationThreshold = 15;
90
91
private ReflectionFactory() {}
92
93
/**
94
* A convenience class for acquiring the capability to instantiate
95
* reflective objects. Use this instead of a raw call to {@link
96
* #getReflectionFactory} in order to avoid being limited by the
97
* permissions of your callers.
98
*
99
* <p>An instance of this class can be used as the argument of
100
* <code>AccessController.doPrivileged</code>.
101
*/
102
public static final class GetReflectionFactoryAction
103
implements PrivilegedAction<ReflectionFactory> {
104
public ReflectionFactory run() {
105
return getReflectionFactory();
106
}
107
}
108
109
/**
110
* Provides the caller with the capability to instantiate reflective
111
* objects.
112
*
113
* <p> First, if there is a security manager, its
114
* <code>checkPermission</code> method is called with a {@link
115
* java.lang.RuntimePermission} with target
116
* <code>"reflectionFactoryAccess"</code>. This may result in a
117
* security exception.
118
*
119
* <p> The returned <code>ReflectionFactory</code> object should be
120
* carefully guarded by the caller, since it can be used to read and
121
* write private data and invoke private methods, as well as to load
122
* unverified bytecodes. It must never be passed to untrusted code.
123
*
124
* @exception SecurityException if a security manager exists and its
125
* <code>checkPermission</code> method doesn't allow
126
* access to the RuntimePermission "reflectionFactoryAccess". */
127
public static ReflectionFactory getReflectionFactory() {
128
SecurityManager security = System.getSecurityManager();
129
if (security != null) {
130
// TO DO: security.checkReflectionFactoryAccess();
131
security.checkPermission(reflectionFactoryAccessPerm);
132
}
133
return soleInstance;
134
}
135
136
//--------------------------------------------------------------------------
137
//
138
// Routines used by java.lang.reflect
139
//
140
//
141
142
/** Called only by java.lang.reflect.Modifier's static initializer */
143
public void setLangReflectAccess(LangReflectAccess access) {
144
langReflectAccess = access;
145
}
146
147
/**
148
* Note: this routine can cause the declaring class for the field
149
* be initialized and therefore must not be called until the
150
* first get/set of this field.
151
* @param field the field
152
* @param override true if caller has overridden aaccessibility
153
*/
154
public FieldAccessor newFieldAccessor(Field field, boolean override) {
155
checkInitted();
156
return UnsafeFieldAccessorFactory.newFieldAccessor(field, override);
157
}
158
159
public MethodAccessor newMethodAccessor(Method method) {
160
checkInitted();
161
162
if (noInflation && !ReflectUtil.isVMAnonymousClass(method.getDeclaringClass())) {
163
return new MethodAccessorGenerator().
164
generateMethod(method.getDeclaringClass(),
165
method.getName(),
166
method.getParameterTypes(),
167
method.getReturnType(),
168
method.getExceptionTypes(),
169
method.getModifiers());
170
} else {
171
NativeMethodAccessorImpl acc =
172
new NativeMethodAccessorImpl(method);
173
DelegatingMethodAccessorImpl res =
174
new DelegatingMethodAccessorImpl(acc);
175
acc.setParent(res);
176
return res;
177
}
178
}
179
180
public ConstructorAccessor newConstructorAccessor(Constructor<?> c) {
181
checkInitted();
182
183
Class<?> declaringClass = c.getDeclaringClass();
184
if (Modifier.isAbstract(declaringClass.getModifiers())) {
185
return new InstantiationExceptionConstructorAccessorImpl(null);
186
}
187
if (declaringClass == Class.class) {
188
return new InstantiationExceptionConstructorAccessorImpl
189
("Can not instantiate java.lang.Class");
190
}
191
// Bootstrapping issue: since we use Class.newInstance() in
192
// the ConstructorAccessor generation process, we have to
193
// break the cycle here.
194
if (Reflection.isSubclassOf(declaringClass,
195
ConstructorAccessorImpl.class)) {
196
return new BootstrapConstructorAccessorImpl(c);
197
}
198
199
if (noInflation && !ReflectUtil.isVMAnonymousClass(c.getDeclaringClass())) {
200
return new MethodAccessorGenerator().
201
generateConstructor(c.getDeclaringClass(),
202
c.getParameterTypes(),
203
c.getExceptionTypes(),
204
c.getModifiers());
205
} else {
206
NativeConstructorAccessorImpl acc =
207
new NativeConstructorAccessorImpl(c);
208
DelegatingConstructorAccessorImpl res =
209
new DelegatingConstructorAccessorImpl(acc);
210
acc.setParent(res);
211
return res;
212
}
213
}
214
215
//--------------------------------------------------------------------------
216
//
217
// Routines used by java.lang
218
//
219
//
220
221
/** Creates a new java.lang.reflect.Field. Access checks as per
222
java.lang.reflect.AccessibleObject are not overridden. */
223
public Field newField(Class<?> declaringClass,
224
String name,
225
Class<?> type,
226
int modifiers,
227
int slot,
228
String signature,
229
byte[] annotations)
230
{
231
return langReflectAccess().newField(declaringClass,
232
name,
233
type,
234
modifiers,
235
slot,
236
signature,
237
annotations);
238
}
239
240
/** Creates a new java.lang.reflect.Method. Access checks as per
241
java.lang.reflect.AccessibleObject are not overridden. */
242
public Method newMethod(Class<?> declaringClass,
243
String name,
244
Class<?>[] parameterTypes,
245
Class<?> returnType,
246
Class<?>[] checkedExceptions,
247
int modifiers,
248
int slot,
249
String signature,
250
byte[] annotations,
251
byte[] parameterAnnotations,
252
byte[] annotationDefault)
253
{
254
return langReflectAccess().newMethod(declaringClass,
255
name,
256
parameterTypes,
257
returnType,
258
checkedExceptions,
259
modifiers,
260
slot,
261
signature,
262
annotations,
263
parameterAnnotations,
264
annotationDefault);
265
}
266
267
/** Creates a new java.lang.reflect.Constructor. Access checks as
268
per java.lang.reflect.AccessibleObject are not overridden. */
269
public Constructor<?> newConstructor(Class<?> declaringClass,
270
Class<?>[] parameterTypes,
271
Class<?>[] checkedExceptions,
272
int modifiers,
273
int slot,
274
String signature,
275
byte[] annotations,
276
byte[] parameterAnnotations)
277
{
278
return langReflectAccess().newConstructor(declaringClass,
279
parameterTypes,
280
checkedExceptions,
281
modifiers,
282
slot,
283
signature,
284
annotations,
285
parameterAnnotations);
286
}
287
288
/** Gets the MethodAccessor object for a java.lang.reflect.Method */
289
public MethodAccessor getMethodAccessor(Method m) {
290
return langReflectAccess().getMethodAccessor(m);
291
}
292
293
/** Sets the MethodAccessor object for a java.lang.reflect.Method */
294
public void setMethodAccessor(Method m, MethodAccessor accessor) {
295
langReflectAccess().setMethodAccessor(m, accessor);
296
}
297
298
/** Gets the ConstructorAccessor object for a
299
java.lang.reflect.Constructor */
300
public ConstructorAccessor getConstructorAccessor(Constructor<?> c) {
301
return langReflectAccess().getConstructorAccessor(c);
302
}
303
304
/** Sets the ConstructorAccessor object for a
305
java.lang.reflect.Constructor */
306
public void setConstructorAccessor(Constructor<?> c,
307
ConstructorAccessor accessor)
308
{
309
langReflectAccess().setConstructorAccessor(c, accessor);
310
}
311
312
/** Makes a copy of the passed method. The returned method is a
313
"child" of the passed one; see the comments in Method.java for
314
details. */
315
public Method copyMethod(Method arg) {
316
return langReflectAccess().copyMethod(arg);
317
}
318
319
/** Makes a copy of the passed field. The returned field is a
320
"child" of the passed one; see the comments in Field.java for
321
details. */
322
public Field copyField(Field arg) {
323
return langReflectAccess().copyField(arg);
324
}
325
326
/** Makes a copy of the passed constructor. The returned
327
constructor is a "child" of the passed one; see the comments
328
in Constructor.java for details. */
329
public <T> Constructor<T> copyConstructor(Constructor<T> arg) {
330
return langReflectAccess().copyConstructor(arg);
331
}
332
333
/** Gets the byte[] that encodes TypeAnnotations on an executable.
334
*/
335
public byte[] getExecutableTypeAnnotationBytes(Executable ex) {
336
return langReflectAccess().getExecutableTypeAnnotationBytes(ex);
337
}
338
339
//--------------------------------------------------------------------------
340
//
341
// Routines used by serialization
342
//
343
//
344
345
/**
346
* Returns an accessible constructor capable of creating instances
347
* of the given class, initialized by the given constructor.
348
*
349
* @param classToInstantiate the class to instantiate
350
* @param constructorToCall the constructor to call
351
* @return an accessible constructor
352
*/
353
public Constructor<?> newConstructorForSerialization
354
(Class<?> classToInstantiate, Constructor<?> constructorToCall)
355
{
356
// Fast path
357
if (constructorToCall.getDeclaringClass() == classToInstantiate) {
358
return constructorToCall;
359
}
360
return generateConstructor(classToInstantiate, constructorToCall);
361
}
362
363
/**
364
* Returns an accessible no-arg constructor for a class.
365
* The no-arg constructor is found searching the class and its supertypes.
366
*
367
* @param cl the class to instantiate
368
* @return a no-arg constructor for the class or {@code null} if
369
* the class or supertypes do not have a suitable no-arg constructor
370
*/
371
public final Constructor<?> newConstructorForSerialization(Class<?> cl) {
372
Class<?> initCl = cl;
373
while (Serializable.class.isAssignableFrom(initCl)) {
374
if ((initCl = initCl.getSuperclass()) == null) {
375
return null;
376
}
377
}
378
Constructor<?> constructorToCall;
379
try {
380
constructorToCall = initCl.getDeclaredConstructor();
381
int mods = constructorToCall.getModifiers();
382
if ((mods & Modifier.PRIVATE) != 0 ||
383
((mods & (Modifier.PUBLIC | Modifier.PROTECTED)) == 0 &&
384
!packageEquals(cl, initCl))) {
385
return null;
386
}
387
} catch (NoSuchMethodException ex) {
388
return null;
389
}
390
return generateConstructor(cl, constructorToCall);
391
}
392
393
private final Constructor<?> generateConstructor(Class<?> classToInstantiate,
394
Constructor<?> constructorToCall) {
395
396
397
ConstructorAccessor acc = new MethodAccessorGenerator().
398
generateSerializationConstructor(classToInstantiate,
399
constructorToCall.getParameterTypes(),
400
constructorToCall.getExceptionTypes(),
401
constructorToCall.getModifiers(),
402
constructorToCall.getDeclaringClass());
403
Constructor<?> c = newConstructor(constructorToCall.getDeclaringClass(),
404
constructorToCall.getParameterTypes(),
405
constructorToCall.getExceptionTypes(),
406
constructorToCall.getModifiers(),
407
langReflectAccess().
408
getConstructorSlot(constructorToCall),
409
langReflectAccess().
410
getConstructorSignature(constructorToCall),
411
langReflectAccess().
412
getConstructorAnnotations(constructorToCall),
413
langReflectAccess().
414
getConstructorParameterAnnotations(constructorToCall));
415
setConstructorAccessor(c, acc);
416
c.setAccessible(true);
417
return c;
418
}
419
420
/**
421
* Returns an accessible no-arg constructor for an externalizable class to be
422
* initialized using a public no-argument constructor.
423
*
424
* @param cl the class to instantiate
425
* @return A no-arg constructor for the class; returns {@code null} if
426
* the class does not implement {@link java.io.Externalizable}
427
*/
428
public final Constructor<?> newConstructorForExternalization(Class<?> cl) {
429
if (!Externalizable.class.isAssignableFrom(cl)) {
430
return null;
431
}
432
try {
433
Constructor<?> cons = cl.getConstructor();
434
cons.setAccessible(true);
435
return cons;
436
} catch (NoSuchMethodException ex) {
437
return null;
438
}
439
}
440
441
/**
442
* Returns a direct MethodHandle for the {@code readObject} method on
443
* a Serializable class.
444
* The first argument of {@link MethodHandle#invoke} is the serializable
445
* object and the second argument is the {@code ObjectInputStream} passed to
446
* {@code readObject}.
447
*
448
* @param cl a Serializable class
449
* @return a direct MethodHandle for the {@code readObject} method of the class or
450
* {@code null} if the class does not have a {@code readObject} method
451
*/
452
public final MethodHandle readObjectForSerialization(Class<?> cl) {
453
return findReadWriteObjectForSerialization(cl, "readObject", ObjectInputStream.class);
454
}
455
456
/**
457
* Returns a direct MethodHandle for the {@code readObjectNoData} method on
458
* a Serializable class.
459
* The first argument of {@link MethodHandle#invoke} is the serializable
460
* object and the second argument is the {@code ObjectInputStream} passed to
461
* {@code readObjectNoData}.
462
*
463
* @param cl a Serializable class
464
* @return a direct MethodHandle for the {@code readObjectNoData} method
465
* of the class or {@code null} if the class does not have a
466
* {@code readObjectNoData} method
467
*/
468
public final MethodHandle readObjectNoDataForSerialization(Class<?> cl) {
469
return findReadWriteObjectForSerialization(cl, "readObjectNoData", ObjectInputStream.class);
470
}
471
472
/**
473
* Returns a direct MethodHandle for the {@code writeObject} method on
474
* a Serializable class.
475
* The first argument of {@link MethodHandle#invoke} is the serializable
476
* object and the second argument is the {@code ObjectOutputStream} passed to
477
* {@code writeObject}.
478
*
479
* @param cl a Serializable class
480
* @return a direct MethodHandle for the {@code writeObject} method of the class or
481
* {@code null} if the class does not have a {@code writeObject} method
482
*/
483
public final MethodHandle writeObjectForSerialization(Class<?> cl) {
484
return findReadWriteObjectForSerialization(cl, "writeObject", ObjectOutputStream.class);
485
}
486
487
private final MethodHandle findReadWriteObjectForSerialization(Class<?> cl,
488
String methodName,
489
Class<?> streamClass) {
490
if (!Serializable.class.isAssignableFrom(cl)) {
491
return null;
492
}
493
494
try {
495
Method meth = cl.getDeclaredMethod(methodName, streamClass);
496
int mods = meth.getModifiers();
497
if (meth.getReturnType() != Void.TYPE ||
498
Modifier.isStatic(mods) ||
499
!Modifier.isPrivate(mods)) {
500
return null;
501
}
502
meth.setAccessible(true);
503
return MethodHandles.lookup().unreflect(meth);
504
} catch (NoSuchMethodException ex) {
505
return null;
506
} catch (IllegalAccessException ex1) {
507
throw new InternalError("Error", ex1);
508
}
509
}
510
511
/**
512
* Returns a direct MethodHandle for the {@code readResolve} method on
513
* a serializable class.
514
* The single argument of {@link MethodHandle#invoke} is the serializable
515
* object.
516
*
517
* @param cl the Serializable class
518
* @return a direct MethodHandle for the {@code readResolve} method of the class or
519
* {@code null} if the class does not have a {@code readResolve} method
520
*/
521
public final MethodHandle readResolveForSerialization(Class<?> cl) {
522
return getReplaceResolveForSerialization(cl, "readResolve");
523
}
524
525
/**
526
* Returns a direct MethodHandle for the {@code writeReplace} method on
527
* a serializable class.
528
* The single argument of {@link MethodHandle#invoke} is the serializable
529
* object.
530
*
531
* @param cl the Serializable class
532
* @return a direct MethodHandle for the {@code writeReplace} method of the class or
533
* {@code null} if the class does not have a {@code writeReplace} method
534
*/
535
public final MethodHandle writeReplaceForSerialization(Class<?> cl) {
536
return getReplaceResolveForSerialization(cl, "writeReplace");
537
}
538
539
/**
540
* Returns a direct MethodHandle for the {@code writeReplace} method on
541
* a serializable class.
542
* The single argument of {@link MethodHandle#invoke} is the serializable
543
* object.
544
*
545
* @param cl the Serializable class
546
* @return a direct MethodHandle for the {@code writeReplace} method of the class or
547
* {@code null} if the class does not have a {@code writeReplace} method
548
*/
549
private MethodHandle getReplaceResolveForSerialization(Class<?> cl,
550
String methodName) {
551
if (!Serializable.class.isAssignableFrom(cl)) {
552
return null;
553
}
554
555
Class<?> defCl = cl;
556
while (defCl != null) {
557
try {
558
Method m = defCl.getDeclaredMethod(methodName);
559
if (m.getReturnType() != Object.class) {
560
return null;
561
}
562
int mods = m.getModifiers();
563
if (Modifier.isStatic(mods) | Modifier.isAbstract(mods)) {
564
return null;
565
} else if (Modifier.isPublic(mods) | Modifier.isProtected(mods)) {
566
// fall through
567
} else if (Modifier.isPrivate(mods) && (cl != defCl)) {
568
return null;
569
} else if (!packageEquals(cl, defCl)) {
570
return null;
571
}
572
try {
573
// Normal return
574
m.setAccessible(true);
575
return MethodHandles.lookup().unreflect(m);
576
} catch (IllegalAccessException ex0) {
577
// setAccessible should prevent IAE
578
throw new InternalError("Error", ex0);
579
}
580
} catch (NoSuchMethodException ex) {
581
defCl = defCl.getSuperclass();
582
}
583
}
584
return null;
585
}
586
587
/**
588
* Returns true if the class has a static initializer.
589
* The presence of a static initializer is used to compute the serialVersionUID.
590
* @param cl a serializable classLook
591
* @return {@code true} if the class has a static initializer,
592
* otherwise {@code false}
593
*/
594
public final boolean hasStaticInitializerForSerialization(Class<?> cl) {
595
Method m = hasStaticInitializerMethod;
596
if (m == null) {
597
try {
598
m = ObjectStreamClass.class.getDeclaredMethod("hasStaticInitializer",
599
new Class<?>[]{Class.class});
600
m.setAccessible(true);
601
hasStaticInitializerMethod = m;
602
} catch (NoSuchMethodException ex) {
603
throw new InternalError("No such method hasStaticInitializer on "
604
+ ObjectStreamClass.class, ex);
605
}
606
}
607
try {
608
return (Boolean) m.invoke(null, cl);
609
} catch (InvocationTargetException | IllegalAccessException ex) {
610
throw new InternalError("Exception invoking hasStaticInitializer", ex);
611
}
612
}
613
614
/**
615
* Returns a new OptionalDataException with {@code eof} set to {@code true}
616
* or {@code false}.
617
* @param bool the value of {@code eof} in the created OptionalDataException
618
* @return a new OptionalDataException
619
*/
620
public final OptionalDataException newOptionalDataExceptionForSerialization(boolean bool) {
621
try {
622
Constructor<OptionalDataException> boolCtor =
623
OptionalDataException.class.getDeclaredConstructor(Boolean.TYPE);
624
boolCtor.setAccessible(true);
625
return boolCtor.newInstance(bool);
626
} catch (NoSuchMethodException | InstantiationException|
627
IllegalAccessException|InvocationTargetException ex) {
628
throw new InternalError("unable to create OptionalDataException", ex);
629
}
630
}
631
632
//--------------------------------------------------------------------------
633
//
634
// Internals only below this point
635
//
636
637
static int inflationThreshold() {
638
return inflationThreshold;
639
}
640
641
/** We have to defer full initialization of this class until after
642
the static initializer is run since java.lang.reflect.Method's
643
static initializer (more properly, that for
644
java.lang.reflect.AccessibleObject) causes this class's to be
645
run, before the system properties are set up. */
646
private static void checkInitted() {
647
if (initted) return;
648
AccessController.doPrivileged(
649
new PrivilegedAction<Void>() {
650
public Void run() {
651
// Tests to ensure the system properties table is fully
652
// initialized. This is needed because reflection code is
653
// called very early in the initialization process (before
654
// command-line arguments have been parsed and therefore
655
// these user-settable properties installed.) We assume that
656
// if System.out is non-null then the System class has been
657
// fully initialized and that the bulk of the startup code
658
// has been run.
659
660
if (System.out == null) {
661
// java.lang.System not yet fully initialized
662
return null;
663
}
664
665
String val = System.getProperty("sun.reflect.noInflation");
666
if (val != null && val.equals("true")) {
667
noInflation = true;
668
}
669
670
val = System.getProperty("sun.reflect.inflationThreshold");
671
if (val != null) {
672
try {
673
inflationThreshold = Integer.parseInt(val);
674
} catch (NumberFormatException e) {
675
throw new RuntimeException("Unable to parse property sun.reflect.inflationThreshold", e);
676
}
677
}
678
679
initted = true;
680
return null;
681
}
682
});
683
}
684
685
private static LangReflectAccess langReflectAccess() {
686
if (langReflectAccess == null) {
687
// Call a static method to get class java.lang.reflect.Modifier
688
// initialized. Its static initializer will cause
689
// setLangReflectAccess() to be called from the context of the
690
// java.lang.reflect package.
691
Modifier.isPublic(Modifier.PUBLIC);
692
}
693
return langReflectAccess;
694
}
695
696
/**
697
* Returns true if classes are defined in the classloader and same package, false
698
* otherwise.
699
* @param cl1 a class
700
* @param cl2 another class
701
* @returns true if the two classes are in the same classloader and package
702
*/
703
private static boolean packageEquals(Class<?> cl1, Class<?> cl2) {
704
return cl1.getClassLoader() == cl2.getClassLoader() &&
705
Objects.equals(cl1.getPackage(), cl2.getPackage());
706
}
707
708
}
709
710