Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/mobile
Path: blob/master/src/java.base/share/classes/jdk/internal/reflect/Reflection.java
41159 views
1
/*
2
* Copyright (c) 2001, 2020, 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 jdk.internal.reflect;
27
28
import java.lang.reflect.*;
29
import java.util.HashMap;
30
import java.util.Map;
31
import java.util.Objects;
32
import java.util.Set;
33
import jdk.internal.access.SharedSecrets;
34
import jdk.internal.misc.VM;
35
import jdk.internal.vm.annotation.IntrinsicCandidate;
36
37
/** Common utility routines used by both java.lang and
38
java.lang.reflect */
39
40
public class Reflection {
41
42
/** Used to filter out fields and methods from certain classes from public
43
view, where they are sensitive or they may contain VM-internal objects.
44
These Maps are updated very rarely. Rather than synchronize on
45
each access, we use copy-on-write */
46
private static volatile Map<Class<?>, Set<String>> fieldFilterMap;
47
private static volatile Map<Class<?>, Set<String>> methodFilterMap;
48
private static final String WILDCARD = "*";
49
public static final Set<String> ALL_MEMBERS = Set.of(WILDCARD);
50
51
static {
52
fieldFilterMap = Map.of(
53
Reflection.class, ALL_MEMBERS,
54
AccessibleObject.class, ALL_MEMBERS,
55
Class.class, Set.of("classLoader", "classData"),
56
ClassLoader.class, ALL_MEMBERS,
57
Constructor.class, ALL_MEMBERS,
58
Field.class, ALL_MEMBERS,
59
Method.class, ALL_MEMBERS,
60
Module.class, ALL_MEMBERS,
61
System.class, Set.of("security")
62
);
63
methodFilterMap = Map.of();
64
}
65
66
/** Returns the class of the caller of the method calling this method,
67
ignoring frames associated with java.lang.reflect.Method.invoke()
68
and its implementation. */
69
@CallerSensitive
70
@IntrinsicCandidate
71
public static native Class<?> getCallerClass();
72
73
/** Retrieves the access flags written to the class file. For
74
inner classes these flags may differ from those returned by
75
Class.getModifiers(), which searches the InnerClasses
76
attribute to find the source-level access flags. This is used
77
instead of Class.getModifiers() for run-time access checks due
78
to compatibility reasons; see 4471811. Only the values of the
79
low 13 bits (i.e., a mask of 0x1FFF) are guaranteed to be
80
valid. */
81
@IntrinsicCandidate
82
public static native int getClassAccessFlags(Class<?> c);
83
84
85
/**
86
* Ensures that access to a member is granted and throws
87
* IllegalAccessException if not.
88
*
89
* @param currentClass the class performing the access
90
* @param memberClass the declaring class of the member being accessed
91
* @param targetClass the class of target object if accessing instance
92
* field or method;
93
* or the declaring class if accessing constructor;
94
* or null if accessing static field or method
95
* @param modifiers the member's access modifiers
96
* @throws IllegalAccessException if access to member is denied
97
*/
98
public static void ensureMemberAccess(Class<?> currentClass,
99
Class<?> memberClass,
100
Class<?> targetClass,
101
int modifiers)
102
throws IllegalAccessException
103
{
104
if (!verifyMemberAccess(currentClass, memberClass, targetClass, modifiers)) {
105
throw newIllegalAccessException(currentClass, memberClass, targetClass, modifiers);
106
}
107
}
108
109
public static void ensureNativeAccess(Class<?> currentClass) {
110
Module module = currentClass.getModule();
111
if (!SharedSecrets.getJavaLangAccess().isEnableNativeAccess(module)) {
112
throw new IllegalCallerException("Illegal native access from: " + module);
113
}
114
}
115
116
/**
117
* Verify access to a member and return {@code true} if it is granted.
118
*
119
* @param currentClass the class performing the access
120
* @param memberClass the declaring class of the member being accessed
121
* @param targetClass the class of target object if accessing instance
122
* field or method;
123
* or the declaring class if accessing constructor;
124
* or null if accessing static field or method
125
* @param modifiers the member's access modifiers
126
* @return {@code true} if access to member is granted
127
*/
128
public static boolean verifyMemberAccess(Class<?> currentClass,
129
Class<?> memberClass,
130
Class<?> targetClass,
131
int modifiers)
132
{
133
Objects.requireNonNull(currentClass);
134
Objects.requireNonNull(memberClass);
135
136
if (currentClass == memberClass) {
137
// Always succeeds
138
return true;
139
}
140
141
if (!verifyModuleAccess(currentClass.getModule(), memberClass)) {
142
return false;
143
}
144
145
boolean gotIsSameClassPackage = false;
146
boolean isSameClassPackage = false;
147
148
if (!Modifier.isPublic(getClassAccessFlags(memberClass))) {
149
isSameClassPackage = isSameClassPackage(currentClass, memberClass);
150
gotIsSameClassPackage = true;
151
if (!isSameClassPackage) {
152
return false;
153
}
154
}
155
156
// At this point we know that currentClass can access memberClass.
157
158
if (Modifier.isPublic(modifiers)) {
159
return true;
160
}
161
162
// Check for nestmate access if member is private
163
if (Modifier.isPrivate(modifiers)) {
164
// Note: targetClass may be outside the nest, but that is okay
165
// as long as memberClass is in the nest.
166
if (areNestMates(currentClass, memberClass)) {
167
return true;
168
}
169
}
170
171
boolean successSoFar = false;
172
173
if (Modifier.isProtected(modifiers)) {
174
// See if currentClass is a subclass of memberClass
175
if (isSubclassOf(currentClass, memberClass)) {
176
successSoFar = true;
177
}
178
}
179
180
if (!successSoFar && !Modifier.isPrivate(modifiers)) {
181
if (!gotIsSameClassPackage) {
182
isSameClassPackage = isSameClassPackage(currentClass,
183
memberClass);
184
gotIsSameClassPackage = true;
185
}
186
187
if (isSameClassPackage) {
188
successSoFar = true;
189
}
190
}
191
192
if (!successSoFar) {
193
return false;
194
}
195
196
// Additional test for protected instance members
197
// and protected constructors: JLS 6.6.2
198
if (targetClass != null && Modifier.isProtected(modifiers) &&
199
targetClass != currentClass)
200
{
201
if (!gotIsSameClassPackage) {
202
isSameClassPackage = isSameClassPackage(currentClass, memberClass);
203
gotIsSameClassPackage = true;
204
}
205
if (!isSameClassPackage) {
206
if (!isSubclassOf(targetClass, currentClass)) {
207
return false;
208
}
209
}
210
}
211
212
return true;
213
}
214
215
/*
216
* Verify if a member is public and memberClass is a public type
217
* in a package that is unconditionally exported and
218
* return {@code true} if it is granted.
219
*
220
* @param memberClass the declaring class of the member being accessed
221
* @param modifiers the member's access modifiers
222
* @return {@code true} if the member is public and in a publicly accessible type
223
*/
224
public static boolean verifyPublicMemberAccess(Class<?> memberClass, int modifiers) {
225
Module m = memberClass.getModule();
226
return Modifier.isPublic(modifiers)
227
&& m.isExported(memberClass.getPackageName())
228
&& Modifier.isPublic(Reflection.getClassAccessFlags(memberClass));
229
}
230
231
/**
232
* Returns {@code true} if memberClass's module exports memberClass's
233
* package to currentModule.
234
*/
235
public static boolean verifyModuleAccess(Module currentModule, Class<?> memberClass) {
236
Module memberModule = memberClass.getModule();
237
if (currentModule == memberModule) {
238
// same module (named or unnamed) or both null if called
239
// before module system is initialized, which means we are
240
// dealing with java.base only.
241
return true;
242
} else {
243
String pkg = memberClass.getPackageName();
244
return memberModule.isExported(pkg, currentModule);
245
}
246
}
247
248
/**
249
* Returns true if two classes in the same package.
250
*/
251
private static boolean isSameClassPackage(Class<?> c1, Class<?> c2) {
252
if (c1.getClassLoader() != c2.getClassLoader())
253
return false;
254
return Objects.equals(c1.getPackageName(), c2.getPackageName());
255
}
256
257
static boolean isSubclassOf(Class<?> queryClass,
258
Class<?> ofClass)
259
{
260
while (queryClass != null) {
261
if (queryClass == ofClass) {
262
return true;
263
}
264
queryClass = queryClass.getSuperclass();
265
}
266
return false;
267
}
268
269
// fieldNames must contain only interned Strings
270
public static synchronized void registerFieldsToFilter(Class<?> containingClass,
271
Set<String> fieldNames) {
272
fieldFilterMap =
273
registerFilter(fieldFilterMap, containingClass, fieldNames);
274
}
275
276
// methodNames must contain only interned Strings
277
public static synchronized void registerMethodsToFilter(Class<?> containingClass,
278
Set<String> methodNames) {
279
methodFilterMap =
280
registerFilter(methodFilterMap, containingClass, methodNames);
281
}
282
283
private static Map<Class<?>, Set<String>> registerFilter(Map<Class<?>, Set<String>> map,
284
Class<?> containingClass,
285
Set<String> names) {
286
if (map.get(containingClass) != null) {
287
throw new IllegalArgumentException
288
("Filter already registered: " + containingClass);
289
}
290
map = new HashMap<>(map);
291
map.put(containingClass, Set.copyOf(names));
292
return map;
293
}
294
295
public static Field[] filterFields(Class<?> containingClass, Field[] fields) {
296
if (fieldFilterMap == null) {
297
// Bootstrapping
298
return fields;
299
}
300
return (Field[])filter(fields, fieldFilterMap.get(containingClass));
301
}
302
303
public static Method[] filterMethods(Class<?> containingClass, Method[] methods) {
304
if (methodFilterMap == null) {
305
// Bootstrapping
306
return methods;
307
}
308
return (Method[])filter(methods, methodFilterMap.get(containingClass));
309
}
310
311
private static Member[] filter(Member[] members, Set<String> filteredNames) {
312
if ((filteredNames == null) || (members.length == 0)) {
313
return members;
314
}
315
Class<?> memberType = members[0].getClass();
316
if (filteredNames.contains(WILDCARD)) {
317
return (Member[]) Array.newInstance(memberType, 0);
318
}
319
int numNewMembers = 0;
320
for (Member member : members) {
321
if (!filteredNames.contains(member.getName())) {
322
++numNewMembers;
323
}
324
}
325
Member[] newMembers = (Member[])Array.newInstance(memberType, numNewMembers);
326
int destIdx = 0;
327
for (Member member : members) {
328
if (!filteredNames.contains(member.getName())) {
329
newMembers[destIdx++] = member;
330
}
331
}
332
return newMembers;
333
}
334
335
/**
336
* Tests if the given method is caller-sensitive and the declaring class
337
* is defined by either the bootstrap class loader or platform class loader.
338
*/
339
public static boolean isCallerSensitive(Method m) {
340
final ClassLoader loader = m.getDeclaringClass().getClassLoader();
341
if (VM.isSystemDomainLoader(loader)) {
342
return m.isAnnotationPresent(CallerSensitive.class);
343
}
344
return false;
345
}
346
347
/*
348
* Tests if the given Field is a trusted final field and it cannot be
349
* modified reflectively regardless of the value of its accessible flag.
350
*/
351
public static boolean isTrustedFinalField(Field field) {
352
return SharedSecrets.getJavaLangReflectAccess().isTrustedFinalField(field);
353
}
354
355
/**
356
* Returns an IllegalAccessException with an exception message based on
357
* the access that is denied.
358
*/
359
public static IllegalAccessException newIllegalAccessException(Class<?> currentClass,
360
Class<?> memberClass,
361
Class<?> targetClass,
362
int modifiers)
363
{
364
if (currentClass == null)
365
return newIllegalAccessException(memberClass, modifiers);
366
367
String currentSuffix = "";
368
String memberSuffix = "";
369
Module m1 = currentClass.getModule();
370
if (m1.isNamed())
371
currentSuffix = " (in " + m1 + ")";
372
Module m2 = memberClass.getModule();
373
if (m2.isNamed())
374
memberSuffix = " (in " + m2 + ")";
375
376
String memberPackageName = memberClass.getPackageName();
377
378
String msg = currentClass + currentSuffix + " cannot access ";
379
if (m2.isExported(memberPackageName, m1)) {
380
381
// module access okay so include the modifiers in the message
382
msg += "a member of " + memberClass + memberSuffix +
383
" with modifiers \"" + Modifier.toString(modifiers) + "\"";
384
385
} else {
386
// module access failed
387
msg += memberClass + memberSuffix+ " because "
388
+ m2 + " does not export " + memberPackageName;
389
if (m2.isNamed()) msg += " to " + m1;
390
}
391
392
return new IllegalAccessException(msg);
393
}
394
395
/**
396
* Returns an IllegalAccessException with an exception message where
397
* there is no caller frame.
398
*/
399
private static IllegalAccessException newIllegalAccessException(Class<?> memberClass,
400
int modifiers)
401
{
402
String memberSuffix = "";
403
Module m2 = memberClass.getModule();
404
if (m2.isNamed())
405
memberSuffix = " (in " + m2 + ")";
406
407
String memberPackageName = memberClass.getPackageName();
408
409
String msg = "JNI attached native thread (null caller frame) cannot access ";
410
if (m2.isExported(memberPackageName)) {
411
412
// module access okay so include the modifiers in the message
413
msg += "a member of " + memberClass + memberSuffix +
414
" with modifiers \"" + Modifier.toString(modifiers) + "\"";
415
416
} else {
417
// module access failed
418
msg += memberClass + memberSuffix+ " because "
419
+ m2 + " does not export " + memberPackageName;
420
}
421
422
return new IllegalAccessException(msg);
423
}
424
425
/**
426
* Returns true if {@code currentClass} and {@code memberClass}
427
* are nestmates - that is, if they have the same nesthost as
428
* determined by the VM.
429
*/
430
public static native boolean areNestMates(Class<?> currentClass,
431
Class<?> memberClass);
432
}
433
434