author | rfield |
Mon, 04 Nov 2013 10:12:18 -0800 | |
changeset 21609 | f23c375e4baf |
parent 20825 | 3d5429b4b601 |
child 21672 | 33014eb0cb79 |
permissions | -rw-r--r-- |
2 | 1 |
/* |
21609
f23c375e4baf
7194897: JSR 292: Cannot create more than 16 instances of an anonymous class
rfield
parents:
20825
diff
changeset
|
2 |
* Copyright (c) 2005, 2013, Oracle and/or its affiliates. All rights reserved. |
2 | 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 |
|
5506 | 7 |
* published by the Free Software Foundation. Oracle designates this |
2 | 8 |
* particular file as subject to the "Classpath" exception as provided |
5506 | 9 |
* by Oracle in the LICENSE file that accompanied this code. |
2 | 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 |
* |
|
5506 | 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. |
|
2 | 24 |
*/ |
25 |
||
26 |
||
27 |
package sun.reflect.misc; |
|
28 |
||
20825 | 29 |
import java.lang.reflect.Method; |
2 | 30 |
import java.lang.reflect.Modifier; |
18244 | 31 |
import java.lang.reflect.Proxy; |
20825 | 32 |
import java.util.Arrays; |
2 | 33 |
import sun.reflect.Reflection; |
34 |
||
35 |
public final class ReflectUtil { |
|
36 |
||
37 |
private ReflectUtil() { |
|
38 |
} |
|
39 |
||
10129
bf705e446ca1
7068617: Core libraries don't build with javac -Xlint:all -Werror
jjg
parents:
5506
diff
changeset
|
40 |
public static Class<?> forName(String name) |
2 | 41 |
throws ClassNotFoundException { |
42 |
checkPackageAccess(name); |
|
43 |
return Class.forName(name); |
|
44 |
} |
|
45 |
||
10129
bf705e446ca1
7068617: Core libraries don't build with javac -Xlint:all -Werror
jjg
parents:
5506
diff
changeset
|
46 |
public static Object newInstance(Class<?> cls) |
2 | 47 |
throws InstantiationException, IllegalAccessException { |
48 |
checkPackageAccess(cls); |
|
49 |
return cls.newInstance(); |
|
50 |
} |
|
51 |
||
52 |
/* |
|
53 |
* Reflection.ensureMemberAccess is overly-restrictive |
|
54 |
* due to a bug. We awkwardly work around it for now. |
|
55 |
*/ |
|
10129
bf705e446ca1
7068617: Core libraries don't build with javac -Xlint:all -Werror
jjg
parents:
5506
diff
changeset
|
56 |
public static void ensureMemberAccess(Class<?> currentClass, |
bf705e446ca1
7068617: Core libraries don't build with javac -Xlint:all -Werror
jjg
parents:
5506
diff
changeset
|
57 |
Class<?> memberClass, |
2 | 58 |
Object target, |
59 |
int modifiers) |
|
60 |
throws IllegalAccessException |
|
61 |
{ |
|
62 |
if (target == null && Modifier.isProtected(modifiers)) { |
|
63 |
int mods = modifiers; |
|
64 |
mods = mods & (~Modifier.PROTECTED); |
|
65 |
mods = mods | Modifier.PUBLIC; |
|
66 |
||
67 |
/* |
|
68 |
* See if we fail because of class modifiers |
|
69 |
*/ |
|
70 |
Reflection.ensureMemberAccess(currentClass, |
|
71 |
memberClass, |
|
72 |
target, |
|
73 |
mods); |
|
74 |
try { |
|
75 |
/* |
|
76 |
* We're still here so class access was ok. |
|
77 |
* Now try with default field access. |
|
78 |
*/ |
|
79 |
mods = mods & (~Modifier.PUBLIC); |
|
80 |
Reflection.ensureMemberAccess(currentClass, |
|
81 |
memberClass, |
|
82 |
target, |
|
83 |
mods); |
|
84 |
/* |
|
85 |
* We're still here so access is ok without |
|
86 |
* checking for protected. |
|
87 |
*/ |
|
88 |
return; |
|
89 |
} catch (IllegalAccessException e) { |
|
90 |
/* |
|
91 |
* Access failed but we're 'protected' so |
|
92 |
* if the test below succeeds then we're ok. |
|
93 |
*/ |
|
94 |
if (isSubclassOf(currentClass, memberClass)) { |
|
95 |
return; |
|
96 |
} else { |
|
97 |
throw e; |
|
98 |
} |
|
99 |
} |
|
100 |
} else { |
|
101 |
Reflection.ensureMemberAccess(currentClass, |
|
102 |
memberClass, |
|
103 |
target, |
|
104 |
modifiers); |
|
105 |
} |
|
106 |
} |
|
107 |
||
10129
bf705e446ca1
7068617: Core libraries don't build with javac -Xlint:all -Werror
jjg
parents:
5506
diff
changeset
|
108 |
private static boolean isSubclassOf(Class<?> queryClass, |
bf705e446ca1
7068617: Core libraries don't build with javac -Xlint:all -Werror
jjg
parents:
5506
diff
changeset
|
109 |
Class<?> ofClass) |
2 | 110 |
{ |
111 |
while (queryClass != null) { |
|
112 |
if (queryClass == ofClass) { |
|
113 |
return true; |
|
114 |
} |
|
115 |
queryClass = queryClass.getSuperclass(); |
|
116 |
} |
|
117 |
return false; |
|
118 |
} |
|
119 |
||
18244 | 120 |
/** |
121 |
* Checks package access on the given class. |
|
122 |
* |
|
123 |
* If it is a {@link Proxy#isProxyClass(java.lang.Class)} that implements |
|
124 |
* a non-public interface (i.e. may be in a non-restricted package), |
|
125 |
* also check the package access on the proxy interfaces. |
|
126 |
*/ |
|
10129
bf705e446ca1
7068617: Core libraries don't build with javac -Xlint:all -Werror
jjg
parents:
5506
diff
changeset
|
127 |
public static void checkPackageAccess(Class<?> clazz) { |
2 | 128 |
checkPackageAccess(clazz.getName()); |
18244 | 129 |
if (isNonPublicProxyClass(clazz)) { |
130 |
checkProxyPackageAccess(clazz); |
|
131 |
} |
|
2 | 132 |
} |
133 |
||
18244 | 134 |
/** |
135 |
* Checks package access on the given classname. |
|
136 |
* This method is typically called when the Class instance is not |
|
137 |
* available and the caller attempts to load a class on behalf |
|
138 |
* the true caller (application). |
|
139 |
*/ |
|
2 | 140 |
public static void checkPackageAccess(String name) { |
141 |
SecurityManager s = System.getSecurityManager(); |
|
142 |
if (s != null) { |
|
143 |
String cname = name.replace('/', '.'); |
|
144 |
if (cname.startsWith("[")) { |
|
145 |
int b = cname.lastIndexOf('[') + 2; |
|
146 |
if (b > 1 && b < cname.length()) { |
|
147 |
cname = cname.substring(b); |
|
148 |
} |
|
149 |
} |
|
150 |
int i = cname.lastIndexOf('.'); |
|
151 |
if (i != -1) { |
|
152 |
s.checkPackageAccess(cname.substring(0, i)); |
|
153 |
} |
|
154 |
} |
|
155 |
} |
|
156 |
||
10129
bf705e446ca1
7068617: Core libraries don't build with javac -Xlint:all -Werror
jjg
parents:
5506
diff
changeset
|
157 |
public static boolean isPackageAccessible(Class<?> clazz) { |
2 | 158 |
try { |
159 |
checkPackageAccess(clazz); |
|
160 |
} catch (SecurityException e) { |
|
161 |
return false; |
|
162 |
} |
|
163 |
return true; |
|
164 |
} |
|
13589
da4cb574f4a6
7193339: Prepare system classes be defined by a non-null module loader
mchung
parents:
10129
diff
changeset
|
165 |
|
da4cb574f4a6
7193339: Prepare system classes be defined by a non-null module loader
mchung
parents:
10129
diff
changeset
|
166 |
// Returns true if p is an ancestor of cl i.e. class loader 'p' can |
da4cb574f4a6
7193339: Prepare system classes be defined by a non-null module loader
mchung
parents:
10129
diff
changeset
|
167 |
// be found in the cl's delegation chain |
da4cb574f4a6
7193339: Prepare system classes be defined by a non-null module loader
mchung
parents:
10129
diff
changeset
|
168 |
private static boolean isAncestor(ClassLoader p, ClassLoader cl) { |
da4cb574f4a6
7193339: Prepare system classes be defined by a non-null module loader
mchung
parents:
10129
diff
changeset
|
169 |
ClassLoader acl = cl; |
da4cb574f4a6
7193339: Prepare system classes be defined by a non-null module loader
mchung
parents:
10129
diff
changeset
|
170 |
do { |
da4cb574f4a6
7193339: Prepare system classes be defined by a non-null module loader
mchung
parents:
10129
diff
changeset
|
171 |
acl = acl.getParent(); |
da4cb574f4a6
7193339: Prepare system classes be defined by a non-null module loader
mchung
parents:
10129
diff
changeset
|
172 |
if (p == acl) { |
da4cb574f4a6
7193339: Prepare system classes be defined by a non-null module loader
mchung
parents:
10129
diff
changeset
|
173 |
return true; |
da4cb574f4a6
7193339: Prepare system classes be defined by a non-null module loader
mchung
parents:
10129
diff
changeset
|
174 |
} |
da4cb574f4a6
7193339: Prepare system classes be defined by a non-null module loader
mchung
parents:
10129
diff
changeset
|
175 |
} while (acl != null); |
da4cb574f4a6
7193339: Prepare system classes be defined by a non-null module loader
mchung
parents:
10129
diff
changeset
|
176 |
return false; |
da4cb574f4a6
7193339: Prepare system classes be defined by a non-null module loader
mchung
parents:
10129
diff
changeset
|
177 |
} |
da4cb574f4a6
7193339: Prepare system classes be defined by a non-null module loader
mchung
parents:
10129
diff
changeset
|
178 |
|
da4cb574f4a6
7193339: Prepare system classes be defined by a non-null module loader
mchung
parents:
10129
diff
changeset
|
179 |
/** |
da4cb574f4a6
7193339: Prepare system classes be defined by a non-null module loader
mchung
parents:
10129
diff
changeset
|
180 |
* Returns true if package access check is needed for reflective |
da4cb574f4a6
7193339: Prepare system classes be defined by a non-null module loader
mchung
parents:
10129
diff
changeset
|
181 |
* access from a class loader 'from' to classes or members in |
da4cb574f4a6
7193339: Prepare system classes be defined by a non-null module loader
mchung
parents:
10129
diff
changeset
|
182 |
* a class defined by class loader 'to'. This method returns true |
da4cb574f4a6
7193339: Prepare system classes be defined by a non-null module loader
mchung
parents:
10129
diff
changeset
|
183 |
* if 'from' is not the same as or an ancestor of 'to'. All code |
da4cb574f4a6
7193339: Prepare system classes be defined by a non-null module loader
mchung
parents:
10129
diff
changeset
|
184 |
* in a system domain are granted with all permission and so this |
da4cb574f4a6
7193339: Prepare system classes be defined by a non-null module loader
mchung
parents:
10129
diff
changeset
|
185 |
* method returns false if 'from' class loader is a class loader |
da4cb574f4a6
7193339: Prepare system classes be defined by a non-null module loader
mchung
parents:
10129
diff
changeset
|
186 |
* loading system classes. On the other hand, if a class loader |
da4cb574f4a6
7193339: Prepare system classes be defined by a non-null module loader
mchung
parents:
10129
diff
changeset
|
187 |
* attempts to access system domain classes, it requires package |
da4cb574f4a6
7193339: Prepare system classes be defined by a non-null module loader
mchung
parents:
10129
diff
changeset
|
188 |
* access check and this method will return true. |
da4cb574f4a6
7193339: Prepare system classes be defined by a non-null module loader
mchung
parents:
10129
diff
changeset
|
189 |
*/ |
da4cb574f4a6
7193339: Prepare system classes be defined by a non-null module loader
mchung
parents:
10129
diff
changeset
|
190 |
public static boolean needsPackageAccessCheck(ClassLoader from, ClassLoader to) { |
da4cb574f4a6
7193339: Prepare system classes be defined by a non-null module loader
mchung
parents:
10129
diff
changeset
|
191 |
if (from == null || from == to) |
da4cb574f4a6
7193339: Prepare system classes be defined by a non-null module loader
mchung
parents:
10129
diff
changeset
|
192 |
return false; |
da4cb574f4a6
7193339: Prepare system classes be defined by a non-null module loader
mchung
parents:
10129
diff
changeset
|
193 |
|
da4cb574f4a6
7193339: Prepare system classes be defined by a non-null module loader
mchung
parents:
10129
diff
changeset
|
194 |
if (to == null) |
da4cb574f4a6
7193339: Prepare system classes be defined by a non-null module loader
mchung
parents:
10129
diff
changeset
|
195 |
return true; |
da4cb574f4a6
7193339: Prepare system classes be defined by a non-null module loader
mchung
parents:
10129
diff
changeset
|
196 |
|
da4cb574f4a6
7193339: Prepare system classes be defined by a non-null module loader
mchung
parents:
10129
diff
changeset
|
197 |
return !isAncestor(from, to); |
da4cb574f4a6
7193339: Prepare system classes be defined by a non-null module loader
mchung
parents:
10129
diff
changeset
|
198 |
} |
16087
89b565a23835
7197546: (proxy) Reflect about creating reflective proxies
mchung
parents:
13589
diff
changeset
|
199 |
|
89b565a23835
7197546: (proxy) Reflect about creating reflective proxies
mchung
parents:
13589
diff
changeset
|
200 |
/** |
18244 | 201 |
* Check package access on the proxy interfaces that the given proxy class |
202 |
* implements. |
|
203 |
* |
|
204 |
* @param clazz Proxy class object |
|
205 |
*/ |
|
206 |
public static void checkProxyPackageAccess(Class<?> clazz) { |
|
207 |
SecurityManager s = System.getSecurityManager(); |
|
208 |
if (s != null) { |
|
209 |
// check proxy interfaces if the given class is a proxy class |
|
210 |
if (Proxy.isProxyClass(clazz)) { |
|
211 |
for (Class<?> intf : clazz.getInterfaces()) { |
|
212 |
checkPackageAccess(intf); |
|
213 |
} |
|
214 |
} |
|
215 |
} |
|
216 |
} |
|
217 |
||
218 |
/** |
|
16087
89b565a23835
7197546: (proxy) Reflect about creating reflective proxies
mchung
parents:
13589
diff
changeset
|
219 |
* Access check on the interfaces that a proxy class implements and throw |
18244 | 220 |
* {@code SecurityException} if it accesses a restricted package from |
221 |
* the caller's class loader. |
|
16087
89b565a23835
7197546: (proxy) Reflect about creating reflective proxies
mchung
parents:
13589
diff
changeset
|
222 |
* |
89b565a23835
7197546: (proxy) Reflect about creating reflective proxies
mchung
parents:
13589
diff
changeset
|
223 |
* @param ccl the caller's class loader |
89b565a23835
7197546: (proxy) Reflect about creating reflective proxies
mchung
parents:
13589
diff
changeset
|
224 |
* @param interfaces the list of interfaces that a proxy class implements |
89b565a23835
7197546: (proxy) Reflect about creating reflective proxies
mchung
parents:
13589
diff
changeset
|
225 |
*/ |
89b565a23835
7197546: (proxy) Reflect about creating reflective proxies
mchung
parents:
13589
diff
changeset
|
226 |
public static void checkProxyPackageAccess(ClassLoader ccl, |
89b565a23835
7197546: (proxy) Reflect about creating reflective proxies
mchung
parents:
13589
diff
changeset
|
227 |
Class<?>... interfaces) |
89b565a23835
7197546: (proxy) Reflect about creating reflective proxies
mchung
parents:
13589
diff
changeset
|
228 |
{ |
89b565a23835
7197546: (proxy) Reflect about creating reflective proxies
mchung
parents:
13589
diff
changeset
|
229 |
SecurityManager sm = System.getSecurityManager(); |
89b565a23835
7197546: (proxy) Reflect about creating reflective proxies
mchung
parents:
13589
diff
changeset
|
230 |
if (sm != null) { |
89b565a23835
7197546: (proxy) Reflect about creating reflective proxies
mchung
parents:
13589
diff
changeset
|
231 |
for (Class<?> intf : interfaces) { |
89b565a23835
7197546: (proxy) Reflect about creating reflective proxies
mchung
parents:
13589
diff
changeset
|
232 |
ClassLoader cl = intf.getClassLoader(); |
89b565a23835
7197546: (proxy) Reflect about creating reflective proxies
mchung
parents:
13589
diff
changeset
|
233 |
if (needsPackageAccessCheck(ccl, cl)) { |
89b565a23835
7197546: (proxy) Reflect about creating reflective proxies
mchung
parents:
13589
diff
changeset
|
234 |
checkPackageAccess(intf); |
89b565a23835
7197546: (proxy) Reflect about creating reflective proxies
mchung
parents:
13589
diff
changeset
|
235 |
} |
89b565a23835
7197546: (proxy) Reflect about creating reflective proxies
mchung
parents:
13589
diff
changeset
|
236 |
} |
89b565a23835
7197546: (proxy) Reflect about creating reflective proxies
mchung
parents:
13589
diff
changeset
|
237 |
} |
89b565a23835
7197546: (proxy) Reflect about creating reflective proxies
mchung
parents:
13589
diff
changeset
|
238 |
} |
89b565a23835
7197546: (proxy) Reflect about creating reflective proxies
mchung
parents:
13589
diff
changeset
|
239 |
|
16108
e5fcdadc69b2
8006882: Proxy generated classes in sun.proxy package breaks JMockit
mchung
parents:
16100
diff
changeset
|
240 |
// Note that bytecode instrumentation tools may exclude 'sun.*' |
e5fcdadc69b2
8006882: Proxy generated classes in sun.proxy package breaks JMockit
mchung
parents:
16100
diff
changeset
|
241 |
// classes but not generated proxy classes and so keep it in com.sun.* |
e5fcdadc69b2
8006882: Proxy generated classes in sun.proxy package breaks JMockit
mchung
parents:
16100
diff
changeset
|
242 |
public static final String PROXY_PACKAGE = "com.sun.proxy"; |
18244 | 243 |
|
244 |
/** |
|
245 |
* Test if the given class is a proxy class that implements |
|
246 |
* non-public interface. Such proxy class may be in a non-restricted |
|
247 |
* package that bypasses checkPackageAccess. |
|
248 |
*/ |
|
249 |
public static boolean isNonPublicProxyClass(Class<?> cls) { |
|
250 |
String name = cls.getName(); |
|
251 |
int i = name.lastIndexOf('.'); |
|
252 |
String pkg = (i != -1) ? name.substring(0, i) : ""; |
|
253 |
return Proxy.isProxyClass(cls) && !pkg.equals(PROXY_PACKAGE); |
|
254 |
} |
|
20825 | 255 |
|
256 |
/** |
|
257 |
* Check if the given method is a method declared in the proxy interface |
|
258 |
* implemented by the given proxy instance. |
|
259 |
* |
|
260 |
* @param proxy a proxy instance |
|
261 |
* @param method an interface method dispatched to a InvocationHandler |
|
262 |
* |
|
263 |
* @throws IllegalArgumentException if the given proxy or method is invalid. |
|
264 |
*/ |
|
265 |
public static void checkProxyMethod(Object proxy, Method method) { |
|
266 |
// check if it is a valid proxy instance |
|
267 |
if (proxy == null || !Proxy.isProxyClass(proxy.getClass())) { |
|
268 |
throw new IllegalArgumentException("Not a Proxy instance"); |
|
2 | 269 |
} |
20825 | 270 |
if (Modifier.isStatic(method.getModifiers())) { |
271 |
throw new IllegalArgumentException("Can't handle static method"); |
|
272 |
} |
|
273 |
||
274 |
Class<?> c = method.getDeclaringClass(); |
|
275 |
if (c == Object.class) { |
|
276 |
String name = method.getName(); |
|
277 |
if (name.equals("hashCode") || name.equals("equals") || name.equals("toString")) { |
|
278 |
return; |
|
279 |
} |
|
280 |
} |
|
281 |
||
282 |
if (isSuperInterface(proxy.getClass(), c)) { |
|
283 |
return; |
|
284 |
} |
|
285 |
||
286 |
// disallow any method not declared in one of the proxy intefaces |
|
287 |
throw new IllegalArgumentException("Can't handle: " + method); |
|
288 |
} |
|
289 |
||
290 |
private static boolean isSuperInterface(Class<?> c, Class<?> intf) { |
|
291 |
for (Class<?> i : c.getInterfaces()) { |
|
292 |
if (i == intf) { |
|
293 |
return true; |
|
294 |
} |
|
295 |
if (isSuperInterface(i, intf)) { |
|
296 |
return true; |
|
297 |
} |
|
298 |
} |
|
299 |
return false; |
|
300 |
} |
|
21609
f23c375e4baf
7194897: JSR 292: Cannot create more than 16 instances of an anonymous class
rfield
parents:
20825
diff
changeset
|
301 |
|
f23c375e4baf
7194897: JSR 292: Cannot create more than 16 instances of an anonymous class
rfield
parents:
20825
diff
changeset
|
302 |
/** |
f23c375e4baf
7194897: JSR 292: Cannot create more than 16 instances of an anonymous class
rfield
parents:
20825
diff
changeset
|
303 |
* Checks if {@code Class cls} is a VM-anonymous class |
f23c375e4baf
7194897: JSR 292: Cannot create more than 16 instances of an anonymous class
rfield
parents:
20825
diff
changeset
|
304 |
* as defined by {@link sun.misc.Unsafe#defineAnonymousClass} |
f23c375e4baf
7194897: JSR 292: Cannot create more than 16 instances of an anonymous class
rfield
parents:
20825
diff
changeset
|
305 |
* (not to be confused with a Java Language anonymous inner class). |
f23c375e4baf
7194897: JSR 292: Cannot create more than 16 instances of an anonymous class
rfield
parents:
20825
diff
changeset
|
306 |
*/ |
f23c375e4baf
7194897: JSR 292: Cannot create more than 16 instances of an anonymous class
rfield
parents:
20825
diff
changeset
|
307 |
public static boolean isVMAnonymousClass(Class<?> cls) { |
f23c375e4baf
7194897: JSR 292: Cannot create more than 16 instances of an anonymous class
rfield
parents:
20825
diff
changeset
|
308 |
return cls.getSimpleName().contains("/"); |
f23c375e4baf
7194897: JSR 292: Cannot create more than 16 instances of an anonymous class
rfield
parents:
20825
diff
changeset
|
309 |
} |
20825 | 310 |
} |