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/Reflection.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.lang.reflect.*;
29
import java.util.HashMap;
30
import java.util.Map;
31
32
/** Common utility routines used by both java.lang and
33
java.lang.reflect */
34
35
public class Reflection {
36
37
/** Used to filter out fields and methods from certain classes from public
38
view, where they are sensitive or they may contain VM-internal objects.
39
These Maps are updated very rarely. Rather than synchronize on
40
each access, we use copy-on-write */
41
private static volatile Map<Class<?>,String[]> fieldFilterMap;
42
private static volatile Map<Class<?>,String[]> methodFilterMap;
43
44
static {
45
Map<Class<?>,String[]> map = new HashMap<Class<?>,String[]>();
46
map.put(Reflection.class,
47
new String[] {"fieldFilterMap", "methodFilterMap"});
48
map.put(System.class, new String[] {"security"});
49
map.put(Class.class, new String[] {"classLoader"});
50
fieldFilterMap = map;
51
52
methodFilterMap = new HashMap<>();
53
}
54
55
/** Returns the class of the caller of the method calling this method,
56
ignoring frames associated with java.lang.reflect.Method.invoke()
57
and its implementation. */
58
@CallerSensitive
59
public static native Class<?> getCallerClass();
60
61
/**
62
* @deprecated This method will be removed in JDK 9.
63
* This method is a private JDK API and retained temporarily for
64
* existing code to run until a replacement API is defined.
65
*/
66
@Deprecated
67
public static native Class<?> getCallerClass(int depth);
68
69
/** Retrieves the access flags written to the class file. For
70
inner classes these flags may differ from those returned by
71
Class.getModifiers(), which searches the InnerClasses
72
attribute to find the source-level access flags. This is used
73
instead of Class.getModifiers() for run-time access checks due
74
to compatibility reasons; see 4471811. Only the values of the
75
low 13 bits (i.e., a mask of 0x1FFF) are guaranteed to be
76
valid. */
77
public static native int getClassAccessFlags(Class<?> c);
78
79
/** A quick "fast-path" check to try to avoid getCallerClass()
80
calls. */
81
public static boolean quickCheckMemberAccess(Class<?> memberClass,
82
int modifiers)
83
{
84
return Modifier.isPublic(getClassAccessFlags(memberClass) & modifiers);
85
}
86
87
public static void ensureMemberAccess(Class<?> currentClass,
88
Class<?> memberClass,
89
Object target,
90
int modifiers)
91
throws IllegalAccessException
92
{
93
if (currentClass == null || memberClass == null) {
94
throw new InternalError();
95
}
96
97
if (!verifyMemberAccess(currentClass, memberClass, target, modifiers)) {
98
throw new IllegalAccessException("Class " + currentClass.getName() +
99
" can not access a member of class " +
100
memberClass.getName() +
101
" with modifiers \"" +
102
Modifier.toString(modifiers) +
103
"\"");
104
}
105
}
106
107
public static boolean verifyMemberAccess(Class<?> currentClass,
108
// Declaring class of field
109
// or method
110
Class<?> memberClass,
111
// May be NULL in case of statics
112
Object target,
113
int modifiers)
114
{
115
// Verify that currentClass can access a field, method, or
116
// constructor of memberClass, where that member's access bits are
117
// "modifiers".
118
119
boolean gotIsSameClassPackage = false;
120
boolean isSameClassPackage = false;
121
122
if (currentClass == memberClass) {
123
// Always succeeds
124
return true;
125
}
126
127
if (!Modifier.isPublic(getClassAccessFlags(memberClass))) {
128
isSameClassPackage = isSameClassPackage(currentClass, memberClass);
129
gotIsSameClassPackage = true;
130
if (!isSameClassPackage) {
131
return false;
132
}
133
}
134
135
// At this point we know that currentClass can access memberClass.
136
137
if (Modifier.isPublic(modifiers)) {
138
return true;
139
}
140
141
boolean successSoFar = false;
142
143
if (Modifier.isProtected(modifiers)) {
144
// See if currentClass is a subclass of memberClass
145
if (isSubclassOf(currentClass, memberClass)) {
146
successSoFar = true;
147
}
148
}
149
150
if (!successSoFar && !Modifier.isPrivate(modifiers)) {
151
if (!gotIsSameClassPackage) {
152
isSameClassPackage = isSameClassPackage(currentClass,
153
memberClass);
154
gotIsSameClassPackage = true;
155
}
156
157
if (isSameClassPackage) {
158
successSoFar = true;
159
}
160
}
161
162
if (!successSoFar) {
163
return false;
164
}
165
166
if (Modifier.isProtected(modifiers)) {
167
// Additional test for protected members: JLS 6.6.2
168
Class<?> targetClass = (target == null ? memberClass : target.getClass());
169
if (targetClass != currentClass) {
170
if (!gotIsSameClassPackage) {
171
isSameClassPackage = isSameClassPackage(currentClass, memberClass);
172
gotIsSameClassPackage = true;
173
}
174
if (!isSameClassPackage) {
175
if (!isSubclassOf(targetClass, currentClass)) {
176
return false;
177
}
178
}
179
}
180
}
181
182
return true;
183
}
184
185
private static boolean isSameClassPackage(Class<?> c1, Class<?> c2) {
186
return isSameClassPackage(c1.getClassLoader(), c1.getName(),
187
c2.getClassLoader(), c2.getName());
188
}
189
190
/** Returns true if two classes are in the same package; classloader
191
and classname information is enough to determine a class's package */
192
private static boolean isSameClassPackage(ClassLoader loader1, String name1,
193
ClassLoader loader2, String name2)
194
{
195
if (loader1 != loader2) {
196
return false;
197
} else {
198
int lastDot1 = name1.lastIndexOf('.');
199
int lastDot2 = name2.lastIndexOf('.');
200
if ((lastDot1 == -1) || (lastDot2 == -1)) {
201
// One of the two doesn't have a package. Only return true
202
// if the other one also doesn't have a package.
203
return (lastDot1 == lastDot2);
204
} else {
205
int idx1 = 0;
206
int idx2 = 0;
207
208
// Skip over '['s
209
if (name1.charAt(idx1) == '[') {
210
do {
211
idx1++;
212
} while (name1.charAt(idx1) == '[');
213
if (name1.charAt(idx1) != 'L') {
214
// Something is terribly wrong. Shouldn't be here.
215
throw new InternalError("Illegal class name " + name1);
216
}
217
}
218
if (name2.charAt(idx2) == '[') {
219
do {
220
idx2++;
221
} while (name2.charAt(idx2) == '[');
222
if (name2.charAt(idx2) != 'L') {
223
// Something is terribly wrong. Shouldn't be here.
224
throw new InternalError("Illegal class name " + name2);
225
}
226
}
227
228
// Check that package part is identical
229
int length1 = lastDot1 - idx1;
230
int length2 = lastDot2 - idx2;
231
232
if (length1 != length2) {
233
return false;
234
}
235
return name1.regionMatches(false, idx1, name2, idx2, length1);
236
}
237
}
238
}
239
240
static boolean isSubclassOf(Class<?> queryClass,
241
Class<?> ofClass)
242
{
243
while (queryClass != null) {
244
if (queryClass == ofClass) {
245
return true;
246
}
247
queryClass = queryClass.getSuperclass();
248
}
249
return false;
250
}
251
252
// fieldNames must contain only interned Strings
253
public static synchronized void registerFieldsToFilter(Class<?> containingClass,
254
String ... fieldNames) {
255
fieldFilterMap =
256
registerFilter(fieldFilterMap, containingClass, fieldNames);
257
}
258
259
// methodNames must contain only interned Strings
260
public static synchronized void registerMethodsToFilter(Class<?> containingClass,
261
String ... methodNames) {
262
methodFilterMap =
263
registerFilter(methodFilterMap, containingClass, methodNames);
264
}
265
266
private static Map<Class<?>,String[]> registerFilter(Map<Class<?>,String[]> map,
267
Class<?> containingClass, String ... names) {
268
if (map.get(containingClass) != null) {
269
throw new IllegalArgumentException
270
("Filter already registered: " + containingClass);
271
}
272
map = new HashMap<Class<?>,String[]>(map);
273
map.put(containingClass, names);
274
return map;
275
}
276
277
public static Field[] filterFields(Class<?> containingClass,
278
Field[] fields) {
279
if (fieldFilterMap == null) {
280
// Bootstrapping
281
return fields;
282
}
283
return (Field[])filter(fields, fieldFilterMap.get(containingClass));
284
}
285
286
public static Method[] filterMethods(Class<?> containingClass, Method[] methods) {
287
if (methodFilterMap == null) {
288
// Bootstrapping
289
return methods;
290
}
291
return (Method[])filter(methods, methodFilterMap.get(containingClass));
292
}
293
294
private static Member[] filter(Member[] members, String[] filteredNames) {
295
if ((filteredNames == null) || (members.length == 0)) {
296
return members;
297
}
298
int numNewMembers = 0;
299
for (Member member : members) {
300
boolean shouldSkip = false;
301
for (String filteredName : filteredNames) {
302
if (member.getName() == filteredName) {
303
shouldSkip = true;
304
break;
305
}
306
}
307
if (!shouldSkip) {
308
++numNewMembers;
309
}
310
}
311
Member[] newMembers =
312
(Member[])Array.newInstance(members[0].getClass(), numNewMembers);
313
int destIdx = 0;
314
for (Member member : members) {
315
boolean shouldSkip = false;
316
for (String filteredName : filteredNames) {
317
if (member.getName() == filteredName) {
318
shouldSkip = true;
319
break;
320
}
321
}
322
if (!shouldSkip) {
323
newMembers[destIdx++] = member;
324
}
325
}
326
return newMembers;
327
}
328
329
/**
330
* Tests if the given method is caller-sensitive and the declaring class
331
* is defined by either the bootstrap class loader or extension class loader.
332
*/
333
public static boolean isCallerSensitive(Method m) {
334
final ClassLoader loader = m.getDeclaringClass().getClassLoader();
335
if (sun.misc.VM.isSystemDomainLoader(loader) || isExtClassLoader(loader)) {
336
return m.isAnnotationPresent(CallerSensitive.class);
337
}
338
return false;
339
}
340
341
private static boolean isExtClassLoader(ClassLoader loader) {
342
ClassLoader cl = ClassLoader.getSystemClassLoader();
343
while (cl != null) {
344
if (cl.getParent() == null && cl == loader) {
345
return true;
346
}
347
cl = cl.getParent();
348
}
349
return false;
350
}
351
}
352
353