Mercurial > hg > truffle
annotate src/share/vm/runtime/reflection.cpp @ 1721:413ad0331a0c
6977924: Changes for 6975078 produce build error with certain gcc versions
Summary: The changes introduced for 6975078 assign badHeapOopVal to the _allocation field in the ResourceObj class. In 32 bit linux builds with certain versions of gcc this assignment will be flagged as an error while compiling allocation.cpp. In 32 bit builds the constant value badHeapOopVal (which is cast to an intptr_t) is negative. The _allocation field is typed as an unsigned intptr_t and gcc catches this as an error.
Reviewed-by: jcoomes, ysr, phh
author | johnc |
---|---|
date | Wed, 18 Aug 2010 10:59:06 -0700 |
parents | c18cbe5936b8 |
children | f95d63e2154a |
rev | line source |
---|---|
0 | 1 /* |
1552
c18cbe5936b8
6941466: Oracle rebranding changes for Hotspot repositories
trims
parents:
1152
diff
changeset
|
2 * Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved. |
0 | 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. | |
8 * | |
9 * This code is distributed in the hope that it will be useful, but WITHOUT | |
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | |
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License | |
12 * version 2 for more details (a copy is included in the LICENSE file that | |
13 * accompanied this code). | |
14 * | |
15 * You should have received a copy of the GNU General Public License version | |
16 * 2 along with this work; if not, write to the Free Software Foundation, | |
17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. | |
18 * | |
1552
c18cbe5936b8
6941466: Oracle rebranding changes for Hotspot repositories
trims
parents:
1152
diff
changeset
|
19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA |
c18cbe5936b8
6941466: Oracle rebranding changes for Hotspot repositories
trims
parents:
1152
diff
changeset
|
20 * or visit www.oracle.com if you need additional information or have any |
c18cbe5936b8
6941466: Oracle rebranding changes for Hotspot repositories
trims
parents:
1152
diff
changeset
|
21 * questions. |
0 | 22 * |
23 */ | |
24 | |
25 #include "incls/_precompiled.incl" | |
26 #include "incls/_reflection.cpp.incl" | |
27 | |
28 #define JAVA_1_5_VERSION 49 | |
29 | |
30 static void trace_class_resolution(klassOop to_class) { | |
31 ResourceMark rm; | |
32 int line_number = -1; | |
33 const char * source_file = NULL; | |
34 klassOop caller = NULL; | |
35 JavaThread* jthread = JavaThread::current(); | |
36 if (jthread->has_last_Java_frame()) { | |
37 vframeStream vfst(jthread); | |
38 // skip over any frames belonging to java.lang.Class | |
39 while (!vfst.at_end() && | |
40 instanceKlass::cast(vfst.method()->method_holder())->name() == vmSymbols::java_lang_Class()) { | |
41 vfst.next(); | |
42 } | |
43 if (!vfst.at_end()) { | |
44 // this frame is a likely suspect | |
45 caller = vfst.method()->method_holder(); | |
46 line_number = vfst.method()->line_number_from_bci(vfst.bci()); | |
47 symbolOop s = instanceKlass::cast(vfst.method()->method_holder())->source_file_name(); | |
48 if (s != NULL) { | |
49 source_file = s->as_C_string(); | |
50 } | |
51 } | |
52 } | |
53 if (caller != NULL) { | |
54 const char * from = Klass::cast(caller)->external_name(); | |
55 const char * to = Klass::cast(to_class)->external_name(); | |
56 // print in a single call to reduce interleaving between threads | |
57 if (source_file != NULL) { | |
58 tty->print("RESOLVE %s %s %s:%d (reflection)\n", from, to, source_file, line_number); | |
59 } else { | |
60 tty->print("RESOLVE %s %s (reflection)\n", from, to); | |
61 } | |
62 } | |
63 } | |
64 | |
65 | |
66 oop Reflection::box(jvalue* value, BasicType type, TRAPS) { | |
67 if (type == T_VOID) { | |
68 return NULL; | |
69 } | |
70 if (type == T_OBJECT || type == T_ARRAY) { | |
71 // regular objects are not boxed | |
72 return (oop) value->l; | |
73 } | |
74 oop result = java_lang_boxing_object::create(type, value, CHECK_NULL); | |
75 if (result == NULL) { | |
76 THROW_(vmSymbols::java_lang_IllegalArgumentException(), result); | |
77 } | |
78 return result; | |
79 } | |
80 | |
81 | |
82 BasicType Reflection::unbox_for_primitive(oop box, jvalue* value, TRAPS) { | |
83 if (box == NULL) { | |
84 THROW_(vmSymbols::java_lang_IllegalArgumentException(), T_ILLEGAL); | |
85 } | |
86 return java_lang_boxing_object::get_value(box, value); | |
87 } | |
88 | |
89 BasicType Reflection::unbox_for_regular_object(oop box, jvalue* value) { | |
90 // Note: box is really the unboxed oop. It might even be a Short, etc.! | |
91 value->l = (jobject) box; | |
92 return T_OBJECT; | |
93 } | |
94 | |
95 | |
96 void Reflection::widen(jvalue* value, BasicType current_type, BasicType wide_type, TRAPS) { | |
97 assert(wide_type != current_type, "widen should not be called with identical types"); | |
98 switch (wide_type) { | |
99 case T_BOOLEAN: | |
100 case T_BYTE: | |
101 case T_CHAR: | |
102 break; // fail | |
103 case T_SHORT: | |
104 switch (current_type) { | |
105 case T_BYTE: | |
106 value->s = (jshort) value->b; | |
107 return; | |
108 } | |
109 break; // fail | |
110 case T_INT: | |
111 switch (current_type) { | |
112 case T_BYTE: | |
113 value->i = (jint) value->b; | |
114 return; | |
115 case T_CHAR: | |
116 value->i = (jint) value->c; | |
117 return; | |
118 case T_SHORT: | |
119 value->i = (jint) value->s; | |
120 return; | |
121 } | |
122 break; // fail | |
123 case T_LONG: | |
124 switch (current_type) { | |
125 case T_BYTE: | |
126 value->j = (jlong) value->b; | |
127 return; | |
128 case T_CHAR: | |
129 value->j = (jlong) value->c; | |
130 return; | |
131 case T_SHORT: | |
132 value->j = (jlong) value->s; | |
133 return; | |
134 case T_INT: | |
135 value->j = (jlong) value->i; | |
136 return; | |
137 } | |
138 break; // fail | |
139 case T_FLOAT: | |
140 switch (current_type) { | |
141 case T_BYTE: | |
142 value->f = (jfloat) value->b; | |
143 return; | |
144 case T_CHAR: | |
145 value->f = (jfloat) value->c; | |
146 return; | |
147 case T_SHORT: | |
148 value->f = (jfloat) value->s; | |
149 return; | |
150 case T_INT: | |
151 value->f = (jfloat) value->i; | |
152 return; | |
153 case T_LONG: | |
154 value->f = (jfloat) value->j; | |
155 return; | |
156 } | |
157 break; // fail | |
158 case T_DOUBLE: | |
159 switch (current_type) { | |
160 case T_BYTE: | |
161 value->d = (jdouble) value->b; | |
162 return; | |
163 case T_CHAR: | |
164 value->d = (jdouble) value->c; | |
165 return; | |
166 case T_SHORT: | |
167 value->d = (jdouble) value->s; | |
168 return; | |
169 case T_INT: | |
170 value->d = (jdouble) value->i; | |
171 return; | |
172 case T_FLOAT: | |
173 value->d = (jdouble) value->f; | |
174 return; | |
175 case T_LONG: | |
176 value->d = (jdouble) value->j; | |
177 return; | |
178 } | |
179 break; // fail | |
180 default: | |
181 break; // fail | |
182 } | |
183 THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(), "argument type mismatch"); | |
184 } | |
185 | |
186 | |
187 BasicType Reflection::array_get(jvalue* value, arrayOop a, int index, TRAPS) { | |
188 if (!a->is_within_bounds(index)) { | |
189 THROW_(vmSymbols::java_lang_ArrayIndexOutOfBoundsException(), T_ILLEGAL); | |
190 } | |
191 if (a->is_objArray()) { | |
192 value->l = (jobject) objArrayOop(a)->obj_at(index); | |
193 return T_OBJECT; | |
194 } else { | |
195 assert(a->is_typeArray(), "just checking"); | |
196 BasicType type = typeArrayKlass::cast(a->klass())->element_type(); | |
197 switch (type) { | |
198 case T_BOOLEAN: | |
199 value->z = typeArrayOop(a)->bool_at(index); | |
200 break; | |
201 case T_CHAR: | |
202 value->c = typeArrayOop(a)->char_at(index); | |
203 break; | |
204 case T_FLOAT: | |
205 value->f = typeArrayOop(a)->float_at(index); | |
206 break; | |
207 case T_DOUBLE: | |
208 value->d = typeArrayOop(a)->double_at(index); | |
209 break; | |
210 case T_BYTE: | |
211 value->b = typeArrayOop(a)->byte_at(index); | |
212 break; | |
213 case T_SHORT: | |
214 value->s = typeArrayOop(a)->short_at(index); | |
215 break; | |
216 case T_INT: | |
217 value->i = typeArrayOop(a)->int_at(index); | |
218 break; | |
219 case T_LONG: | |
220 value->j = typeArrayOop(a)->long_at(index); | |
221 break; | |
222 default: | |
223 return T_ILLEGAL; | |
224 } | |
225 return type; | |
226 } | |
227 } | |
228 | |
229 | |
230 void Reflection::array_set(jvalue* value, arrayOop a, int index, BasicType value_type, TRAPS) { | |
231 if (!a->is_within_bounds(index)) { | |
232 THROW(vmSymbols::java_lang_ArrayIndexOutOfBoundsException()); | |
233 } | |
234 if (a->is_objArray()) { | |
235 if (value_type == T_OBJECT) { | |
236 oop obj = (oop) value->l; | |
237 if (obj != NULL) { | |
238 klassOop element_klass = objArrayKlass::cast(a->klass())->element_klass(); | |
239 if (!obj->is_a(element_klass)) { | |
240 THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(), "array element type mismatch"); | |
241 } | |
242 } | |
243 objArrayOop(a)->obj_at_put(index, obj); | |
244 } | |
245 } else { | |
246 assert(a->is_typeArray(), "just checking"); | |
247 BasicType array_type = typeArrayKlass::cast(a->klass())->element_type(); | |
248 if (array_type != value_type) { | |
249 // The widen operation can potentially throw an exception, but cannot block, | |
250 // so typeArrayOop a is safe if the call succeeds. | |
251 widen(value, value_type, array_type, CHECK); | |
252 } | |
253 switch (array_type) { | |
254 case T_BOOLEAN: | |
255 typeArrayOop(a)->bool_at_put(index, value->z); | |
256 break; | |
257 case T_CHAR: | |
258 typeArrayOop(a)->char_at_put(index, value->c); | |
259 break; | |
260 case T_FLOAT: | |
261 typeArrayOop(a)->float_at_put(index, value->f); | |
262 break; | |
263 case T_DOUBLE: | |
264 typeArrayOop(a)->double_at_put(index, value->d); | |
265 break; | |
266 case T_BYTE: | |
267 typeArrayOop(a)->byte_at_put(index, value->b); | |
268 break; | |
269 case T_SHORT: | |
270 typeArrayOop(a)->short_at_put(index, value->s); | |
271 break; | |
272 case T_INT: | |
273 typeArrayOop(a)->int_at_put(index, value->i); | |
274 break; | |
275 case T_LONG: | |
276 typeArrayOop(a)->long_at_put(index, value->j); | |
277 break; | |
278 default: | |
279 THROW(vmSymbols::java_lang_IllegalArgumentException()); | |
280 } | |
281 } | |
282 } | |
283 | |
284 | |
285 klassOop Reflection::basic_type_mirror_to_arrayklass(oop basic_type_mirror, TRAPS) { | |
286 assert(java_lang_Class::is_primitive(basic_type_mirror), "just checking"); | |
287 BasicType type = java_lang_Class::primitive_type(basic_type_mirror); | |
288 if (type == T_VOID) { | |
289 THROW_0(vmSymbols::java_lang_IllegalArgumentException()); | |
290 } else { | |
291 return Universe::typeArrayKlassObj(type); | |
292 } | |
293 } | |
294 | |
295 | |
296 oop Reflection:: basic_type_arrayklass_to_mirror(klassOop basic_type_arrayklass, TRAPS) { | |
297 BasicType type = typeArrayKlass::cast(basic_type_arrayklass)->element_type(); | |
298 return Universe::java_mirror(type); | |
299 } | |
300 | |
301 | |
302 arrayOop Reflection::reflect_new_array(oop element_mirror, jint length, TRAPS) { | |
303 if (element_mirror == NULL) { | |
304 THROW_0(vmSymbols::java_lang_NullPointerException()); | |
305 } | |
306 if (length < 0) { | |
307 THROW_0(vmSymbols::java_lang_NegativeArraySizeException()); | |
308 } | |
309 if (java_lang_Class::is_primitive(element_mirror)) { | |
310 klassOop tak = basic_type_mirror_to_arrayklass(element_mirror, CHECK_NULL); | |
311 return typeArrayKlass::cast(tak)->allocate(length, THREAD); | |
312 } else { | |
313 klassOop k = java_lang_Class::as_klassOop(element_mirror); | |
314 if (Klass::cast(k)->oop_is_array() && arrayKlass::cast(k)->dimension() >= MAX_DIM) { | |
315 THROW_0(vmSymbols::java_lang_IllegalArgumentException()); | |
316 } | |
317 return oopFactory::new_objArray(k, length, THREAD); | |
318 } | |
319 } | |
320 | |
321 | |
322 arrayOop Reflection::reflect_new_multi_array(oop element_mirror, typeArrayOop dim_array, TRAPS) { | |
323 assert(dim_array->is_typeArray(), "just checking"); | |
324 assert(typeArrayKlass::cast(dim_array->klass())->element_type() == T_INT, "just checking"); | |
325 | |
326 if (element_mirror == NULL) { | |
327 THROW_0(vmSymbols::java_lang_NullPointerException()); | |
328 } | |
329 | |
330 int len = dim_array->length(); | |
331 if (len <= 0 || len > MAX_DIM) { | |
332 THROW_0(vmSymbols::java_lang_IllegalArgumentException()); | |
333 } | |
334 | |
335 jint dimensions[MAX_DIM]; // C array copy of intArrayOop | |
336 for (int i = 0; i < len; i++) { | |
337 int d = dim_array->int_at(i); | |
338 if (d < 0) { | |
339 THROW_0(vmSymbols::java_lang_NegativeArraySizeException()); | |
340 } | |
341 dimensions[i] = d; | |
342 } | |
343 | |
344 klassOop klass; | |
345 int dim = len; | |
346 if (java_lang_Class::is_primitive(element_mirror)) { | |
347 klass = basic_type_mirror_to_arrayklass(element_mirror, CHECK_NULL); | |
348 } else { | |
349 klass = java_lang_Class::as_klassOop(element_mirror); | |
350 if (Klass::cast(klass)->oop_is_array()) { | |
351 int k_dim = arrayKlass::cast(klass)->dimension(); | |
352 if (k_dim + len > MAX_DIM) { | |
353 THROW_0(vmSymbols::java_lang_IllegalArgumentException()); | |
354 } | |
355 dim += k_dim; | |
356 } | |
357 } | |
358 klass = Klass::cast(klass)->array_klass(dim, CHECK_NULL); | |
359 oop obj = arrayKlass::cast(klass)->multi_allocate(len, dimensions, THREAD); | |
360 assert(obj->is_array(), "just checking"); | |
361 return arrayOop(obj); | |
362 } | |
363 | |
364 | |
365 oop Reflection::array_component_type(oop mirror, TRAPS) { | |
366 if (java_lang_Class::is_primitive(mirror)) { | |
367 return NULL; | |
368 } | |
369 | |
370 klassOop klass = java_lang_Class::as_klassOop(mirror); | |
371 if (!Klass::cast(klass)->oop_is_array()) { | |
372 return NULL; | |
373 } | |
374 | |
375 oop result = arrayKlass::cast(klass)->component_mirror(); | |
376 #ifdef ASSERT | |
377 oop result2 = NULL; | |
378 if (arrayKlass::cast(klass)->dimension() == 1) { | |
379 if (Klass::cast(klass)->oop_is_typeArray()) { | |
380 result2 = basic_type_arrayklass_to_mirror(klass, CHECK_NULL); | |
381 } else { | |
382 result2 = Klass::cast(objArrayKlass::cast(klass)->element_klass())->java_mirror(); | |
383 } | |
384 } else { | |
385 klassOop lower_dim = arrayKlass::cast(klass)->lower_dimension(); | |
386 assert(Klass::cast(lower_dim)->oop_is_array(), "just checking"); | |
387 result2 = Klass::cast(lower_dim)->java_mirror(); | |
388 } | |
389 assert(result == result2, "results must be consistent"); | |
390 #endif //ASSERT | |
391 return result; | |
392 } | |
393 | |
394 | |
395 bool Reflection::reflect_check_access(klassOop field_class, AccessFlags acc, klassOop target_class, bool is_method_invoke, TRAPS) { | |
396 // field_class : declaring class | |
397 // acc : declared field access | |
398 // target_class : for protected | |
399 | |
400 // Check if field or method is accessible to client. Throw an | |
401 // IllegalAccessException and return false if not. | |
402 | |
403 // The "client" is the class associated with the nearest real frame | |
404 // getCallerClass already skips Method.invoke frames, so pass 0 in | |
405 // that case (same as classic). | |
406 ResourceMark rm(THREAD); | |
407 assert(THREAD->is_Java_thread(), "sanity check"); | |
408 klassOop client_class = ((JavaThread *)THREAD)->security_get_caller_class(is_method_invoke ? 0 : 1); | |
409 | |
410 if (client_class != field_class) { | |
411 if (!verify_class_access(client_class, field_class, false) | |
412 || !verify_field_access(client_class, | |
413 field_class, | |
414 field_class, | |
415 acc, | |
416 false)) { | |
417 THROW_(vmSymbols::java_lang_IllegalAccessException(), false); | |
418 } | |
419 } | |
420 | |
421 // Additional test for protected members: JLS 6.6.2 | |
422 | |
423 if (acc.is_protected()) { | |
424 if (target_class != client_class) { | |
425 if (!is_same_class_package(client_class, field_class)) { | |
426 if (!Klass::cast(target_class)->is_subclass_of(client_class)) { | |
427 THROW_(vmSymbols::java_lang_IllegalAccessException(), false); | |
428 } | |
429 } | |
430 } | |
431 } | |
432 | |
433 // Passed all tests | |
434 return true; | |
435 } | |
436 | |
437 | |
438 bool Reflection::verify_class_access(klassOop current_class, klassOop new_class, bool classloader_only) { | |
439 // Verify that current_class can access new_class. If the classloader_only | |
440 // flag is set, we automatically allow any accesses in which current_class | |
441 // doesn't have a classloader. | |
442 if ((current_class == NULL) || | |
443 (current_class == new_class) || | |
444 (instanceKlass::cast(new_class)->is_public()) || | |
445 is_same_class_package(current_class, new_class)) { | |
446 return true; | |
447 } | |
448 // New (1.4) reflection implementation. Allow all accesses from | |
449 // sun/reflect/MagicAccessorImpl subclasses to succeed trivially. | |
450 if ( JDK_Version::is_gte_jdk14x_version() | |
451 && UseNewReflection | |
1142 | 452 && Klass::cast(current_class)->is_subclass_of(SystemDictionary::reflect_MagicAccessorImpl_klass())) { |
0 | 453 return true; |
454 } | |
455 | |
456 return can_relax_access_check_for(current_class, new_class, classloader_only); | |
457 } | |
458 | |
431
a45484ea312d
6653858: dynamic languages need to be able to load anonymous classes
jrose
parents:
196
diff
changeset
|
459 static bool under_host_klass(instanceKlass* ik, klassOop host_klass) { |
a45484ea312d
6653858: dynamic languages need to be able to load anonymous classes
jrose
parents:
196
diff
changeset
|
460 DEBUG_ONLY(int inf_loop_check = 1000 * 1000 * 1000); |
a45484ea312d
6653858: dynamic languages need to be able to load anonymous classes
jrose
parents:
196
diff
changeset
|
461 for (;;) { |
a45484ea312d
6653858: dynamic languages need to be able to load anonymous classes
jrose
parents:
196
diff
changeset
|
462 klassOop hc = (klassOop) ik->host_klass(); |
a45484ea312d
6653858: dynamic languages need to be able to load anonymous classes
jrose
parents:
196
diff
changeset
|
463 if (hc == NULL) return false; |
a45484ea312d
6653858: dynamic languages need to be able to load anonymous classes
jrose
parents:
196
diff
changeset
|
464 if (hc == host_klass) return true; |
a45484ea312d
6653858: dynamic languages need to be able to load anonymous classes
jrose
parents:
196
diff
changeset
|
465 ik = instanceKlass::cast(hc); |
a45484ea312d
6653858: dynamic languages need to be able to load anonymous classes
jrose
parents:
196
diff
changeset
|
466 |
a45484ea312d
6653858: dynamic languages need to be able to load anonymous classes
jrose
parents:
196
diff
changeset
|
467 // There's no way to make a host class loop short of patching memory. |
a45484ea312d
6653858: dynamic languages need to be able to load anonymous classes
jrose
parents:
196
diff
changeset
|
468 // Therefore there cannot be a loop here unles there's another bug. |
a45484ea312d
6653858: dynamic languages need to be able to load anonymous classes
jrose
parents:
196
diff
changeset
|
469 // Still, let's check for it. |
a45484ea312d
6653858: dynamic languages need to be able to load anonymous classes
jrose
parents:
196
diff
changeset
|
470 assert(--inf_loop_check > 0, "no host_klass loop"); |
a45484ea312d
6653858: dynamic languages need to be able to load anonymous classes
jrose
parents:
196
diff
changeset
|
471 } |
a45484ea312d
6653858: dynamic languages need to be able to load anonymous classes
jrose
parents:
196
diff
changeset
|
472 } |
a45484ea312d
6653858: dynamic languages need to be able to load anonymous classes
jrose
parents:
196
diff
changeset
|
473 |
0 | 474 bool Reflection::can_relax_access_check_for( |
475 klassOop accessor, klassOop accessee, bool classloader_only) { | |
476 instanceKlass* accessor_ik = instanceKlass::cast(accessor); | |
477 instanceKlass* accessee_ik = instanceKlass::cast(accessee); | |
431
a45484ea312d
6653858: dynamic languages need to be able to load anonymous classes
jrose
parents:
196
diff
changeset
|
478 |
a45484ea312d
6653858: dynamic languages need to be able to load anonymous classes
jrose
parents:
196
diff
changeset
|
479 // If either is on the other's host_klass chain, access is OK, |
a45484ea312d
6653858: dynamic languages need to be able to load anonymous classes
jrose
parents:
196
diff
changeset
|
480 // because one is inside the other. |
a45484ea312d
6653858: dynamic languages need to be able to load anonymous classes
jrose
parents:
196
diff
changeset
|
481 if (under_host_klass(accessor_ik, accessee) || |
a45484ea312d
6653858: dynamic languages need to be able to load anonymous classes
jrose
parents:
196
diff
changeset
|
482 under_host_klass(accessee_ik, accessor)) |
a45484ea312d
6653858: dynamic languages need to be able to load anonymous classes
jrose
parents:
196
diff
changeset
|
483 return true; |
a45484ea312d
6653858: dynamic languages need to be able to load anonymous classes
jrose
parents:
196
diff
changeset
|
484 |
1152
cd37471eaecc
6914206: change way of permission checking for generated MethodHandle adapters
twisti
parents:
1142
diff
changeset
|
485 // Adapter frames can access anything. |
cd37471eaecc
6914206: change way of permission checking for generated MethodHandle adapters
twisti
parents:
1142
diff
changeset
|
486 if (MethodHandleCompiler::klass_is_method_handle_adapter_holder(accessor)) |
cd37471eaecc
6914206: change way of permission checking for generated MethodHandle adapters
twisti
parents:
1142
diff
changeset
|
487 // This is an internal adapter frame from the MethodHandleCompiler. |
cd37471eaecc
6914206: change way of permission checking for generated MethodHandle adapters
twisti
parents:
1142
diff
changeset
|
488 return true; |
cd37471eaecc
6914206: change way of permission checking for generated MethodHandle adapters
twisti
parents:
1142
diff
changeset
|
489 |
0 | 490 if (RelaxAccessControlCheck || |
491 (accessor_ik->major_version() < JAVA_1_5_VERSION && | |
492 accessee_ik->major_version() < JAVA_1_5_VERSION)) { | |
493 return classloader_only && | |
494 Verifier::relax_verify_for(accessor_ik->class_loader()) && | |
495 accessor_ik->protection_domain() == accessee_ik->protection_domain() && | |
496 accessor_ik->class_loader() == accessee_ik->class_loader(); | |
497 } else { | |
498 return false; | |
499 } | |
500 } | |
501 | |
502 bool Reflection::verify_field_access(klassOop current_class, | |
503 klassOop resolved_class, | |
504 klassOop field_class, | |
505 AccessFlags access, | |
506 bool classloader_only, | |
507 bool protected_restriction) { | |
508 // Verify that current_class can access a field of field_class, where that | |
509 // field's access bits are "access". We assume that we've already verified | |
510 // that current_class can access field_class. | |
511 // | |
512 // If the classloader_only flag is set, we automatically allow any accesses | |
513 // in which current_class doesn't have a classloader. | |
514 // | |
515 // "resolved_class" is the runtime type of "field_class". Sometimes we don't | |
516 // need this distinction (e.g. if all we have is the runtime type, or during | |
517 // class file parsing when we only care about the static type); in that case | |
518 // callers should ensure that resolved_class == field_class. | |
519 // | |
520 if ((current_class == NULL) || | |
521 (current_class == field_class) || | |
522 access.is_public()) { | |
523 return true; | |
524 } | |
525 | |
526 if (access.is_protected()) { | |
527 if (!protected_restriction) { | |
528 // See if current_class is a subclass of field_class | |
529 if (Klass::cast(current_class)->is_subclass_of(field_class)) { | |
115 | 530 if (access.is_static() || // static fields are ok, see 6622385 |
531 current_class == resolved_class || | |
0 | 532 field_class == resolved_class || |
533 Klass::cast(current_class)->is_subclass_of(resolved_class) || | |
534 Klass::cast(resolved_class)->is_subclass_of(current_class)) { | |
535 return true; | |
536 } | |
537 } | |
538 } | |
539 } | |
540 | |
541 if (!access.is_private() && is_same_class_package(current_class, field_class)) { | |
542 return true; | |
543 } | |
544 | |
545 // New (1.4) reflection implementation. Allow all accesses from | |
546 // sun/reflect/MagicAccessorImpl subclasses to succeed trivially. | |
547 if ( JDK_Version::is_gte_jdk14x_version() | |
548 && UseNewReflection | |
1142 | 549 && Klass::cast(current_class)->is_subclass_of(SystemDictionary::reflect_MagicAccessorImpl_klass())) { |
0 | 550 return true; |
551 } | |
552 | |
553 return can_relax_access_check_for( | |
554 current_class, field_class, classloader_only); | |
555 } | |
556 | |
557 | |
558 bool Reflection::is_same_class_package(klassOop class1, klassOop class2) { | |
559 return instanceKlass::cast(class1)->is_same_class_package(class2); | |
560 } | |
561 | |
665
c89f86385056
6814659: separable cleanups and subroutines for 6655638
jrose
parents:
431
diff
changeset
|
562 bool Reflection::is_same_package_member(klassOop class1, klassOop class2, TRAPS) { |
c89f86385056
6814659: separable cleanups and subroutines for 6655638
jrose
parents:
431
diff
changeset
|
563 return instanceKlass::cast(class1)->is_same_package_member(class2, THREAD); |
c89f86385056
6814659: separable cleanups and subroutines for 6655638
jrose
parents:
431
diff
changeset
|
564 } |
c89f86385056
6814659: separable cleanups and subroutines for 6655638
jrose
parents:
431
diff
changeset
|
565 |
0 | 566 |
567 // Checks that the 'outer' klass has declared 'inner' as being an inner klass. If not, | |
568 // throw an incompatible class change exception | |
665
c89f86385056
6814659: separable cleanups and subroutines for 6655638
jrose
parents:
431
diff
changeset
|
569 // If inner_is_member, require the inner to be a member of the outer. |
c89f86385056
6814659: separable cleanups and subroutines for 6655638
jrose
parents:
431
diff
changeset
|
570 // If !inner_is_member, require the inner to be anonymous (a non-member). |
c89f86385056
6814659: separable cleanups and subroutines for 6655638
jrose
parents:
431
diff
changeset
|
571 // Caller is responsible for figuring out in advance which case must be true. |
c89f86385056
6814659: separable cleanups and subroutines for 6655638
jrose
parents:
431
diff
changeset
|
572 void Reflection::check_for_inner_class(instanceKlassHandle outer, instanceKlassHandle inner, |
c89f86385056
6814659: separable cleanups and subroutines for 6655638
jrose
parents:
431
diff
changeset
|
573 bool inner_is_member, TRAPS) { |
0 | 574 const int inner_class_info_index = 0; |
575 const int outer_class_info_index = 1; | |
576 | |
577 typeArrayHandle icls (THREAD, outer->inner_classes()); | |
578 constantPoolHandle cp (THREAD, outer->constants()); | |
579 for(int i = 0; i < icls->length(); i += 4) { | |
580 int ioff = icls->ushort_at(i + inner_class_info_index); | |
581 int ooff = icls->ushort_at(i + outer_class_info_index); | |
582 | |
665
c89f86385056
6814659: separable cleanups and subroutines for 6655638
jrose
parents:
431
diff
changeset
|
583 if (inner_is_member && ioff != 0 && ooff != 0) { |
0 | 584 klassOop o = cp->klass_at(ooff, CHECK); |
585 if (o == outer()) { | |
586 klassOop i = cp->klass_at(ioff, CHECK); | |
587 if (i == inner()) { | |
588 return; | |
589 } | |
590 } | |
591 } | |
665
c89f86385056
6814659: separable cleanups and subroutines for 6655638
jrose
parents:
431
diff
changeset
|
592 if (!inner_is_member && ioff != 0 && ooff == 0 && |
c89f86385056
6814659: separable cleanups and subroutines for 6655638
jrose
parents:
431
diff
changeset
|
593 cp->klass_name_at_matches(inner, ioff)) { |
c89f86385056
6814659: separable cleanups and subroutines for 6655638
jrose
parents:
431
diff
changeset
|
594 klassOop i = cp->klass_at(ioff, CHECK); |
c89f86385056
6814659: separable cleanups and subroutines for 6655638
jrose
parents:
431
diff
changeset
|
595 if (i == inner()) { |
c89f86385056
6814659: separable cleanups and subroutines for 6655638
jrose
parents:
431
diff
changeset
|
596 return; |
c89f86385056
6814659: separable cleanups and subroutines for 6655638
jrose
parents:
431
diff
changeset
|
597 } |
c89f86385056
6814659: separable cleanups and subroutines for 6655638
jrose
parents:
431
diff
changeset
|
598 } |
0 | 599 } |
600 | |
601 // 'inner' not declared as an inner klass in outer | |
602 ResourceMark rm(THREAD); | |
603 Exceptions::fthrow( | |
604 THREAD_AND_LOCATION, | |
605 vmSymbolHandles::java_lang_IncompatibleClassChangeError(), | |
606 "%s and %s disagree on InnerClasses attribute", | |
607 outer->external_name(), | |
608 inner->external_name() | |
609 ); | |
610 } | |
611 | |
612 // Utility method converting a single SignatureStream element into java.lang.Class instance | |
613 | |
614 oop get_mirror_from_signature(methodHandle method, SignatureStream* ss, TRAPS) { | |
615 switch (ss->type()) { | |
616 default: | |
617 assert(ss->type() != T_VOID || ss->at_return_type(), "T_VOID should only appear as return type"); | |
618 return java_lang_Class::primitive_mirror(ss->type()); | |
619 case T_OBJECT: | |
620 case T_ARRAY: | |
621 symbolOop name = ss->as_symbol(CHECK_NULL); | |
622 oop loader = instanceKlass::cast(method->method_holder())->class_loader(); | |
623 oop protection_domain = instanceKlass::cast(method->method_holder())->protection_domain(); | |
624 klassOop k = SystemDictionary::resolve_or_fail( | |
625 symbolHandle(THREAD, name), | |
626 Handle(THREAD, loader), | |
627 Handle(THREAD, protection_domain), | |
628 true, CHECK_NULL); | |
629 if (TraceClassResolution) { | |
630 trace_class_resolution(k); | |
631 } | |
632 return k->klass_part()->java_mirror(); | |
633 }; | |
634 } | |
635 | |
636 | |
637 objArrayHandle Reflection::get_parameter_types(methodHandle method, int parameter_count, oop* return_type, TRAPS) { | |
638 // Allocate array holding parameter types (java.lang.Class instances) | |
1142 | 639 objArrayOop m = oopFactory::new_objArray(SystemDictionary::Class_klass(), parameter_count, CHECK_(objArrayHandle())); |
0 | 640 objArrayHandle mirrors (THREAD, m); |
641 int index = 0; | |
642 // Collect parameter types | |
643 symbolHandle signature (THREAD, method->signature()); | |
644 SignatureStream ss(signature); | |
645 while (!ss.at_return_type()) { | |
646 oop mirror = get_mirror_from_signature(method, &ss, CHECK_(objArrayHandle())); | |
647 mirrors->obj_at_put(index++, mirror); | |
648 ss.next(); | |
649 } | |
650 assert(index == parameter_count, "invalid parameter count"); | |
651 if (return_type != NULL) { | |
652 // Collect return type as well | |
653 assert(ss.at_return_type(), "return type should be present"); | |
654 *return_type = get_mirror_from_signature(method, &ss, CHECK_(objArrayHandle())); | |
655 } | |
656 return mirrors; | |
657 } | |
658 | |
659 objArrayHandle Reflection::get_exception_types(methodHandle method, TRAPS) { | |
660 return method->resolved_checked_exceptions(CHECK_(objArrayHandle())); | |
661 } | |
662 | |
663 | |
664 Handle Reflection::new_type(symbolHandle signature, KlassHandle k, TRAPS) { | |
665 // Basic types | |
666 BasicType type = vmSymbols::signature_type(signature()); | |
667 if (type != T_OBJECT) { | |
668 return Handle(THREAD, Universe::java_mirror(type)); | |
669 } | |
670 | |
671 oop loader = instanceKlass::cast(k())->class_loader(); | |
672 oop protection_domain = Klass::cast(k())->protection_domain(); | |
673 klassOop result = SystemDictionary::resolve_or_fail(signature, | |
674 Handle(THREAD, loader), | |
675 Handle(THREAD, protection_domain), | |
676 true, CHECK_(Handle())); | |
677 | |
678 if (TraceClassResolution) { | |
679 trace_class_resolution(result); | |
680 } | |
681 | |
682 oop nt = Klass::cast(result)->java_mirror(); | |
683 return Handle(THREAD, nt); | |
684 } | |
685 | |
686 | |
687 oop Reflection::new_method(methodHandle method, bool intern_name, bool for_constant_pool_access, TRAPS) { | |
688 // In jdk1.2.x, getMethods on an interface erroneously includes <clinit>, thus the complicated assert. | |
689 // Also allow sun.reflect.ConstantPool to refer to <clinit> methods as java.lang.reflect.Methods. | |
690 assert(!method()->is_initializer() || | |
691 (for_constant_pool_access && method()->is_static()) || | |
692 (method()->name() == vmSymbols::class_initializer_name() | |
693 && Klass::cast(method()->method_holder())->is_interface() && JDK_Version::is_jdk12x_version()), "should call new_constructor instead"); | |
694 instanceKlassHandle holder (THREAD, method->method_holder()); | |
695 int slot = method->method_idnum(); | |
696 | |
697 symbolHandle signature (THREAD, method->signature()); | |
698 int parameter_count = ArgumentCount(signature).size(); | |
699 oop return_type_oop = NULL; | |
700 objArrayHandle parameter_types = get_parameter_types(method, parameter_count, &return_type_oop, CHECK_NULL); | |
701 if (parameter_types.is_null() || return_type_oop == NULL) return NULL; | |
702 | |
703 Handle return_type(THREAD, return_type_oop); | |
704 | |
705 objArrayHandle exception_types = get_exception_types(method, CHECK_NULL); | |
706 | |
707 if (exception_types.is_null()) return NULL; | |
708 | |
709 symbolHandle method_name(THREAD, method->name()); | |
710 Handle name; | |
711 if (intern_name) { | |
712 // intern_name is only true with UseNewReflection | |
713 oop name_oop = StringTable::intern(method_name(), CHECK_NULL); | |
714 name = Handle(THREAD, name_oop); | |
715 } else { | |
716 name = java_lang_String::create_from_symbol(method_name, CHECK_NULL); | |
717 } | |
718 if (name.is_null()) return NULL; | |
719 | |
720 int modifiers = method->access_flags().as_int() & JVM_RECOGNIZED_METHOD_MODIFIERS; | |
721 | |
722 Handle mh = java_lang_reflect_Method::create(CHECK_NULL); | |
723 | |
724 java_lang_reflect_Method::set_clazz(mh(), holder->java_mirror()); | |
725 java_lang_reflect_Method::set_slot(mh(), slot); | |
726 java_lang_reflect_Method::set_name(mh(), name()); | |
727 java_lang_reflect_Method::set_return_type(mh(), return_type()); | |
728 java_lang_reflect_Method::set_parameter_types(mh(), parameter_types()); | |
729 java_lang_reflect_Method::set_exception_types(mh(), exception_types()); | |
730 java_lang_reflect_Method::set_modifiers(mh(), modifiers); | |
731 java_lang_reflect_Method::set_override(mh(), false); | |
732 if (java_lang_reflect_Method::has_signature_field() && | |
733 method->generic_signature() != NULL) { | |
734 symbolHandle gs(THREAD, method->generic_signature()); | |
735 Handle sig = java_lang_String::create_from_symbol(gs, CHECK_NULL); | |
736 java_lang_reflect_Method::set_signature(mh(), sig()); | |
737 } | |
738 if (java_lang_reflect_Method::has_annotations_field()) { | |
739 java_lang_reflect_Method::set_annotations(mh(), method->annotations()); | |
740 } | |
741 if (java_lang_reflect_Method::has_parameter_annotations_field()) { | |
742 java_lang_reflect_Method::set_parameter_annotations(mh(), method->parameter_annotations()); | |
743 } | |
744 if (java_lang_reflect_Method::has_annotation_default_field()) { | |
745 java_lang_reflect_Method::set_annotation_default(mh(), method->annotation_default()); | |
746 } | |
747 return mh(); | |
748 } | |
749 | |
750 | |
751 oop Reflection::new_constructor(methodHandle method, TRAPS) { | |
752 assert(method()->is_initializer(), "should call new_method instead"); | |
753 | |
754 instanceKlassHandle holder (THREAD, method->method_holder()); | |
755 int slot = method->method_idnum(); | |
756 | |
757 symbolHandle signature (THREAD, method->signature()); | |
758 int parameter_count = ArgumentCount(signature).size(); | |
759 objArrayHandle parameter_types = get_parameter_types(method, parameter_count, NULL, CHECK_NULL); | |
760 if (parameter_types.is_null()) return NULL; | |
761 | |
762 objArrayHandle exception_types = get_exception_types(method, CHECK_NULL); | |
763 if (exception_types.is_null()) return NULL; | |
764 | |
765 int modifiers = method->access_flags().as_int() & JVM_RECOGNIZED_METHOD_MODIFIERS; | |
766 | |
767 Handle ch = java_lang_reflect_Constructor::create(CHECK_NULL); | |
768 | |
769 java_lang_reflect_Constructor::set_clazz(ch(), holder->java_mirror()); | |
770 java_lang_reflect_Constructor::set_slot(ch(), slot); | |
771 java_lang_reflect_Constructor::set_parameter_types(ch(), parameter_types()); | |
772 java_lang_reflect_Constructor::set_exception_types(ch(), exception_types()); | |
773 java_lang_reflect_Constructor::set_modifiers(ch(), modifiers); | |
774 java_lang_reflect_Constructor::set_override(ch(), false); | |
775 if (java_lang_reflect_Constructor::has_signature_field() && | |
776 method->generic_signature() != NULL) { | |
777 symbolHandle gs(THREAD, method->generic_signature()); | |
778 Handle sig = java_lang_String::create_from_symbol(gs, CHECK_NULL); | |
779 java_lang_reflect_Constructor::set_signature(ch(), sig()); | |
780 } | |
781 if (java_lang_reflect_Constructor::has_annotations_field()) { | |
782 java_lang_reflect_Constructor::set_annotations(ch(), method->annotations()); | |
783 } | |
784 if (java_lang_reflect_Constructor::has_parameter_annotations_field()) { | |
785 java_lang_reflect_Constructor::set_parameter_annotations(ch(), method->parameter_annotations()); | |
786 } | |
787 return ch(); | |
788 } | |
789 | |
790 | |
791 oop Reflection::new_field(fieldDescriptor* fd, bool intern_name, TRAPS) { | |
792 symbolHandle field_name(THREAD, fd->name()); | |
793 Handle name; | |
794 if (intern_name) { | |
795 // intern_name is only true with UseNewReflection | |
796 oop name_oop = StringTable::intern(field_name(), CHECK_NULL); | |
797 name = Handle(THREAD, name_oop); | |
798 } else { | |
799 name = java_lang_String::create_from_symbol(field_name, CHECK_NULL); | |
800 } | |
801 symbolHandle signature (THREAD, fd->signature()); | |
802 KlassHandle holder (THREAD, fd->field_holder()); | |
803 Handle type = new_type(signature, holder, CHECK_NULL); | |
804 Handle rh = java_lang_reflect_Field::create(CHECK_NULL); | |
805 | |
806 java_lang_reflect_Field::set_clazz(rh(), Klass::cast(fd->field_holder())->java_mirror()); | |
807 java_lang_reflect_Field::set_slot(rh(), fd->index()); | |
808 java_lang_reflect_Field::set_name(rh(), name()); | |
809 java_lang_reflect_Field::set_type(rh(), type()); | |
810 // Note the ACC_ANNOTATION bit, which is a per-class access flag, is never set here. | |
811 java_lang_reflect_Field::set_modifiers(rh(), fd->access_flags().as_int() & JVM_RECOGNIZED_FIELD_MODIFIERS); | |
812 java_lang_reflect_Field::set_override(rh(), false); | |
813 if (java_lang_reflect_Field::has_signature_field() && | |
814 fd->generic_signature() != NULL) { | |
815 symbolHandle gs(THREAD, fd->generic_signature()); | |
816 Handle sig = java_lang_String::create_from_symbol(gs, CHECK_NULL); | |
817 java_lang_reflect_Field::set_signature(rh(), sig()); | |
818 } | |
819 if (java_lang_reflect_Field::has_annotations_field()) { | |
820 java_lang_reflect_Field::set_annotations(rh(), fd->annotations()); | |
821 } | |
822 return rh(); | |
823 } | |
824 | |
825 | |
826 //--------------------------------------------------------------------------- | |
827 // | |
828 // Supporting routines for old native code-based reflection (pre-JDK 1.4). | |
829 // | |
830 // See reflection.hpp for details. | |
831 // | |
832 //--------------------------------------------------------------------------- | |
833 | |
834 #ifdef SUPPORT_OLD_REFLECTION | |
835 | |
836 methodHandle Reflection::resolve_interface_call(instanceKlassHandle klass, methodHandle method, | |
837 KlassHandle recv_klass, Handle receiver, TRAPS) { | |
838 assert(!method.is_null() , "method should not be null"); | |
839 | |
840 CallInfo info; | |
841 symbolHandle signature (THREAD, method->signature()); | |
842 symbolHandle name (THREAD, method->name()); | |
843 LinkResolver::resolve_interface_call(info, receiver, recv_klass, klass, | |
844 name, signature, | |
845 KlassHandle(), false, true, | |
846 CHECK_(methodHandle())); | |
847 return info.selected_method(); | |
848 } | |
849 | |
850 | |
851 oop Reflection::invoke(instanceKlassHandle klass, methodHandle reflected_method, | |
852 Handle receiver, bool override, objArrayHandle ptypes, | |
853 BasicType rtype, objArrayHandle args, bool is_method_invoke, TRAPS) { | |
854 ResourceMark rm(THREAD); | |
855 | |
856 methodHandle method; // actual method to invoke | |
857 KlassHandle target_klass; // target klass, receiver's klass for non-static | |
858 | |
859 // Ensure klass is initialized | |
860 klass->initialize(CHECK_NULL); | |
861 | |
862 bool is_static = reflected_method->is_static(); | |
863 if (is_static) { | |
864 // ignore receiver argument | |
865 method = reflected_method; | |
866 target_klass = klass; | |
867 } else { | |
868 // check for null receiver | |
869 if (receiver.is_null()) { | |
870 THROW_0(vmSymbols::java_lang_NullPointerException()); | |
871 } | |
872 // Check class of receiver against class declaring method | |
873 if (!receiver->is_a(klass())) { | |
874 THROW_MSG_0(vmSymbols::java_lang_IllegalArgumentException(), "object is not an instance of declaring class"); | |
875 } | |
876 // target klass is receiver's klass | |
877 target_klass = KlassHandle(THREAD, receiver->klass()); | |
878 // no need to resolve if method is private or <init> | |
879 if (reflected_method->is_private() || reflected_method->name() == vmSymbols::object_initializer_name()) { | |
880 method = reflected_method; | |
881 } else { | |
882 // resolve based on the receiver | |
883 if (instanceKlass::cast(reflected_method->method_holder())->is_interface()) { | |
884 // resolve interface call | |
885 if (ReflectionWrapResolutionErrors) { | |
886 // new default: 6531596 | |
887 // Match resolution errors with those thrown due to reflection inlining | |
888 // Linktime resolution & IllegalAccessCheck already done by Class.getMethod() | |
889 method = resolve_interface_call(klass, reflected_method, target_klass, receiver, THREAD); | |
890 if (HAS_PENDING_EXCEPTION) { | |
891 // Method resolution threw an exception; wrap it in an InvocationTargetException | |
892 oop resolution_exception = PENDING_EXCEPTION; | |
893 CLEAR_PENDING_EXCEPTION; | |
894 JavaCallArguments args(Handle(THREAD, resolution_exception)); | |
895 THROW_ARG_0(vmSymbolHandles::java_lang_reflect_InvocationTargetException(), | |
896 vmSymbolHandles::throwable_void_signature(), | |
897 &args); | |
898 } | |
899 } else { | |
900 method = resolve_interface_call(klass, reflected_method, target_klass, receiver, CHECK_(NULL)); | |
901 } | |
902 } else { | |
903 // if the method can be overridden, we resolve using the vtable index. | |
904 int index = reflected_method->vtable_index(); | |
905 method = reflected_method; | |
906 if (index != methodOopDesc::nonvirtual_vtable_index) { | |
907 // target_klass might be an arrayKlassOop but all vtables start at | |
908 // the same place. The cast is to avoid virtual call and assertion. | |
909 instanceKlass* inst = (instanceKlass*)target_klass()->klass_part(); | |
910 method = methodHandle(THREAD, inst->method_at_vtable(index)); | |
911 } | |
912 if (!method.is_null()) { | |
913 // Check for abstract methods as well | |
914 if (method->is_abstract()) { | |
915 // new default: 6531596 | |
916 if (ReflectionWrapResolutionErrors) { | |
917 ResourceMark rm(THREAD); | |
918 Handle h_origexception = Exceptions::new_exception(THREAD, | |
919 vmSymbols::java_lang_AbstractMethodError(), | |
920 methodOopDesc::name_and_sig_as_C_string(Klass::cast(target_klass()), | |
921 method->name(), | |
922 method->signature())); | |
923 JavaCallArguments args(h_origexception); | |
924 THROW_ARG_0(vmSymbolHandles::java_lang_reflect_InvocationTargetException(), | |
925 vmSymbolHandles::throwable_void_signature(), | |
926 &args); | |
927 } else { | |
928 ResourceMark rm(THREAD); | |
929 THROW_MSG_0(vmSymbols::java_lang_AbstractMethodError(), | |
930 methodOopDesc::name_and_sig_as_C_string(Klass::cast(target_klass()), | |
931 method->name(), | |
932 method->signature())); | |
933 } | |
934 } | |
935 } | |
936 } | |
937 } | |
938 } | |
939 | |
940 // I believe this is a ShouldNotGetHere case which requires | |
941 // an internal vtable bug. If you ever get this please let Karen know. | |
942 if (method.is_null()) { | |
943 ResourceMark rm(THREAD); | |
944 THROW_MSG_0(vmSymbols::java_lang_NoSuchMethodError(), | |
945 methodOopDesc::name_and_sig_as_C_string(Klass::cast(klass()), | |
946 reflected_method->name(), | |
947 reflected_method->signature())); | |
948 } | |
949 | |
950 // In the JDK 1.4 reflection implementation, the security check is | |
951 // done at the Java level | |
952 if (!(JDK_Version::is_gte_jdk14x_version() && UseNewReflection)) { | |
953 | |
954 // Access checking (unless overridden by Method) | |
955 if (!override) { | |
956 if (!(klass->is_public() && reflected_method->is_public())) { | |
957 bool access = Reflection::reflect_check_access(klass(), reflected_method->access_flags(), target_klass(), is_method_invoke, CHECK_NULL); | |
958 if (!access) { | |
959 return NULL; // exception | |
960 } | |
961 } | |
962 } | |
963 | |
964 } // !(Universe::is_gte_jdk14x_version() && UseNewReflection) | |
965 | |
966 assert(ptypes->is_objArray(), "just checking"); | |
967 int args_len = args.is_null() ? 0 : args->length(); | |
968 // Check number of arguments | |
969 if (ptypes->length() != args_len) { | |
970 THROW_MSG_0(vmSymbols::java_lang_IllegalArgumentException(), "wrong number of arguments"); | |
971 } | |
972 | |
973 // Create object to contain parameters for the JavaCall | |
974 JavaCallArguments java_args(method->size_of_parameters()); | |
975 | |
976 if (!is_static) { | |
977 java_args.push_oop(receiver); | |
978 } | |
979 | |
980 for (int i = 0; i < args_len; i++) { | |
981 oop type_mirror = ptypes->obj_at(i); | |
982 oop arg = args->obj_at(i); | |
983 if (java_lang_Class::is_primitive(type_mirror)) { | |
984 jvalue value; | |
985 BasicType ptype = basic_type_mirror_to_basic_type(type_mirror, CHECK_NULL); | |
986 BasicType atype = unbox_for_primitive(arg, &value, CHECK_NULL); | |
987 if (ptype != atype) { | |
988 widen(&value, atype, ptype, CHECK_NULL); | |
989 } | |
990 switch (ptype) { | |
991 case T_BOOLEAN: java_args.push_int(value.z); break; | |
992 case T_CHAR: java_args.push_int(value.c); break; | |
993 case T_BYTE: java_args.push_int(value.b); break; | |
994 case T_SHORT: java_args.push_int(value.s); break; | |
995 case T_INT: java_args.push_int(value.i); break; | |
996 case T_LONG: java_args.push_long(value.j); break; | |
997 case T_FLOAT: java_args.push_float(value.f); break; | |
998 case T_DOUBLE: java_args.push_double(value.d); break; | |
999 default: | |
1000 THROW_MSG_0(vmSymbols::java_lang_IllegalArgumentException(), "argument type mismatch"); | |
1001 } | |
1002 } else { | |
1003 if (arg != NULL) { | |
1004 klassOop k = java_lang_Class::as_klassOop(type_mirror); | |
1005 if (!arg->is_a(k)) { | |
1006 THROW_MSG_0(vmSymbols::java_lang_IllegalArgumentException(), "argument type mismatch"); | |
1007 } | |
1008 } | |
1009 Handle arg_handle(THREAD, arg); // Create handle for argument | |
1010 java_args.push_oop(arg_handle); // Push handle | |
1011 } | |
1012 } | |
1013 | |
1014 assert(java_args.size_of_parameters() == method->size_of_parameters(), "just checking"); | |
1015 | |
1016 // All oops (including receiver) is passed in as Handles. An potential oop is returned as an | |
1017 // oop (i.e., NOT as an handle) | |
1018 JavaValue result(rtype); | |
1019 JavaCalls::call(&result, method, &java_args, THREAD); | |
1020 | |
1021 if (HAS_PENDING_EXCEPTION) { | |
1022 // Method threw an exception; wrap it in an InvocationTargetException | |
1023 oop target_exception = PENDING_EXCEPTION; | |
1024 CLEAR_PENDING_EXCEPTION; | |
1025 JavaCallArguments args(Handle(THREAD, target_exception)); | |
1026 THROW_ARG_0(vmSymbolHandles::java_lang_reflect_InvocationTargetException(), | |
1027 vmSymbolHandles::throwable_void_signature(), | |
1028 &args); | |
1029 } else { | |
1030 if (rtype == T_BOOLEAN || rtype == T_BYTE || rtype == T_CHAR || rtype == T_SHORT) | |
1031 narrow((jvalue*) result.get_value_addr(), rtype, CHECK_NULL); | |
1032 return box((jvalue*) result.get_value_addr(), rtype, CHECK_NULL); | |
1033 } | |
1034 } | |
1035 | |
1036 | |
1037 void Reflection::narrow(jvalue* value, BasicType narrow_type, TRAPS) { | |
1038 switch (narrow_type) { | |
1039 case T_BOOLEAN: | |
1040 value->z = (jboolean) value->i; | |
1041 return; | |
1042 case T_BYTE: | |
1043 value->b = (jbyte) value->i; | |
1044 return; | |
1045 case T_CHAR: | |
1046 value->c = (jchar) value->i; | |
1047 return; | |
1048 case T_SHORT: | |
1049 value->s = (jshort) value->i; | |
1050 return; | |
1051 default: | |
1052 break; // fail | |
1053 } | |
1054 THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(), "argument type mismatch"); | |
1055 } | |
1056 | |
1057 | |
1058 BasicType Reflection::basic_type_mirror_to_basic_type(oop basic_type_mirror, TRAPS) { | |
1059 assert(java_lang_Class::is_primitive(basic_type_mirror), "just checking"); | |
1060 return java_lang_Class::primitive_type(basic_type_mirror); | |
1061 } | |
1062 | |
1063 | |
1064 bool Reflection::match_parameter_types(methodHandle method, objArrayHandle types, int parameter_count, TRAPS) { | |
1065 int types_len = types.is_null() ? 0 : types->length(); | |
1066 if (types_len != parameter_count) return false; | |
1067 if (parameter_count > 0) { | |
1068 objArrayHandle method_types = get_parameter_types(method, parameter_count, NULL, CHECK_false); | |
1069 for (int index = 0; index < parameter_count; index++) { | |
1070 if (types->obj_at(index) != method_types->obj_at(index)) { | |
1071 return false; | |
1072 } | |
1073 } | |
1074 } | |
1075 return true; | |
1076 } | |
1077 | |
1078 | |
1079 oop Reflection::new_field(FieldStream* st, TRAPS) { | |
1080 symbolHandle field_name(THREAD, st->name()); | |
1081 Handle name = java_lang_String::create_from_symbol(field_name, CHECK_NULL); | |
1082 symbolHandle signature(THREAD, st->signature()); | |
1083 Handle type = new_type(signature, st->klass(), CHECK_NULL); | |
1084 Handle rh = java_lang_reflect_Field::create(CHECK_NULL); | |
1085 oop result = rh(); | |
1086 | |
1087 java_lang_reflect_Field::set_clazz(result, st->klass()->java_mirror()); | |
1088 java_lang_reflect_Field::set_slot(result, st->index()); | |
1089 java_lang_reflect_Field::set_name(result, name()); | |
1090 java_lang_reflect_Field::set_type(result, type()); | |
1091 // Note the ACC_ANNOTATION bit, which is a per-class access flag, is never set here. | |
1092 java_lang_reflect_Field::set_modifiers(result, st->access_flags().as_int() & JVM_RECOGNIZED_FIELD_MODIFIERS); | |
1093 java_lang_reflect_Field::set_override(result, false); | |
1094 return result; | |
1095 } | |
1096 | |
1097 | |
1098 bool Reflection::resolve_field(Handle field_mirror, Handle& receiver, fieldDescriptor* fd, bool check_final, TRAPS) { | |
1099 if (field_mirror.is_null()) { | |
1100 THROW_(vmSymbols::java_lang_NullPointerException(), false); | |
1101 } | |
1102 | |
1103 instanceKlassHandle klass (THREAD, java_lang_Class::as_klassOop(java_lang_reflect_Field::clazz(field_mirror()))); | |
1104 int slot = java_lang_reflect_Field::slot(field_mirror()); | |
1105 | |
1106 // Ensure klass is initialized | |
1107 klass->initialize(CHECK_false); | |
1108 fd->initialize(klass(), slot); | |
1109 | |
1110 bool is_static = fd->is_static(); | |
1111 KlassHandle receiver_klass; | |
1112 | |
1113 if (is_static) { | |
1114 receiver = KlassHandle(THREAD, klass()); | |
1115 receiver_klass = klass; | |
1116 } else { | |
1117 // Check object is a non-null instance of declaring class | |
1118 if (receiver.is_null()) { | |
1119 THROW_(vmSymbols::java_lang_NullPointerException(), false); | |
1120 } | |
1121 if (!receiver->is_a(klass())) { | |
1122 THROW_MSG_(vmSymbols::java_lang_IllegalArgumentException(), "object is not an instance of declaring class", false); | |
1123 } | |
1124 receiver_klass = KlassHandle(THREAD, receiver->klass()); | |
1125 } | |
1126 | |
1127 // Access checking (unless overridden by Field) | |
1128 if (!java_lang_reflect_Field::override(field_mirror())) { | |
1129 if (!(klass->is_public() && fd->is_public())) { | |
1130 bool access_check = reflect_check_access(klass(), fd->access_flags(), receiver_klass(), false, CHECK_false); | |
1131 if (!access_check) { | |
1132 return false; // exception | |
1133 } | |
1134 } | |
1135 } | |
1136 | |
1137 if (check_final && fd->is_final()) { | |
1138 // In 1.3 we always throw an error when attempting to set a final field. | |
1139 // In 1.2.x, this was allowed in the override bit was set by calling Field.setAccessible(true). | |
1140 // We currently maintain backwards compatibility. See bug 4250960. | |
1141 bool strict_final_check = !JDK_Version::is_jdk12x_version(); | |
1142 if (strict_final_check || !java_lang_reflect_Field::override(field_mirror())) { | |
1143 THROW_MSG_(vmSymbols::java_lang_IllegalAccessException(), "field is final", false); | |
1144 } | |
1145 } | |
1146 return true; | |
1147 } | |
1148 | |
1149 | |
1150 BasicType Reflection::field_get(jvalue* value, fieldDescriptor* fd, Handle receiver) { | |
1151 BasicType field_type = fd->field_type(); | |
1152 int offset = fd->offset(); | |
1153 switch (field_type) { | |
1154 case T_BOOLEAN: | |
1155 value->z = receiver->bool_field(offset); | |
1156 break; | |
1157 case T_CHAR: | |
1158 value->c = receiver->char_field(offset); | |
1159 break; | |
1160 case T_FLOAT: | |
1161 value->f = receiver->float_field(offset); | |
1162 break; | |
1163 case T_DOUBLE: | |
1164 value->d = receiver->double_field(offset); | |
1165 break; | |
1166 case T_BYTE: | |
1167 value->b = receiver->byte_field(offset); | |
1168 break; | |
1169 case T_SHORT: | |
1170 value->s = receiver->short_field(offset); | |
1171 break; | |
1172 case T_INT: | |
1173 value->i = receiver->int_field(offset); | |
1174 break; | |
1175 case T_LONG: | |
1176 value->j = receiver->long_field(offset); | |
1177 break; | |
1178 case T_OBJECT: | |
1179 case T_ARRAY: | |
1180 value->l = (jobject) receiver->obj_field(offset); | |
1181 break; | |
1182 default: | |
1183 return T_ILLEGAL; | |
1184 } | |
1185 return field_type; | |
1186 } | |
1187 | |
1188 | |
1189 void Reflection::field_set(jvalue* value, fieldDescriptor* fd, Handle receiver, BasicType value_type, TRAPS) { | |
1190 BasicType field_type = fd->field_type(); | |
1191 if (field_type != value_type) { | |
1192 widen(value, value_type, field_type, CHECK); | |
1193 } | |
1194 | |
1195 int offset = fd->offset(); | |
1196 switch (field_type) { | |
1197 case T_BOOLEAN: | |
1198 receiver->bool_field_put(offset, value->z); | |
1199 break; | |
1200 case T_CHAR: | |
1201 receiver->char_field_put(offset, value->c); | |
1202 break; | |
1203 case T_FLOAT: | |
1204 receiver->float_field_put(offset, value->f); | |
1205 break; | |
1206 case T_DOUBLE: | |
1207 receiver->double_field_put(offset, value->d); | |
1208 break; | |
1209 case T_BYTE: | |
1210 receiver->byte_field_put(offset, value->b); | |
1211 break; | |
1212 case T_SHORT: | |
1213 receiver->short_field_put(offset, value->s); | |
1214 break; | |
1215 case T_INT: | |
1216 receiver->int_field_put(offset, value->i); | |
1217 break; | |
1218 case T_LONG: | |
1219 receiver->long_field_put(offset, value->j); | |
1220 break; | |
1221 case T_OBJECT: | |
1222 case T_ARRAY: { | |
1223 Handle obj(THREAD, (oop) value->l); | |
1224 if (obj.not_null()) { | |
1225 symbolHandle signature(THREAD, fd->signature()); | |
1226 Handle loader (THREAD, fd->loader()); | |
1227 Handle protect (THREAD, Klass::cast(fd->field_holder())->protection_domain()); | |
1228 klassOop k = SystemDictionary::resolve_or_fail(signature, loader, protect, true, CHECK); // may block | |
1229 if (!obj->is_a(k)) { | |
1230 THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(), "field type mismatch"); | |
1231 } | |
1232 } | |
1233 receiver->obj_field_put(offset, obj()); | |
1234 break; | |
1235 } | |
1236 default: | |
1237 THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(), "field type mismatch"); | |
1238 } | |
1239 } | |
1240 | |
1241 | |
1242 oop Reflection::reflect_field(oop mirror, symbolOop field_name, jint which, TRAPS) { | |
1243 // Exclude primitive types and array types | |
1244 if (java_lang_Class::is_primitive(mirror)) return NULL; | |
1245 if (Klass::cast(java_lang_Class::as_klassOop(mirror))->oop_is_array()) return NULL; | |
1246 | |
1247 instanceKlassHandle k(THREAD, java_lang_Class::as_klassOop(mirror)); | |
1248 bool local_fields_only = (which == DECLARED); | |
1249 | |
1250 // Ensure class is linked | |
1251 k->link_class(CHECK_NULL); | |
1252 | |
1253 // Search class and interface fields | |
1254 for (FieldStream st(k, local_fields_only, false); !st.eos(); st.next()) { | |
1255 if (st.name() == field_name) { | |
1256 if (local_fields_only || st.access_flags().is_public()) { | |
1257 return new_field(&st, THREAD); | |
1258 } | |
1259 } | |
1260 } | |
1261 | |
1262 return NULL; | |
1263 } | |
1264 | |
1265 | |
1266 objArrayOop Reflection::reflect_fields(oop mirror, jint which, TRAPS) { | |
1267 // Exclude primitive types and array types | |
1268 if (java_lang_Class::is_primitive(mirror) | |
1269 || Klass::cast(java_lang_Class::as_klassOop(mirror))->oop_is_array()) { | |
1270 symbolHandle name = vmSymbolHandles::java_lang_reflect_Field(); | |
1271 klassOop klass = SystemDictionary::resolve_or_fail(name, true, CHECK_NULL); | |
1272 return oopFactory::new_objArray(klass, 0, CHECK_NULL); // Return empty array | |
1273 } | |
1274 | |
1275 instanceKlassHandle k(THREAD, java_lang_Class::as_klassOop(mirror)); | |
1276 | |
1277 // Ensure class is linked | |
1278 k->link_class(CHECK_NULL); | |
1279 | |
1280 bool local_fields_only = (which == DECLARED); | |
1281 int count = 0; | |
1282 { // Compute fields count for class and interface fields | |
1283 for (FieldStream st(k, local_fields_only, false); !st.eos(); st.next()) { | |
1284 if (local_fields_only || st.access_flags().is_public()) { | |
1285 count++; | |
1286 } | |
1287 } | |
1288 } | |
1289 | |
1290 // Allocate result | |
1291 symbolHandle name = vmSymbolHandles::java_lang_reflect_Field(); | |
1292 klassOop klass = SystemDictionary::resolve_or_fail(name, true, CHECK_NULL); | |
1293 objArrayOop r = oopFactory::new_objArray(klass, count, CHECK_NULL); | |
1294 objArrayHandle result (THREAD, r); | |
1295 | |
1296 // Fill in results backwards | |
1297 { | |
1298 for (FieldStream st(k, local_fields_only, false); !st.eos(); st.next()) { | |
1299 if (local_fields_only || st.access_flags().is_public()) { | |
1300 oop field = new_field(&st, CHECK_NULL); | |
1301 result->obj_at_put(--count, field); | |
1302 } | |
1303 } | |
1304 assert(count == 0, "just checking"); | |
1305 } | |
1306 return result(); | |
1307 } | |
1308 | |
1309 | |
1310 oop Reflection::reflect_method(oop mirror, symbolHandle method_name, objArrayHandle types, jint which, TRAPS) { | |
1311 if (java_lang_Class::is_primitive(mirror)) return NULL; | |
1312 klassOop klass = java_lang_Class::as_klassOop(mirror); | |
1313 if (Klass::cast(klass)->oop_is_array() && which == MEMBER_DECLARED) return NULL; | |
1314 | |
1315 if (Klass::cast(java_lang_Class::as_klassOop(mirror))->oop_is_array()) { | |
1142 | 1316 klass = SystemDictionary::Object_klass(); |
0 | 1317 } |
1318 instanceKlassHandle h_k(THREAD, klass); | |
1319 | |
1320 // Ensure klass is linked (need not be initialized) | |
1321 h_k->link_class(CHECK_NULL); | |
1322 | |
1323 // For interfaces include static initializers under jdk1.2.x (since classic does that) | |
1324 bool include_clinit = JDK_Version::is_jdk12x_version() && h_k->is_interface(); | |
1325 | |
1326 switch (which) { | |
1327 case MEMBER_PUBLIC: | |
1328 // First the public non-static methods (works if method holder is an interface) | |
1329 // Note that we can ignore checks for overridden methods, since we go up the hierarchy. | |
1330 { | |
1331 for (MethodStream st(h_k, false, false); !st.eos(); st.next()) { | |
1332 methodHandle m(THREAD, st.method()); | |
1333 // For interfaces include static initializers since classic does that! | |
1334 if (method_name() == m->name() && (include_clinit || (m->is_public() && !m->is_static() && !m->is_initializer()))) { | |
1335 symbolHandle signature(THREAD, m->signature()); | |
1336 bool parameter_match = match_parameter_types(m, types, ArgumentCount(signature).size(), CHECK_NULL); | |
1337 if (parameter_match) { | |
1338 return new_method(m, false, false, THREAD); | |
1339 } | |
1340 } | |
1341 } | |
1342 } | |
1343 // Then the public static methods (works if method holder is an interface) | |
1344 { | |
1345 for (MethodStream st(h_k, false, false); !st.eos(); st.next()) { | |
1346 methodHandle m(THREAD, st.method()); | |
1347 if (method_name() == m->name() && m->is_public() && m->is_static() && !m->is_initializer()) { | |
1348 symbolHandle signature(THREAD, m->signature()); | |
1349 bool parameter_match = match_parameter_types(m, types, ArgumentCount(signature).size(), CHECK_NULL); | |
1350 if (parameter_match) { | |
1351 return new_method(m, false, false, THREAD); | |
1352 } | |
1353 } | |
1354 } | |
1355 } | |
1356 break; | |
1357 case MEMBER_DECLARED: | |
1358 // All local methods | |
1359 { | |
1360 for (MethodStream st(h_k, true, true); !st.eos(); st.next()) { | |
1361 methodHandle m(THREAD, st.method()); | |
1362 if (method_name() == m->name() && !m->is_initializer()) { | |
1363 symbolHandle signature(THREAD, m->signature()); | |
1364 bool parameter_match = match_parameter_types(m, types, ArgumentCount(signature).size(), CHECK_NULL); | |
1365 if (parameter_match) { | |
1366 return new_method(m, false, false, THREAD); | |
1367 } | |
1368 } | |
1369 } | |
1370 } | |
1371 break; | |
1372 default: | |
1373 break; | |
1374 } | |
1375 return NULL; | |
1376 } | |
1377 | |
1378 | |
1379 objArrayOop Reflection::reflect_methods(oop mirror, jint which, TRAPS) { | |
1380 // Exclude primitive types | |
1381 if (java_lang_Class::is_primitive(mirror) || | |
1382 (Klass::cast(java_lang_Class::as_klassOop(mirror))->oop_is_array() && (which == MEMBER_DECLARED))) { | |
1142 | 1383 klassOop klass = SystemDictionary::reflect_Method_klass(); |
0 | 1384 return oopFactory::new_objArray(klass, 0, CHECK_NULL); // Return empty array |
1385 } | |
1386 | |
1387 klassOop klass = java_lang_Class::as_klassOop(mirror); | |
1388 if (Klass::cast(java_lang_Class::as_klassOop(mirror))->oop_is_array()) { | |
1142 | 1389 klass = SystemDictionary::Object_klass(); |
0 | 1390 } |
1391 instanceKlassHandle h_k(THREAD, klass); | |
1392 | |
1393 // Ensure klass is linked (need not be initialized) | |
1394 h_k->link_class(CHECK_NULL); | |
1395 | |
1396 // We search the (super)interfaces only if h_k is an interface itself | |
1397 bool is_interface = h_k->is_interface(); | |
1398 | |
1399 // For interfaces include static initializers under jdk1.2.x (since classic does that) | |
1400 bool include_clinit = JDK_Version::is_jdk12x_version() && is_interface; | |
1401 | |
1402 switch (which) { | |
1403 case MEMBER_PUBLIC: | |
1404 { | |
1405 | |
1406 // Count public methods (non-static and static) | |
1407 int count = 0; | |
1408 { | |
1409 for (MethodStream st(h_k, false, false); !st.eos(); st.next()) { | |
1410 methodOop m = st.method(); | |
1411 // For interfaces include static initializers since classic does that! | |
1412 if (include_clinit || (!m->is_initializer() && m->is_public() && !m->is_overridden_in(h_k()))) { | |
1413 count++; | |
1414 } | |
1415 } | |
1416 } | |
1417 | |
1418 // Allocate result | |
1142 | 1419 klassOop klass = SystemDictionary::reflect_Method_klass(); |
0 | 1420 objArrayOop r = oopFactory::new_objArray(klass, count, CHECK_NULL); |
1421 objArrayHandle h_result (THREAD, r); | |
1422 | |
1423 // Fill in results backwards | |
1424 { | |
1425 // First the non-static public methods | |
1426 for (MethodStream st(h_k, false, false); !st.eos(); st.next()) { | |
1427 methodHandle m (THREAD, st.method()); | |
1428 if (!m->is_static() && !m->is_initializer() && m->is_public() && !m->is_overridden_in(h_k())) { | |
1429 oop method = new_method(m, false, false, CHECK_NULL); | |
1430 if (method == NULL) { | |
1431 return NULL; | |
1432 } else { | |
1433 h_result->obj_at_put(--count, method); | |
1434 } | |
1435 } | |
1436 } | |
1437 } | |
1438 { | |
1439 // Then the static public methods | |
1440 for (MethodStream st(h_k, false, !is_interface); !st.eos(); st.next()) { | |
1441 methodHandle m (THREAD, st.method()); | |
1442 if (m->is_static() && (include_clinit || (!m->is_initializer()) && m->is_public() && !m->is_overridden_in(h_k()))) { | |
1443 oop method = new_method(m, false, false, CHECK_NULL); | |
1444 if (method == NULL) { | |
1445 return NULL; | |
1446 } else { | |
1447 h_result->obj_at_put(--count, method); | |
1448 } | |
1449 } | |
1450 } | |
1451 } | |
1452 | |
1453 assert(count == 0, "just checking"); | |
1454 return h_result(); | |
1455 } | |
1456 | |
1457 case MEMBER_DECLARED: | |
1458 { | |
1459 // Count all methods | |
1460 int count = 0; | |
1461 { | |
1462 for (MethodStream st(h_k, true, !is_interface); !st.eos(); st.next()) { | |
1463 methodOop m = st.method(); | |
1464 if (!m->is_initializer()) { | |
1465 count++; | |
1466 } | |
1467 } | |
1468 } | |
1469 // Allocate result | |
1142 | 1470 klassOop klass = SystemDictionary::reflect_Method_klass(); |
0 | 1471 objArrayOop r = oopFactory::new_objArray(klass, count, CHECK_NULL); |
1472 objArrayHandle h_result (THREAD, r); | |
1473 | |
1474 // Fill in results backwards | |
1475 { | |
1476 for (MethodStream st(h_k, true, true); !st.eos(); st.next()) { | |
1477 methodHandle m (THREAD, st.method()); | |
1478 if (!m->is_initializer()) { | |
1479 oop method = new_method(m, false, false, CHECK_NULL); | |
1480 if (method == NULL) { | |
1481 return NULL; | |
1482 } else { | |
1483 h_result->obj_at_put(--count, method); | |
1484 } | |
1485 } | |
1486 } | |
1487 } | |
1488 assert(count == 0, "just checking"); | |
1489 return h_result(); | |
1490 } | |
1491 } | |
1492 ShouldNotReachHere(); | |
1493 return NULL; | |
1494 } | |
1495 | |
1496 | |
1497 oop Reflection::reflect_constructor(oop mirror, objArrayHandle types, jint which, TRAPS) { | |
1498 | |
1499 // Exclude primitive, interface and array types | |
1500 bool prim = java_lang_Class::is_primitive(mirror); | |
1501 Klass* klass = prim ? NULL : Klass::cast(java_lang_Class::as_klassOop(mirror)); | |
1502 if (prim || klass->is_interface() || klass->oop_is_array()) return NULL; | |
1503 | |
1504 // Must be instance klass | |
1505 instanceKlassHandle h_k(THREAD, java_lang_Class::as_klassOop(mirror)); | |
1506 | |
1507 // Ensure klass is linked (need not be initialized) | |
1508 h_k->link_class(CHECK_NULL); | |
1509 | |
1510 bool local_only = (which == MEMBER_DECLARED); | |
1511 for (MethodStream st(h_k, true, true); !st.eos(); st.next()) { | |
1512 methodHandle m(THREAD, st.method()); | |
1513 if (m->name() == vmSymbols::object_initializer_name() && (local_only || m->is_public())) { | |
1514 symbolHandle signature(THREAD, m->signature()); | |
1515 bool parameter_match = match_parameter_types(m, types, ArgumentCount(signature).size(), CHECK_NULL); | |
1516 if (parameter_match) { | |
1517 return new_constructor(m, THREAD); | |
1518 } | |
1519 } | |
1520 } | |
1521 | |
1522 return NULL; | |
1523 } | |
1524 | |
1525 | |
1526 objArrayOop Reflection::reflect_constructors(oop mirror, jint which, TRAPS) { | |
1527 // Exclude primitive, interface and array types | |
1528 bool prim = java_lang_Class::is_primitive(mirror); | |
1529 Klass* k = prim ? NULL : Klass::cast(java_lang_Class::as_klassOop(mirror)); | |
1530 if (prim || k->is_interface() || k->oop_is_array()) { | |
1142 | 1531 return oopFactory::new_objArray(SystemDictionary::reflect_Constructor_klass(), 0, CHECK_NULL); // Return empty array |
0 | 1532 } |
1533 | |
1534 // Must be instanceKlass at this point | |
1535 instanceKlassHandle h_k(THREAD, java_lang_Class::as_klassOop(mirror)); | |
1536 | |
1537 // Ensure klass is linked (need not be initialized) | |
1538 h_k->link_class(CHECK_NULL); | |
1539 | |
1540 bool local_only = (which == MEMBER_DECLARED); | |
1541 int count = 0; | |
1542 { | |
1543 for (MethodStream st(h_k, true, true); !st.eos(); st.next()) { | |
1544 methodOop m = st.method(); | |
1545 if (m->name() == vmSymbols::object_initializer_name() && (local_only || m->is_public())) { | |
1546 count++; | |
1547 } | |
1548 } | |
1549 } | |
1550 | |
1551 // Allocate result | |
1552 symbolHandle name = vmSymbolHandles::java_lang_reflect_Constructor(); | |
1553 klassOop klass = SystemDictionary::resolve_or_fail(name, true, CHECK_NULL); | |
1554 objArrayOop r = oopFactory::new_objArray(klass, count, CHECK_NULL); | |
1555 objArrayHandle h_result (THREAD, r); | |
1556 | |
1557 // Fill in results backwards | |
1558 { | |
1559 for (MethodStream st(h_k, true, true); !st.eos(); st.next()) { | |
1560 methodHandle m (THREAD, st.method()); | |
1561 if (m->name() == vmSymbols::object_initializer_name() && (local_only || m->is_public())) { | |
1562 oop constr = new_constructor(m, CHECK_NULL); | |
1563 if (constr == NULL) { | |
1564 return NULL; | |
1565 } else { | |
1566 h_result->obj_at_put(--count, constr); | |
1567 } | |
1568 } | |
1569 } | |
1570 assert(count == 0, "just checking"); | |
1571 } | |
1572 return h_result(); | |
1573 } | |
1574 | |
1575 | |
1576 // This would be nicer if, say, java.lang.reflect.Method was a subclass | |
1577 // of java.lang.reflect.Constructor | |
1578 | |
1579 oop Reflection::invoke_method(oop method_mirror, Handle receiver, objArrayHandle args, TRAPS) { | |
1580 oop mirror = java_lang_reflect_Method::clazz(method_mirror); | |
1581 int slot = java_lang_reflect_Method::slot(method_mirror); | |
1582 bool override = java_lang_reflect_Method::override(method_mirror) != 0; | |
1583 objArrayHandle ptypes(THREAD, objArrayOop(java_lang_reflect_Method::parameter_types(method_mirror))); | |
1584 | |
1585 oop return_type_mirror = java_lang_reflect_Method::return_type(method_mirror); | |
1586 BasicType rtype; | |
1587 if (java_lang_Class::is_primitive(return_type_mirror)) { | |
1588 rtype = basic_type_mirror_to_basic_type(return_type_mirror, CHECK_NULL); | |
1589 } else { | |
1590 rtype = T_OBJECT; | |
1591 } | |
1592 | |
1593 instanceKlassHandle klass(THREAD, java_lang_Class::as_klassOop(mirror)); | |
51
1ffa5cdd0b7e
6667089: 3/3 multiple redefinitions of a class break reflection
dcubed
parents:
0
diff
changeset
|
1594 methodOop m = klass->method_with_idnum(slot); |
1ffa5cdd0b7e
6667089: 3/3 multiple redefinitions of a class break reflection
dcubed
parents:
0
diff
changeset
|
1595 if (m == NULL) { |
0 | 1596 THROW_MSG_0(vmSymbols::java_lang_InternalError(), "invoke"); |
1597 } | |
51
1ffa5cdd0b7e
6667089: 3/3 multiple redefinitions of a class break reflection
dcubed
parents:
0
diff
changeset
|
1598 methodHandle method(THREAD, m); |
0 | 1599 |
1600 return invoke(klass, method, receiver, override, ptypes, rtype, args, true, THREAD); | |
1601 } | |
1602 | |
1603 | |
1604 oop Reflection::invoke_constructor(oop constructor_mirror, objArrayHandle args, TRAPS) { | |
1605 oop mirror = java_lang_reflect_Constructor::clazz(constructor_mirror); | |
1606 int slot = java_lang_reflect_Constructor::slot(constructor_mirror); | |
1607 bool override = java_lang_reflect_Constructor::override(constructor_mirror) != 0; | |
1608 objArrayHandle ptypes(THREAD, objArrayOop(java_lang_reflect_Constructor::parameter_types(constructor_mirror))); | |
1609 | |
1610 instanceKlassHandle klass(THREAD, java_lang_Class::as_klassOop(mirror)); | |
51
1ffa5cdd0b7e
6667089: 3/3 multiple redefinitions of a class break reflection
dcubed
parents:
0
diff
changeset
|
1611 methodOop m = klass->method_with_idnum(slot); |
1ffa5cdd0b7e
6667089: 3/3 multiple redefinitions of a class break reflection
dcubed
parents:
0
diff
changeset
|
1612 if (m == NULL) { |
0 | 1613 THROW_MSG_0(vmSymbols::java_lang_InternalError(), "invoke"); |
1614 } | |
51
1ffa5cdd0b7e
6667089: 3/3 multiple redefinitions of a class break reflection
dcubed
parents:
0
diff
changeset
|
1615 methodHandle method(THREAD, m); |
0 | 1616 assert(method->name() == vmSymbols::object_initializer_name(), "invalid constructor"); |
1617 | |
1618 // Make sure klass gets initialize | |
1619 klass->initialize(CHECK_NULL); | |
1620 | |
1621 // Create new instance (the receiver) | |
1622 klass->check_valid_for_instantiation(false, CHECK_NULL); | |
1623 Handle receiver = klass->allocate_instance_handle(CHECK_NULL); | |
1624 | |
1625 // Ignore result from call and return receiver | |
1626 invoke(klass, method, receiver, override, ptypes, T_VOID, args, false, CHECK_NULL); | |
1627 return receiver(); | |
1628 } | |
1629 | |
1630 | |
1631 #endif /* SUPPORT_OLD_REFLECTION */ |