1 | /* |
2 | * Copyright (c) 1997, 2019, Oracle and/or its affiliates. All rights reserved. |
3 | * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. |
4 | * |
5 | * This code is free software; you can redistribute it and/or modify it |
6 | * under the terms of the GNU General Public License version 2 only, as |
7 | * published by the Free Software Foundation. |
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 | * |
19 | * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA |
20 | * or visit www.oracle.com if you need additional information or have any |
21 | * questions. |
22 | * |
23 | */ |
24 | |
25 | #include "precompiled.hpp" |
26 | #include "jvm.h" |
27 | #include "classfile/classFileStream.hpp" |
28 | #include "classfile/classLoader.hpp" |
29 | #include "classfile/classLoaderData.inline.hpp" |
30 | #include "classfile/javaAssertions.hpp" |
31 | #include "classfile/javaClasses.inline.hpp" |
32 | #include "classfile/moduleEntry.hpp" |
33 | #include "classfile/modules.hpp" |
34 | #include "classfile/packageEntry.hpp" |
35 | #include "classfile/stringTable.hpp" |
36 | #include "classfile/symbolTable.hpp" |
37 | #include "classfile/systemDictionary.hpp" |
38 | #include "classfile/vmSymbols.hpp" |
39 | #include "gc/shared/collectedHeap.inline.hpp" |
40 | #include "interpreter/bytecode.hpp" |
41 | #include "jfr/jfrEvents.hpp" |
42 | #include "logging/log.hpp" |
43 | #include "memory/heapShared.hpp" |
44 | #include "memory/oopFactory.hpp" |
45 | #include "memory/referenceType.hpp" |
46 | #include "memory/resourceArea.hpp" |
47 | #include "memory/universe.hpp" |
48 | #include "oops/access.inline.hpp" |
49 | #include "oops/constantPool.hpp" |
50 | #include "oops/fieldStreams.hpp" |
51 | #include "oops/instanceKlass.hpp" |
52 | #include "oops/method.hpp" |
53 | #include "oops/objArrayKlass.hpp" |
54 | #include "oops/objArrayOop.inline.hpp" |
55 | #include "oops/oop.inline.hpp" |
56 | #include "prims/jvm_misc.hpp" |
57 | #include "prims/jvmtiExport.hpp" |
58 | #include "prims/jvmtiThreadState.hpp" |
59 | #include "prims/nativeLookup.hpp" |
60 | #include "prims/stackwalk.hpp" |
61 | #include "runtime/arguments.hpp" |
62 | #include "runtime/atomic.hpp" |
63 | #include "runtime/handles.inline.hpp" |
64 | #include "runtime/init.hpp" |
65 | #include "runtime/interfaceSupport.inline.hpp" |
66 | #include "runtime/deoptimization.hpp" |
67 | #include "runtime/handshake.hpp" |
68 | #include "runtime/java.hpp" |
69 | #include "runtime/javaCalls.hpp" |
70 | #include "runtime/jfieldIDWorkaround.hpp" |
71 | #include "runtime/jniHandles.inline.hpp" |
72 | #include "runtime/orderAccess.hpp" |
73 | #include "runtime/os.inline.hpp" |
74 | #include "runtime/perfData.hpp" |
75 | #include "runtime/reflection.hpp" |
76 | #include "runtime/thread.inline.hpp" |
77 | #include "runtime/threadSMR.hpp" |
78 | #include "runtime/vframe.inline.hpp" |
79 | #include "runtime/vmOperations.hpp" |
80 | #include "runtime/vm_version.hpp" |
81 | #include "services/attachListener.hpp" |
82 | #include "services/management.hpp" |
83 | #include "services/threadService.hpp" |
84 | #include "utilities/copy.hpp" |
85 | #include "utilities/defaultStream.hpp" |
86 | #include "utilities/dtrace.hpp" |
87 | #include "utilities/events.hpp" |
88 | #include "utilities/histogram.hpp" |
89 | #include "utilities/macros.hpp" |
90 | #include "utilities/utf8.hpp" |
91 | #if INCLUDE_CDS |
92 | #include "classfile/systemDictionaryShared.hpp" |
93 | #endif |
94 | |
95 | #include <errno.h> |
96 | |
97 | /* |
98 | NOTE about use of any ctor or function call that can trigger a safepoint/GC: |
99 | such ctors and calls MUST NOT come between an oop declaration/init and its |
100 | usage because if objects are move this may cause various memory stomps, bus |
101 | errors and segfaults. Here is a cookbook for causing so called "naked oop |
102 | failures": |
103 | |
104 | JVM_ENTRY(jobjectArray, JVM_GetClassDeclaredFields<etc> { |
105 | JVMWrapper("JVM_GetClassDeclaredFields"); |
106 | |
107 | // Object address to be held directly in mirror & not visible to GC |
108 | oop mirror = JNIHandles::resolve_non_null(ofClass); |
109 | |
110 | // If this ctor can hit a safepoint, moving objects around, then |
111 | ComplexConstructor foo; |
112 | |
113 | // Boom! mirror may point to JUNK instead of the intended object |
114 | (some dereference of mirror) |
115 | |
116 | // Here's another call that may block for GC, making mirror stale |
117 | MutexLocker ml(some_lock); |
118 | |
119 | // And here's an initializer that can result in a stale oop |
120 | // all in one step. |
121 | oop o = call_that_can_throw_exception(TRAPS); |
122 | |
123 | |
124 | The solution is to keep the oop declaration BELOW the ctor or function |
125 | call that might cause a GC, do another resolve to reassign the oop, or |
126 | consider use of a Handle instead of an oop so there is immunity from object |
127 | motion. But note that the "QUICK" entries below do not have a handlemark |
128 | and thus can only support use of handles passed in. |
129 | */ |
130 | |
131 | static void trace_class_resolution_impl(Klass* to_class, TRAPS) { |
132 | ResourceMark rm; |
133 | int line_number = -1; |
134 | const char * source_file = NULL; |
135 | const char * trace = "explicit" ; |
136 | InstanceKlass* caller = NULL; |
137 | JavaThread* jthread = JavaThread::current(); |
138 | if (jthread->has_last_Java_frame()) { |
139 | vframeStream vfst(jthread); |
140 | |
141 | // scan up the stack skipping ClassLoader, AccessController and PrivilegedAction frames |
142 | TempNewSymbol access_controller = SymbolTable::new_symbol("java/security/AccessController" ); |
143 | Klass* access_controller_klass = SystemDictionary::resolve_or_fail(access_controller, false, CHECK); |
144 | TempNewSymbol privileged_action = SymbolTable::new_symbol("java/security/PrivilegedAction" ); |
145 | Klass* privileged_action_klass = SystemDictionary::resolve_or_fail(privileged_action, false, CHECK); |
146 | |
147 | Method* last_caller = NULL; |
148 | |
149 | while (!vfst.at_end()) { |
150 | Method* m = vfst.method(); |
151 | if (!vfst.method()->method_holder()->is_subclass_of(SystemDictionary::ClassLoader_klass())&& |
152 | !vfst.method()->method_holder()->is_subclass_of(access_controller_klass) && |
153 | !vfst.method()->method_holder()->is_subclass_of(privileged_action_klass)) { |
154 | break; |
155 | } |
156 | last_caller = m; |
157 | vfst.next(); |
158 | } |
159 | // if this is called from Class.forName0 and that is called from Class.forName, |
160 | // then print the caller of Class.forName. If this is Class.loadClass, then print |
161 | // that caller, otherwise keep quiet since this should be picked up elsewhere. |
162 | bool found_it = false; |
163 | if (!vfst.at_end() && |
164 | vfst.method()->method_holder()->name() == vmSymbols::java_lang_Class() && |
165 | vfst.method()->name() == vmSymbols::forName0_name()) { |
166 | vfst.next(); |
167 | if (!vfst.at_end() && |
168 | vfst.method()->method_holder()->name() == vmSymbols::java_lang_Class() && |
169 | vfst.method()->name() == vmSymbols::forName_name()) { |
170 | vfst.next(); |
171 | found_it = true; |
172 | } |
173 | } else if (last_caller != NULL && |
174 | last_caller->method_holder()->name() == |
175 | vmSymbols::java_lang_ClassLoader() && |
176 | last_caller->name() == vmSymbols::loadClass_name()) { |
177 | found_it = true; |
178 | } else if (!vfst.at_end()) { |
179 | if (vfst.method()->is_native()) { |
180 | // JNI call |
181 | found_it = true; |
182 | } |
183 | } |
184 | if (found_it && !vfst.at_end()) { |
185 | // found the caller |
186 | caller = vfst.method()->method_holder(); |
187 | line_number = vfst.method()->line_number_from_bci(vfst.bci()); |
188 | if (line_number == -1) { |
189 | // show method name if it's a native method |
190 | trace = vfst.method()->name_and_sig_as_C_string(); |
191 | } |
192 | Symbol* s = caller->source_file_name(); |
193 | if (s != NULL) { |
194 | source_file = s->as_C_string(); |
195 | } |
196 | } |
197 | } |
198 | if (caller != NULL) { |
199 | if (to_class != caller) { |
200 | const char * from = caller->external_name(); |
201 | const char * to = to_class->external_name(); |
202 | // print in a single call to reduce interleaving between threads |
203 | if (source_file != NULL) { |
204 | log_debug(class, resolve)("%s %s %s:%d (%s)" , from, to, source_file, line_number, trace); |
205 | } else { |
206 | log_debug(class, resolve)("%s %s (%s)" , from, to, trace); |
207 | } |
208 | } |
209 | } |
210 | } |
211 | |
212 | void trace_class_resolution(Klass* to_class) { |
213 | EXCEPTION_MARK; |
214 | trace_class_resolution_impl(to_class, THREAD); |
215 | if (HAS_PENDING_EXCEPTION) { |
216 | CLEAR_PENDING_EXCEPTION; |
217 | } |
218 | } |
219 | |
220 | // Wrapper to trace JVM functions |
221 | |
222 | #ifdef ASSERT |
223 | Histogram* JVMHistogram; |
224 | volatile int JVMHistogram_lock = 0; |
225 | |
226 | class JVMHistogramElement : public HistogramElement { |
227 | public: |
228 | JVMHistogramElement(const char* name); |
229 | }; |
230 | |
231 | JVMHistogramElement::JVMHistogramElement(const char* elementName) { |
232 | _name = elementName; |
233 | uintx count = 0; |
234 | |
235 | while (Atomic::cmpxchg(1, &JVMHistogram_lock, 0) != 0) { |
236 | while (OrderAccess::load_acquire(&JVMHistogram_lock) != 0) { |
237 | count +=1; |
238 | if ( (WarnOnStalledSpinLock > 0) |
239 | && (count % WarnOnStalledSpinLock == 0)) { |
240 | warning("JVMHistogram_lock seems to be stalled" ); |
241 | } |
242 | } |
243 | } |
244 | |
245 | if(JVMHistogram == NULL) |
246 | JVMHistogram = new Histogram("JVM Call Counts" ,100); |
247 | |
248 | JVMHistogram->add_element(this); |
249 | Atomic::dec(&JVMHistogram_lock); |
250 | } |
251 | |
252 | #define JVMCountWrapper(arg) \ |
253 | static JVMHistogramElement* e = new JVMHistogramElement(arg); \ |
254 | if (e != NULL) e->increment_count(); // Due to bug in VC++, we need a NULL check here eventhough it should never happen! |
255 | |
256 | #define JVMWrapper(arg) JVMCountWrapper(arg); |
257 | #else |
258 | #define JVMWrapper(arg) |
259 | #endif |
260 | |
261 | |
262 | // Interface version ///////////////////////////////////////////////////////////////////// |
263 | |
264 | |
265 | JVM_LEAF(jint, JVM_GetInterfaceVersion()) |
266 | return JVM_INTERFACE_VERSION; |
267 | JVM_END |
268 | |
269 | |
270 | // java.lang.System ////////////////////////////////////////////////////////////////////// |
271 | |
272 | |
273 | JVM_LEAF(jlong, JVM_CurrentTimeMillis(JNIEnv *env, jclass ignored)) |
274 | JVMWrapper("JVM_CurrentTimeMillis" ); |
275 | return os::javaTimeMillis(); |
276 | JVM_END |
277 | |
278 | JVM_LEAF(jlong, JVM_NanoTime(JNIEnv *env, jclass ignored)) |
279 | JVMWrapper("JVM_NanoTime" ); |
280 | return os::javaTimeNanos(); |
281 | JVM_END |
282 | |
283 | // The function below is actually exposed by jdk.internal.misc.VM and not |
284 | // java.lang.System, but we choose to keep it here so that it stays next |
285 | // to JVM_CurrentTimeMillis and JVM_NanoTime |
286 | |
287 | const jlong MAX_DIFF_SECS = CONST64(0x0100000000); // 2^32 |
288 | const jlong MIN_DIFF_SECS = -MAX_DIFF_SECS; // -2^32 |
289 | |
290 | JVM_LEAF(jlong, JVM_GetNanoTimeAdjustment(JNIEnv *env, jclass ignored, jlong offset_secs)) |
291 | JVMWrapper("JVM_GetNanoTimeAdjustment" ); |
292 | jlong seconds; |
293 | jlong nanos; |
294 | |
295 | os::javaTimeSystemUTC(seconds, nanos); |
296 | |
297 | // We're going to verify that the result can fit in a long. |
298 | // For that we need the difference in seconds between 'seconds' |
299 | // and 'offset_secs' to be such that: |
300 | // |seconds - offset_secs| < (2^63/10^9) |
301 | // We're going to approximate 10^9 ~< 2^30 (1000^3 ~< 1024^3) |
302 | // which makes |seconds - offset_secs| < 2^33 |
303 | // and we will prefer +/- 2^32 as the maximum acceptable diff |
304 | // as 2^32 has a more natural feel than 2^33... |
305 | // |
306 | // So if |seconds - offset_secs| >= 2^32 - we return a special |
307 | // sentinel value (-1) which the caller should take as an |
308 | // exception value indicating that the offset given to us is |
309 | // too far from range of the current time - leading to too big |
310 | // a nano adjustment. The caller is expected to recover by |
311 | // computing a more accurate offset and calling this method |
312 | // again. (For the record 2^32 secs is ~136 years, so that |
313 | // should rarely happen) |
314 | // |
315 | jlong diff = seconds - offset_secs; |
316 | if (diff >= MAX_DIFF_SECS || diff <= MIN_DIFF_SECS) { |
317 | return -1; // sentinel value: the offset is too far off the target |
318 | } |
319 | |
320 | // return the adjustment. If you compute a time by adding |
321 | // this number of nanoseconds along with the number of seconds |
322 | // in the offset you should get the current UTC time. |
323 | return (diff * (jlong)1000000000) + nanos; |
324 | JVM_END |
325 | |
326 | JVM_ENTRY(void, JVM_ArrayCopy(JNIEnv *env, jclass ignored, jobject src, jint src_pos, |
327 | jobject dst, jint dst_pos, jint length)) |
328 | JVMWrapper("JVM_ArrayCopy" ); |
329 | // Check if we have null pointers |
330 | if (src == NULL || dst == NULL) { |
331 | THROW(vmSymbols::java_lang_NullPointerException()); |
332 | } |
333 | arrayOop s = arrayOop(JNIHandles::resolve_non_null(src)); |
334 | arrayOop d = arrayOop(JNIHandles::resolve_non_null(dst)); |
335 | assert(oopDesc::is_oop(s), "JVM_ArrayCopy: src not an oop" ); |
336 | assert(oopDesc::is_oop(d), "JVM_ArrayCopy: dst not an oop" ); |
337 | // Do copy |
338 | s->klass()->copy_array(s, src_pos, d, dst_pos, length, thread); |
339 | JVM_END |
340 | |
341 | |
342 | static void set_property(Handle props, const char* key, const char* value, TRAPS) { |
343 | JavaValue r(T_OBJECT); |
344 | // public synchronized Object put(Object key, Object value); |
345 | HandleMark hm(THREAD); |
346 | Handle key_str = java_lang_String::create_from_platform_dependent_str(key, CHECK); |
347 | Handle value_str = java_lang_String::create_from_platform_dependent_str((value != NULL ? value : "" ), CHECK); |
348 | JavaCalls::call_virtual(&r, |
349 | props, |
350 | SystemDictionary::Properties_klass(), |
351 | vmSymbols::put_name(), |
352 | vmSymbols::object_object_object_signature(), |
353 | key_str, |
354 | value_str, |
355 | THREAD); |
356 | } |
357 | |
358 | |
359 | #define PUTPROP(props, name, value) set_property((props), (name), (value), CHECK_(properties)); |
360 | |
361 | /* |
362 | * Return all of the system properties in a Java String array with alternating |
363 | * names and values from the jvm SystemProperty. |
364 | * Which includes some internal and all commandline -D defined properties. |
365 | */ |
366 | JVM_ENTRY(jobjectArray, JVM_GetProperties(JNIEnv *env)) |
367 | JVMWrapper("JVM_GetProperties" ); |
368 | ResourceMark rm(THREAD); |
369 | HandleMark hm(THREAD); |
370 | int ndx = 0; |
371 | int fixedCount = 2; |
372 | |
373 | SystemProperty* p = Arguments::system_properties(); |
374 | int count = Arguments::PropertyList_count(p); |
375 | |
376 | // Allocate result String array |
377 | InstanceKlass* ik = SystemDictionary::String_klass(); |
378 | objArrayOop r = oopFactory::new_objArray(ik, (count + fixedCount) * 2, CHECK_NULL); |
379 | objArrayHandle result_h(THREAD, r); |
380 | |
381 | while (p != NULL) { |
382 | const char * key = p->key(); |
383 | if (strcmp(key, "sun.nio.MaxDirectMemorySize" ) != 0) { |
384 | const char * value = p->value(); |
385 | Handle key_str = java_lang_String::create_from_platform_dependent_str(key, CHECK_NULL); |
386 | Handle value_str = java_lang_String::create_from_platform_dependent_str((value != NULL ? value : "" ), CHECK_NULL); |
387 | result_h->obj_at_put(ndx * 2, key_str()); |
388 | result_h->obj_at_put(ndx * 2 + 1, value_str()); |
389 | ndx++; |
390 | } |
391 | p = p->next(); |
392 | } |
393 | |
394 | // Convert the -XX:MaxDirectMemorySize= command line flag |
395 | // to the sun.nio.MaxDirectMemorySize property. |
396 | // Do this after setting user properties to prevent people |
397 | // from setting the value with a -D option, as requested. |
398 | // Leave empty if not supplied |
399 | if (!FLAG_IS_DEFAULT(MaxDirectMemorySize)) { |
400 | char as_chars[256]; |
401 | jio_snprintf(as_chars, sizeof(as_chars), JULONG_FORMAT, MaxDirectMemorySize); |
402 | Handle key_str = java_lang_String::create_from_platform_dependent_str("sun.nio.MaxDirectMemorySize" , CHECK_NULL); |
403 | Handle value_str = java_lang_String::create_from_platform_dependent_str(as_chars, CHECK_NULL); |
404 | result_h->obj_at_put(ndx * 2, key_str()); |
405 | result_h->obj_at_put(ndx * 2 + 1, value_str()); |
406 | ndx++; |
407 | } |
408 | |
409 | // JVM monitoring and management support |
410 | // Add the sun.management.compiler property for the compiler's name |
411 | { |
412 | #undef CSIZE |
413 | #if defined(_LP64) || defined(_WIN64) |
414 | #define CSIZE "64-Bit " |
415 | #else |
416 | #define CSIZE |
417 | #endif // 64bit |
418 | |
419 | #ifdef TIERED |
420 | const char* compiler_name = "HotSpot " CSIZE "Tiered Compilers" ; |
421 | #else |
422 | #if defined(COMPILER1) |
423 | const char* compiler_name = "HotSpot " CSIZE "Client Compiler" ; |
424 | #elif defined(COMPILER2) |
425 | const char* compiler_name = "HotSpot " CSIZE "Server Compiler" ; |
426 | #elif INCLUDE_JVMCI |
427 | #error "INCLUDE_JVMCI should imply TIERED" |
428 | #else |
429 | const char* compiler_name = "" ; |
430 | #endif // compilers |
431 | #endif // TIERED |
432 | |
433 | if (*compiler_name != '\0' && |
434 | (Arguments::mode() != Arguments::_int)) { |
435 | Handle key_str = java_lang_String::create_from_platform_dependent_str("sun.management.compiler" , CHECK_NULL); |
436 | Handle value_str = java_lang_String::create_from_platform_dependent_str(compiler_name, CHECK_NULL); |
437 | result_h->obj_at_put(ndx * 2, key_str()); |
438 | result_h->obj_at_put(ndx * 2 + 1, value_str()); |
439 | ndx++; |
440 | } |
441 | } |
442 | |
443 | return (jobjectArray) JNIHandles::make_local(env, result_h()); |
444 | JVM_END |
445 | |
446 | |
447 | /* |
448 | * Return the temporary directory that the VM uses for the attach |
449 | * and perf data files. |
450 | * |
451 | * It is important that this directory is well-known and the |
452 | * same for all VM instances. It cannot be affected by configuration |
453 | * variables such as java.io.tmpdir. |
454 | */ |
455 | JVM_ENTRY(jstring, JVM_GetTemporaryDirectory(JNIEnv *env)) |
456 | JVMWrapper("JVM_GetTemporaryDirectory" ); |
457 | HandleMark hm(THREAD); |
458 | const char* temp_dir = os::get_temp_directory(); |
459 | Handle h = java_lang_String::create_from_platform_dependent_str(temp_dir, CHECK_NULL); |
460 | return (jstring) JNIHandles::make_local(env, h()); |
461 | JVM_END |
462 | |
463 | |
464 | // java.lang.Runtime ///////////////////////////////////////////////////////////////////////// |
465 | |
466 | extern volatile jint vm_created; |
467 | |
468 | JVM_ENTRY_NO_ENV(void, JVM_BeforeHalt()) |
469 | JVMWrapper("JVM_BeforeHalt" ); |
470 | EventShutdown event; |
471 | if (event.should_commit()) { |
472 | event.set_reason("Shutdown requested from Java" ); |
473 | event.commit(); |
474 | } |
475 | JVM_END |
476 | |
477 | |
478 | JVM_ENTRY_NO_ENV(void, JVM_Halt(jint code)) |
479 | before_exit(thread); |
480 | vm_exit(code); |
481 | JVM_END |
482 | |
483 | |
484 | JVM_ENTRY_NO_ENV(void, JVM_GC(void)) |
485 | JVMWrapper("JVM_GC" ); |
486 | if (!DisableExplicitGC) { |
487 | Universe::heap()->collect(GCCause::_java_lang_system_gc); |
488 | } |
489 | JVM_END |
490 | |
491 | |
492 | JVM_LEAF(jlong, JVM_MaxObjectInspectionAge(void)) |
493 | JVMWrapper("JVM_MaxObjectInspectionAge" ); |
494 | return Universe::heap()->millis_since_last_gc(); |
495 | JVM_END |
496 | |
497 | |
498 | static inline jlong convert_size_t_to_jlong(size_t val) { |
499 | // In the 64-bit vm, a size_t can overflow a jlong (which is signed). |
500 | NOT_LP64 (return (jlong)val;) |
501 | LP64_ONLY(return (jlong)MIN2(val, (size_t)max_jlong);) |
502 | } |
503 | |
504 | JVM_ENTRY_NO_ENV(jlong, JVM_TotalMemory(void)) |
505 | JVMWrapper("JVM_TotalMemory" ); |
506 | size_t n = Universe::heap()->capacity(); |
507 | return convert_size_t_to_jlong(n); |
508 | JVM_END |
509 | |
510 | |
511 | JVM_ENTRY_NO_ENV(jlong, JVM_FreeMemory(void)) |
512 | JVMWrapper("JVM_FreeMemory" ); |
513 | size_t n = Universe::heap()->unused(); |
514 | return convert_size_t_to_jlong(n); |
515 | JVM_END |
516 | |
517 | |
518 | JVM_ENTRY_NO_ENV(jlong, JVM_MaxMemory(void)) |
519 | JVMWrapper("JVM_MaxMemory" ); |
520 | size_t n = Universe::heap()->max_capacity(); |
521 | return convert_size_t_to_jlong(n); |
522 | JVM_END |
523 | |
524 | |
525 | JVM_ENTRY_NO_ENV(jint, JVM_ActiveProcessorCount(void)) |
526 | JVMWrapper("JVM_ActiveProcessorCount" ); |
527 | return os::active_processor_count(); |
528 | JVM_END |
529 | |
530 | |
531 | |
532 | // java.lang.Throwable ////////////////////////////////////////////////////// |
533 | |
534 | |
535 | JVM_ENTRY(void, JVM_FillInStackTrace(JNIEnv *env, jobject receiver)) |
536 | JVMWrapper("JVM_FillInStackTrace" ); |
537 | Handle exception(thread, JNIHandles::resolve_non_null(receiver)); |
538 | java_lang_Throwable::fill_in_stack_trace(exception); |
539 | JVM_END |
540 | |
541 | |
542 | // java.lang.StackTraceElement ////////////////////////////////////////////// |
543 | |
544 | |
545 | JVM_ENTRY(void, JVM_InitStackTraceElementArray(JNIEnv *env, jobjectArray elements, jobject throwable)) |
546 | JVMWrapper("JVM_InitStackTraceElementArray" ); |
547 | Handle exception(THREAD, JNIHandles::resolve(throwable)); |
548 | objArrayOop st = objArrayOop(JNIHandles::resolve(elements)); |
549 | objArrayHandle stack_trace(THREAD, st); |
550 | // Fill in the allocated stack trace |
551 | java_lang_Throwable::get_stack_trace_elements(exception, stack_trace, CHECK); |
552 | JVM_END |
553 | |
554 | |
555 | JVM_ENTRY(void, JVM_InitStackTraceElement(JNIEnv* env, jobject element, jobject stackFrameInfo)) |
556 | JVMWrapper("JVM_InitStackTraceElement" ); |
557 | Handle stack_frame_info(THREAD, JNIHandles::resolve_non_null(stackFrameInfo)); |
558 | Handle stack_trace_element(THREAD, JNIHandles::resolve_non_null(element)); |
559 | java_lang_StackFrameInfo::to_stack_trace_element(stack_frame_info, stack_trace_element, THREAD); |
560 | JVM_END |
561 | |
562 | |
563 | // java.lang.StackWalker ////////////////////////////////////////////////////// |
564 | |
565 | |
566 | JVM_ENTRY(jobject, JVM_CallStackWalk(JNIEnv *env, jobject stackStream, jlong mode, |
567 | jint skip_frames, jint frame_count, jint start_index, |
568 | jobjectArray frames)) |
569 | JVMWrapper("JVM_CallStackWalk" ); |
570 | JavaThread* jt = (JavaThread*) THREAD; |
571 | if (!jt->is_Java_thread() || !jt->has_last_Java_frame()) { |
572 | THROW_MSG_(vmSymbols::java_lang_InternalError(), "doStackWalk: no stack trace" , NULL); |
573 | } |
574 | |
575 | Handle stackStream_h(THREAD, JNIHandles::resolve_non_null(stackStream)); |
576 | |
577 | // frames array is a Class<?>[] array when only getting caller reference, |
578 | // and a StackFrameInfo[] array (or derivative) otherwise. It should never |
579 | // be null. |
580 | objArrayOop fa = objArrayOop(JNIHandles::resolve_non_null(frames)); |
581 | objArrayHandle frames_array_h(THREAD, fa); |
582 | |
583 | int limit = start_index + frame_count; |
584 | if (frames_array_h->length() < limit) { |
585 | THROW_MSG_(vmSymbols::java_lang_IllegalArgumentException(), "not enough space in buffers" , NULL); |
586 | } |
587 | |
588 | oop result = StackWalk::walk(stackStream_h, mode, skip_frames, frame_count, |
589 | start_index, frames_array_h, CHECK_NULL); |
590 | return JNIHandles::make_local(env, result); |
591 | JVM_END |
592 | |
593 | |
594 | JVM_ENTRY(jint, JVM_MoreStackWalk(JNIEnv *env, jobject stackStream, jlong mode, jlong anchor, |
595 | jint frame_count, jint start_index, |
596 | jobjectArray frames)) |
597 | JVMWrapper("JVM_MoreStackWalk" ); |
598 | JavaThread* jt = (JavaThread*) THREAD; |
599 | |
600 | // frames array is a Class<?>[] array when only getting caller reference, |
601 | // and a StackFrameInfo[] array (or derivative) otherwise. It should never |
602 | // be null. |
603 | objArrayOop fa = objArrayOop(JNIHandles::resolve_non_null(frames)); |
604 | objArrayHandle frames_array_h(THREAD, fa); |
605 | |
606 | int limit = start_index+frame_count; |
607 | if (frames_array_h->length() < limit) { |
608 | THROW_MSG_0(vmSymbols::java_lang_IllegalArgumentException(), "not enough space in buffers" ); |
609 | } |
610 | |
611 | Handle stackStream_h(THREAD, JNIHandles::resolve_non_null(stackStream)); |
612 | return StackWalk::fetchNextBatch(stackStream_h, mode, anchor, frame_count, |
613 | start_index, frames_array_h, THREAD); |
614 | JVM_END |
615 | |
616 | // java.lang.Object /////////////////////////////////////////////// |
617 | |
618 | |
619 | JVM_ENTRY(jint, JVM_IHashCode(JNIEnv* env, jobject handle)) |
620 | JVMWrapper("JVM_IHashCode" ); |
621 | // as implemented in the classic virtual machine; return 0 if object is NULL |
622 | return handle == NULL ? 0 : ObjectSynchronizer::FastHashCode (THREAD, JNIHandles::resolve_non_null(handle)) ; |
623 | JVM_END |
624 | |
625 | |
626 | JVM_ENTRY(void, JVM_MonitorWait(JNIEnv* env, jobject handle, jlong ms)) |
627 | JVMWrapper("JVM_MonitorWait" ); |
628 | Handle obj(THREAD, JNIHandles::resolve_non_null(handle)); |
629 | JavaThreadInObjectWaitState jtiows(thread, ms != 0); |
630 | if (JvmtiExport::should_post_monitor_wait()) { |
631 | JvmtiExport::post_monitor_wait((JavaThread *)THREAD, (oop)obj(), ms); |
632 | |
633 | // The current thread already owns the monitor and it has not yet |
634 | // been added to the wait queue so the current thread cannot be |
635 | // made the successor. This means that the JVMTI_EVENT_MONITOR_WAIT |
636 | // event handler cannot accidentally consume an unpark() meant for |
637 | // the ParkEvent associated with this ObjectMonitor. |
638 | } |
639 | ObjectSynchronizer::wait(obj, ms, CHECK); |
640 | JVM_END |
641 | |
642 | |
643 | JVM_ENTRY(void, JVM_MonitorNotify(JNIEnv* env, jobject handle)) |
644 | JVMWrapper("JVM_MonitorNotify" ); |
645 | Handle obj(THREAD, JNIHandles::resolve_non_null(handle)); |
646 | ObjectSynchronizer::notify(obj, CHECK); |
647 | JVM_END |
648 | |
649 | |
650 | JVM_ENTRY(void, JVM_MonitorNotifyAll(JNIEnv* env, jobject handle)) |
651 | JVMWrapper("JVM_MonitorNotifyAll" ); |
652 | Handle obj(THREAD, JNIHandles::resolve_non_null(handle)); |
653 | ObjectSynchronizer::notifyall(obj, CHECK); |
654 | JVM_END |
655 | |
656 | |
657 | JVM_ENTRY(jobject, JVM_Clone(JNIEnv* env, jobject handle)) |
658 | JVMWrapper("JVM_Clone" ); |
659 | Handle obj(THREAD, JNIHandles::resolve_non_null(handle)); |
660 | Klass* klass = obj->klass(); |
661 | JvmtiVMObjectAllocEventCollector oam; |
662 | |
663 | #ifdef ASSERT |
664 | // Just checking that the cloneable flag is set correct |
665 | if (obj->is_array()) { |
666 | guarantee(klass->is_cloneable(), "all arrays are cloneable" ); |
667 | } else { |
668 | guarantee(obj->is_instance(), "should be instanceOop" ); |
669 | bool cloneable = klass->is_subtype_of(SystemDictionary::Cloneable_klass()); |
670 | guarantee(cloneable == klass->is_cloneable(), "incorrect cloneable flag" ); |
671 | } |
672 | #endif |
673 | |
674 | // Check if class of obj supports the Cloneable interface. |
675 | // All arrays are considered to be cloneable (See JLS 20.1.5). |
676 | // All j.l.r.Reference classes are considered non-cloneable. |
677 | if (!klass->is_cloneable() || |
678 | (klass->is_instance_klass() && |
679 | InstanceKlass::cast(klass)->reference_type() != REF_NONE)) { |
680 | ResourceMark rm(THREAD); |
681 | THROW_MSG_0(vmSymbols::java_lang_CloneNotSupportedException(), klass->external_name()); |
682 | } |
683 | |
684 | // Make shallow object copy |
685 | const int size = obj->size(); |
686 | oop new_obj_oop = NULL; |
687 | if (obj->is_array()) { |
688 | const int length = ((arrayOop)obj())->length(); |
689 | new_obj_oop = Universe::heap()->array_allocate(klass, size, length, |
690 | /* do_zero */ true, CHECK_NULL); |
691 | } else { |
692 | new_obj_oop = Universe::heap()->obj_allocate(klass, size, CHECK_NULL); |
693 | } |
694 | |
695 | HeapAccess<>::clone(obj(), new_obj_oop, size); |
696 | |
697 | Handle new_obj(THREAD, new_obj_oop); |
698 | // Caution: this involves a java upcall, so the clone should be |
699 | // "gc-robust" by this stage. |
700 | if (klass->has_finalizer()) { |
701 | assert(obj->is_instance(), "should be instanceOop" ); |
702 | new_obj_oop = InstanceKlass::register_finalizer(instanceOop(new_obj()), CHECK_NULL); |
703 | new_obj = Handle(THREAD, new_obj_oop); |
704 | } |
705 | |
706 | return JNIHandles::make_local(env, new_obj()); |
707 | JVM_END |
708 | |
709 | // java.io.File /////////////////////////////////////////////////////////////// |
710 | |
711 | JVM_LEAF(char*, JVM_NativePath(char* path)) |
712 | JVMWrapper("JVM_NativePath" ); |
713 | return os::native_path(path); |
714 | JVM_END |
715 | |
716 | |
717 | // Misc. class handling /////////////////////////////////////////////////////////// |
718 | |
719 | |
720 | JVM_ENTRY(jclass, JVM_GetCallerClass(JNIEnv* env)) |
721 | JVMWrapper("JVM_GetCallerClass" ); |
722 | |
723 | // Getting the class of the caller frame. |
724 | // |
725 | // The call stack at this point looks something like this: |
726 | // |
727 | // [0] [ @CallerSensitive public sun.reflect.Reflection.getCallerClass ] |
728 | // [1] [ @CallerSensitive API.method ] |
729 | // [.] [ (skipped intermediate frames) ] |
730 | // [n] [ caller ] |
731 | vframeStream vfst(thread); |
732 | // Cf. LibraryCallKit::inline_native_Reflection_getCallerClass |
733 | for (int n = 0; !vfst.at_end(); vfst.security_next(), n++) { |
734 | Method* m = vfst.method(); |
735 | assert(m != NULL, "sanity" ); |
736 | switch (n) { |
737 | case 0: |
738 | // This must only be called from Reflection.getCallerClass |
739 | if (m->intrinsic_id() != vmIntrinsics::_getCallerClass) { |
740 | THROW_MSG_NULL(vmSymbols::java_lang_InternalError(), "JVM_GetCallerClass must only be called from Reflection.getCallerClass" ); |
741 | } |
742 | // fall-through |
743 | case 1: |
744 | // Frame 0 and 1 must be caller sensitive. |
745 | if (!m->caller_sensitive()) { |
746 | THROW_MSG_NULL(vmSymbols::java_lang_InternalError(), err_msg("CallerSensitive annotation expected at frame %d" , n)); |
747 | } |
748 | break; |
749 | default: |
750 | if (!m->is_ignored_by_security_stack_walk()) { |
751 | // We have reached the desired frame; return the holder class. |
752 | return (jclass) JNIHandles::make_local(env, m->method_holder()->java_mirror()); |
753 | } |
754 | break; |
755 | } |
756 | } |
757 | return NULL; |
758 | JVM_END |
759 | |
760 | |
761 | JVM_ENTRY(jclass, JVM_FindPrimitiveClass(JNIEnv* env, const char* utf)) |
762 | JVMWrapper("JVM_FindPrimitiveClass" ); |
763 | oop mirror = NULL; |
764 | BasicType t = name2type(utf); |
765 | if (t != T_ILLEGAL && t != T_OBJECT && t != T_ARRAY) { |
766 | mirror = Universe::java_mirror(t); |
767 | } |
768 | if (mirror == NULL) { |
769 | THROW_MSG_0(vmSymbols::java_lang_ClassNotFoundException(), (char*) utf); |
770 | } else { |
771 | return (jclass) JNIHandles::make_local(env, mirror); |
772 | } |
773 | JVM_END |
774 | |
775 | |
776 | // Returns a class loaded by the bootstrap class loader; or null |
777 | // if not found. ClassNotFoundException is not thrown. |
778 | // FindClassFromBootLoader is exported to the launcher for windows. |
779 | JVM_ENTRY(jclass, JVM_FindClassFromBootLoader(JNIEnv* env, |
780 | const char* name)) |
781 | JVMWrapper("JVM_FindClassFromBootLoader" ); |
782 | |
783 | // Java libraries should ensure that name is never null... |
784 | if (name == NULL || (int)strlen(name) > Symbol::max_length()) { |
785 | // It's impossible to create this class; the name cannot fit |
786 | // into the constant pool. |
787 | return NULL; |
788 | } |
789 | |
790 | TempNewSymbol h_name = SymbolTable::new_symbol(name); |
791 | Klass* k = SystemDictionary::resolve_or_null(h_name, CHECK_NULL); |
792 | if (k == NULL) { |
793 | return NULL; |
794 | } |
795 | |
796 | if (log_is_enabled(Debug, class, resolve)) { |
797 | trace_class_resolution(k); |
798 | } |
799 | return (jclass) JNIHandles::make_local(env, k->java_mirror()); |
800 | JVM_END |
801 | |
802 | // Find a class with this name in this loader, using the caller's protection domain. |
803 | JVM_ENTRY(jclass, JVM_FindClassFromCaller(JNIEnv* env, const char* name, |
804 | jboolean init, jobject loader, |
805 | jclass caller)) |
806 | JVMWrapper("JVM_FindClassFromCaller throws ClassNotFoundException" ); |
807 | // Java libraries should ensure that name is never null... |
808 | if (name == NULL || (int)strlen(name) > Symbol::max_length()) { |
809 | // It's impossible to create this class; the name cannot fit |
810 | // into the constant pool. |
811 | THROW_MSG_0(vmSymbols::java_lang_ClassNotFoundException(), name); |
812 | } |
813 | |
814 | TempNewSymbol h_name = SymbolTable::new_symbol(name); |
815 | |
816 | oop loader_oop = JNIHandles::resolve(loader); |
817 | oop from_class = JNIHandles::resolve(caller); |
818 | oop protection_domain = NULL; |
819 | // If loader is null, shouldn't call ClassLoader.checkPackageAccess; otherwise get |
820 | // NPE. Put it in another way, the bootstrap class loader has all permission and |
821 | // thus no checkPackageAccess equivalence in the VM class loader. |
822 | // The caller is also passed as NULL by the java code if there is no security |
823 | // manager to avoid the performance cost of getting the calling class. |
824 | if (from_class != NULL && loader_oop != NULL) { |
825 | protection_domain = java_lang_Class::as_Klass(from_class)->protection_domain(); |
826 | } |
827 | |
828 | Handle h_loader(THREAD, loader_oop); |
829 | Handle h_prot(THREAD, protection_domain); |
830 | jclass result = find_class_from_class_loader(env, h_name, init, h_loader, |
831 | h_prot, false, THREAD); |
832 | |
833 | if (log_is_enabled(Debug, class, resolve) && result != NULL) { |
834 | trace_class_resolution(java_lang_Class::as_Klass(JNIHandles::resolve_non_null(result))); |
835 | } |
836 | return result; |
837 | JVM_END |
838 | |
839 | // Currently only called from the old verifier. |
840 | JVM_ENTRY(jclass, JVM_FindClassFromClass(JNIEnv *env, const char *name, |
841 | jboolean init, jclass from)) |
842 | JVMWrapper("JVM_FindClassFromClass" ); |
843 | if (name == NULL) { |
844 | THROW_MSG_0(vmSymbols::java_lang_NoClassDefFoundError(), "No class name given" ); |
845 | } |
846 | if ((int)strlen(name) > Symbol::max_length()) { |
847 | // It's impossible to create this class; the name cannot fit |
848 | // into the constant pool. |
849 | Exceptions::fthrow(THREAD_AND_LOCATION, |
850 | vmSymbols::java_lang_NoClassDefFoundError(), |
851 | "Class name exceeds maximum length of %d: %s" , |
852 | Symbol::max_length(), |
853 | name); |
854 | return 0; |
855 | } |
856 | TempNewSymbol h_name = SymbolTable::new_symbol(name); |
857 | oop from_class_oop = JNIHandles::resolve(from); |
858 | Klass* from_class = (from_class_oop == NULL) |
859 | ? (Klass*)NULL |
860 | : java_lang_Class::as_Klass(from_class_oop); |
861 | oop class_loader = NULL; |
862 | oop protection_domain = NULL; |
863 | if (from_class != NULL) { |
864 | class_loader = from_class->class_loader(); |
865 | protection_domain = from_class->protection_domain(); |
866 | } |
867 | Handle h_loader(THREAD, class_loader); |
868 | Handle h_prot (THREAD, protection_domain); |
869 | jclass result = find_class_from_class_loader(env, h_name, init, h_loader, |
870 | h_prot, true, thread); |
871 | |
872 | if (log_is_enabled(Debug, class, resolve) && result != NULL) { |
873 | // this function is generally only used for class loading during verification. |
874 | ResourceMark rm; |
875 | oop from_mirror = JNIHandles::resolve_non_null(from); |
876 | Klass* from_class = java_lang_Class::as_Klass(from_mirror); |
877 | const char * from_name = from_class->external_name(); |
878 | |
879 | oop mirror = JNIHandles::resolve_non_null(result); |
880 | Klass* to_class = java_lang_Class::as_Klass(mirror); |
881 | const char * to = to_class->external_name(); |
882 | log_debug(class, resolve)("%s %s (verification)" , from_name, to); |
883 | } |
884 | |
885 | return result; |
886 | JVM_END |
887 | |
888 | static void is_lock_held_by_thread(Handle loader, PerfCounter* counter, TRAPS) { |
889 | if (loader.is_null()) { |
890 | return; |
891 | } |
892 | |
893 | // check whether the current caller thread holds the lock or not. |
894 | // If not, increment the corresponding counter |
895 | if (ObjectSynchronizer::query_lock_ownership((JavaThread*)THREAD, loader) != |
896 | ObjectSynchronizer::owner_self) { |
897 | counter->inc(); |
898 | } |
899 | } |
900 | |
901 | // common code for JVM_DefineClass() and JVM_DefineClassWithSource() |
902 | static jclass jvm_define_class_common(JNIEnv *env, const char *name, |
903 | jobject loader, const jbyte *buf, |
904 | jsize len, jobject pd, const char *source, |
905 | TRAPS) { |
906 | if (source == NULL) source = "__JVM_DefineClass__" ; |
907 | |
908 | assert(THREAD->is_Java_thread(), "must be a JavaThread" ); |
909 | JavaThread* jt = (JavaThread*) THREAD; |
910 | |
911 | PerfClassTraceTime vmtimer(ClassLoader::perf_define_appclass_time(), |
912 | ClassLoader::perf_define_appclass_selftime(), |
913 | ClassLoader::perf_define_appclasses(), |
914 | jt->get_thread_stat()->perf_recursion_counts_addr(), |
915 | jt->get_thread_stat()->perf_timers_addr(), |
916 | PerfClassTraceTime::DEFINE_CLASS); |
917 | |
918 | if (UsePerfData) { |
919 | ClassLoader::perf_app_classfile_bytes_read()->inc(len); |
920 | } |
921 | |
922 | // Since exceptions can be thrown, class initialization can take place |
923 | // if name is NULL no check for class name in .class stream has to be made. |
924 | TempNewSymbol class_name = NULL; |
925 | if (name != NULL) { |
926 | const int str_len = (int)strlen(name); |
927 | if (str_len > Symbol::max_length()) { |
928 | // It's impossible to create this class; the name cannot fit |
929 | // into the constant pool. |
930 | Exceptions::fthrow(THREAD_AND_LOCATION, |
931 | vmSymbols::java_lang_NoClassDefFoundError(), |
932 | "Class name exceeds maximum length of %d: %s" , |
933 | Symbol::max_length(), |
934 | name); |
935 | return 0; |
936 | } |
937 | class_name = SymbolTable::new_symbol(name, str_len); |
938 | } |
939 | |
940 | ResourceMark rm(THREAD); |
941 | ClassFileStream st((u1*)buf, len, source, ClassFileStream::verify); |
942 | Handle class_loader (THREAD, JNIHandles::resolve(loader)); |
943 | if (UsePerfData) { |
944 | is_lock_held_by_thread(class_loader, |
945 | ClassLoader::sync_JVMDefineClassLockFreeCounter(), |
946 | THREAD); |
947 | } |
948 | Handle protection_domain (THREAD, JNIHandles::resolve(pd)); |
949 | Klass* k = SystemDictionary::resolve_from_stream(class_name, |
950 | class_loader, |
951 | protection_domain, |
952 | &st, |
953 | CHECK_NULL); |
954 | |
955 | if (log_is_enabled(Debug, class, resolve) && k != NULL) { |
956 | trace_class_resolution(k); |
957 | } |
958 | |
959 | return (jclass) JNIHandles::make_local(env, k->java_mirror()); |
960 | } |
961 | |
962 | |
963 | JVM_ENTRY(jclass, JVM_DefineClass(JNIEnv *env, const char *name, jobject loader, const jbyte *buf, jsize len, jobject pd)) |
964 | JVMWrapper("JVM_DefineClass" ); |
965 | |
966 | return jvm_define_class_common(env, name, loader, buf, len, pd, NULL, THREAD); |
967 | JVM_END |
968 | |
969 | |
970 | JVM_ENTRY(jclass, JVM_DefineClassWithSource(JNIEnv *env, const char *name, jobject loader, const jbyte *buf, jsize len, jobject pd, const char *source)) |
971 | JVMWrapper("JVM_DefineClassWithSource" ); |
972 | |
973 | return jvm_define_class_common(env, name, loader, buf, len, pd, source, THREAD); |
974 | JVM_END |
975 | |
976 | JVM_ENTRY(jclass, JVM_FindLoadedClass(JNIEnv *env, jobject loader, jstring name)) |
977 | JVMWrapper("JVM_FindLoadedClass" ); |
978 | ResourceMark rm(THREAD); |
979 | |
980 | Handle h_name (THREAD, JNIHandles::resolve_non_null(name)); |
981 | Handle string = java_lang_String::internalize_classname(h_name, CHECK_NULL); |
982 | |
983 | const char* str = java_lang_String::as_utf8_string(string()); |
984 | // Sanity check, don't expect null |
985 | if (str == NULL) return NULL; |
986 | |
987 | const int str_len = (int)strlen(str); |
988 | if (str_len > Symbol::max_length()) { |
989 | // It's impossible to create this class; the name cannot fit |
990 | // into the constant pool. |
991 | return NULL; |
992 | } |
993 | TempNewSymbol klass_name = SymbolTable::new_symbol(str, str_len); |
994 | |
995 | // Security Note: |
996 | // The Java level wrapper will perform the necessary security check allowing |
997 | // us to pass the NULL as the initiating class loader. |
998 | Handle h_loader(THREAD, JNIHandles::resolve(loader)); |
999 | if (UsePerfData) { |
1000 | is_lock_held_by_thread(h_loader, |
1001 | ClassLoader::sync_JVMFindLoadedClassLockFreeCounter(), |
1002 | THREAD); |
1003 | } |
1004 | |
1005 | Klass* k = SystemDictionary::find_instance_or_array_klass(klass_name, |
1006 | h_loader, |
1007 | Handle(), |
1008 | CHECK_NULL); |
1009 | #if INCLUDE_CDS |
1010 | if (k == NULL) { |
1011 | // If the class is not already loaded, try to see if it's in the shared |
1012 | // archive for the current classloader (h_loader). |
1013 | k = SystemDictionaryShared::find_or_load_shared_class(klass_name, h_loader, CHECK_NULL); |
1014 | } |
1015 | #endif |
1016 | return (k == NULL) ? NULL : |
1017 | (jclass) JNIHandles::make_local(env, k->java_mirror()); |
1018 | JVM_END |
1019 | |
1020 | // Module support ////////////////////////////////////////////////////////////////////////////// |
1021 | |
1022 | JVM_ENTRY(void, JVM_DefineModule(JNIEnv *env, jobject module, jboolean is_open, jstring version, |
1023 | jstring location, const char* const* packages, jsize num_packages)) |
1024 | JVMWrapper("JVM_DefineModule" ); |
1025 | Modules::define_module(module, is_open, version, location, packages, num_packages, CHECK); |
1026 | JVM_END |
1027 | |
1028 | JVM_ENTRY(void, JVM_SetBootLoaderUnnamedModule(JNIEnv *env, jobject module)) |
1029 | JVMWrapper("JVM_SetBootLoaderUnnamedModule" ); |
1030 | Modules::set_bootloader_unnamed_module(module, CHECK); |
1031 | JVM_END |
1032 | |
1033 | JVM_ENTRY(void, JVM_AddModuleExports(JNIEnv *env, jobject from_module, const char* package, jobject to_module)) |
1034 | JVMWrapper("JVM_AddModuleExports" ); |
1035 | Modules::add_module_exports_qualified(from_module, package, to_module, CHECK); |
1036 | JVM_END |
1037 | |
1038 | JVM_ENTRY(void, JVM_AddModuleExportsToAllUnnamed(JNIEnv *env, jobject from_module, const char* package)) |
1039 | JVMWrapper("JVM_AddModuleExportsToAllUnnamed" ); |
1040 | Modules::add_module_exports_to_all_unnamed(from_module, package, CHECK); |
1041 | JVM_END |
1042 | |
1043 | JVM_ENTRY(void, JVM_AddModuleExportsToAll(JNIEnv *env, jobject from_module, const char* package)) |
1044 | JVMWrapper("JVM_AddModuleExportsToAll" ); |
1045 | Modules::add_module_exports(from_module, package, NULL, CHECK); |
1046 | JVM_END |
1047 | |
1048 | JVM_ENTRY (void, JVM_AddReadsModule(JNIEnv *env, jobject from_module, jobject source_module)) |
1049 | JVMWrapper("JVM_AddReadsModule" ); |
1050 | Modules::add_reads_module(from_module, source_module, CHECK); |
1051 | JVM_END |
1052 | |
1053 | // Reflection support ////////////////////////////////////////////////////////////////////////////// |
1054 | |
1055 | JVM_ENTRY(jstring, JVM_InitClassName(JNIEnv *env, jclass cls)) |
1056 | assert (cls != NULL, "illegal class" ); |
1057 | JVMWrapper("JVM_InitClassName" ); |
1058 | JvmtiVMObjectAllocEventCollector oam; |
1059 | ResourceMark rm(THREAD); |
1060 | HandleMark hm(THREAD); |
1061 | Handle java_class(THREAD, JNIHandles::resolve(cls)); |
1062 | oop result = java_lang_Class::name(java_class, CHECK_NULL); |
1063 | return (jstring) JNIHandles::make_local(env, result); |
1064 | JVM_END |
1065 | |
1066 | |
1067 | JVM_ENTRY(jobjectArray, JVM_GetClassInterfaces(JNIEnv *env, jclass cls)) |
1068 | JVMWrapper("JVM_GetClassInterfaces" ); |
1069 | JvmtiVMObjectAllocEventCollector oam; |
1070 | oop mirror = JNIHandles::resolve_non_null(cls); |
1071 | |
1072 | // Special handling for primitive objects |
1073 | if (java_lang_Class::is_primitive(mirror)) { |
1074 | // Primitive objects does not have any interfaces |
1075 | objArrayOop r = oopFactory::new_objArray(SystemDictionary::Class_klass(), 0, CHECK_NULL); |
1076 | return (jobjectArray) JNIHandles::make_local(env, r); |
1077 | } |
1078 | |
1079 | Klass* klass = java_lang_Class::as_Klass(mirror); |
1080 | // Figure size of result array |
1081 | int size; |
1082 | if (klass->is_instance_klass()) { |
1083 | size = InstanceKlass::cast(klass)->local_interfaces()->length(); |
1084 | } else { |
1085 | assert(klass->is_objArray_klass() || klass->is_typeArray_klass(), "Illegal mirror klass" ); |
1086 | size = 2; |
1087 | } |
1088 | |
1089 | // Allocate result array |
1090 | objArrayOop r = oopFactory::new_objArray(SystemDictionary::Class_klass(), size, CHECK_NULL); |
1091 | objArrayHandle result (THREAD, r); |
1092 | // Fill in result |
1093 | if (klass->is_instance_klass()) { |
1094 | // Regular instance klass, fill in all local interfaces |
1095 | for (int index = 0; index < size; index++) { |
1096 | Klass* k = InstanceKlass::cast(klass)->local_interfaces()->at(index); |
1097 | result->obj_at_put(index, k->java_mirror()); |
1098 | } |
1099 | } else { |
1100 | // All arrays implement java.lang.Cloneable and java.io.Serializable |
1101 | result->obj_at_put(0, SystemDictionary::Cloneable_klass()->java_mirror()); |
1102 | result->obj_at_put(1, SystemDictionary::Serializable_klass()->java_mirror()); |
1103 | } |
1104 | return (jobjectArray) JNIHandles::make_local(env, result()); |
1105 | JVM_END |
1106 | |
1107 | |
1108 | JVM_QUICK_ENTRY(jboolean, JVM_IsInterface(JNIEnv *env, jclass cls)) |
1109 | JVMWrapper("JVM_IsInterface" ); |
1110 | oop mirror = JNIHandles::resolve_non_null(cls); |
1111 | if (java_lang_Class::is_primitive(mirror)) { |
1112 | return JNI_FALSE; |
1113 | } |
1114 | Klass* k = java_lang_Class::as_Klass(mirror); |
1115 | jboolean result = k->is_interface(); |
1116 | assert(!result || k->is_instance_klass(), |
1117 | "all interfaces are instance types" ); |
1118 | // The compiler intrinsic for isInterface tests the |
1119 | // Klass::_access_flags bits in the same way. |
1120 | return result; |
1121 | JVM_END |
1122 | |
1123 | |
1124 | JVM_ENTRY(jobjectArray, JVM_GetClassSigners(JNIEnv *env, jclass cls)) |
1125 | JVMWrapper("JVM_GetClassSigners" ); |
1126 | JvmtiVMObjectAllocEventCollector oam; |
1127 | if (java_lang_Class::is_primitive(JNIHandles::resolve_non_null(cls))) { |
1128 | // There are no signers for primitive types |
1129 | return NULL; |
1130 | } |
1131 | |
1132 | objArrayHandle signers(THREAD, java_lang_Class::signers(JNIHandles::resolve_non_null(cls))); |
1133 | |
1134 | // If there are no signers set in the class, or if the class |
1135 | // is an array, return NULL. |
1136 | if (signers == NULL) return NULL; |
1137 | |
1138 | // copy of the signers array |
1139 | Klass* element = ObjArrayKlass::cast(signers->klass())->element_klass(); |
1140 | objArrayOop signers_copy = oopFactory::new_objArray(element, signers->length(), CHECK_NULL); |
1141 | for (int index = 0; index < signers->length(); index++) { |
1142 | signers_copy->obj_at_put(index, signers->obj_at(index)); |
1143 | } |
1144 | |
1145 | // return the copy |
1146 | return (jobjectArray) JNIHandles::make_local(env, signers_copy); |
1147 | JVM_END |
1148 | |
1149 | |
1150 | JVM_ENTRY(void, JVM_SetClassSigners(JNIEnv *env, jclass cls, jobjectArray signers)) |
1151 | JVMWrapper("JVM_SetClassSigners" ); |
1152 | if (!java_lang_Class::is_primitive(JNIHandles::resolve_non_null(cls))) { |
1153 | // This call is ignored for primitive types and arrays. |
1154 | // Signers are only set once, ClassLoader.java, and thus shouldn't |
1155 | // be called with an array. Only the bootstrap loader creates arrays. |
1156 | Klass* k = java_lang_Class::as_Klass(JNIHandles::resolve_non_null(cls)); |
1157 | if (k->is_instance_klass()) { |
1158 | java_lang_Class::set_signers(k->java_mirror(), objArrayOop(JNIHandles::resolve(signers))); |
1159 | } |
1160 | } |
1161 | JVM_END |
1162 | |
1163 | |
1164 | JVM_ENTRY(jobject, JVM_GetProtectionDomain(JNIEnv *env, jclass cls)) |
1165 | JVMWrapper("JVM_GetProtectionDomain" ); |
1166 | if (JNIHandles::resolve(cls) == NULL) { |
1167 | THROW_(vmSymbols::java_lang_NullPointerException(), NULL); |
1168 | } |
1169 | |
1170 | if (java_lang_Class::is_primitive(JNIHandles::resolve(cls))) { |
1171 | // Primitive types does not have a protection domain. |
1172 | return NULL; |
1173 | } |
1174 | |
1175 | oop pd = java_lang_Class::protection_domain(JNIHandles::resolve(cls)); |
1176 | return (jobject) JNIHandles::make_local(env, pd); |
1177 | JVM_END |
1178 | |
1179 | |
1180 | // Returns the inherited_access_control_context field of the running thread. |
1181 | JVM_ENTRY(jobject, JVM_GetInheritedAccessControlContext(JNIEnv *env, jclass cls)) |
1182 | JVMWrapper("JVM_GetInheritedAccessControlContext" ); |
1183 | oop result = java_lang_Thread::inherited_access_control_context(thread->threadObj()); |
1184 | return JNIHandles::make_local(env, result); |
1185 | JVM_END |
1186 | |
1187 | class RegisterArrayForGC { |
1188 | private: |
1189 | JavaThread *_thread; |
1190 | public: |
1191 | RegisterArrayForGC(JavaThread *thread, GrowableArray<oop>* array) { |
1192 | _thread = thread; |
1193 | _thread->register_array_for_gc(array); |
1194 | } |
1195 | |
1196 | ~RegisterArrayForGC() { |
1197 | _thread->register_array_for_gc(NULL); |
1198 | } |
1199 | }; |
1200 | |
1201 | |
1202 | JVM_ENTRY(jobject, JVM_GetStackAccessControlContext(JNIEnv *env, jclass cls)) |
1203 | JVMWrapper("JVM_GetStackAccessControlContext" ); |
1204 | if (!UsePrivilegedStack) return NULL; |
1205 | |
1206 | ResourceMark rm(THREAD); |
1207 | GrowableArray<oop>* local_array = new GrowableArray<oop>(12); |
1208 | JvmtiVMObjectAllocEventCollector oam; |
1209 | |
1210 | // count the protection domains on the execution stack. We collapse |
1211 | // duplicate consecutive protection domains into a single one, as |
1212 | // well as stopping when we hit a privileged frame. |
1213 | |
1214 | oop previous_protection_domain = NULL; |
1215 | Handle privileged_context(thread, NULL); |
1216 | bool is_privileged = false; |
1217 | oop protection_domain = NULL; |
1218 | |
1219 | // Iterate through Java frames |
1220 | vframeStream vfst(thread); |
1221 | for(; !vfst.at_end(); vfst.next()) { |
1222 | // get method of frame |
1223 | Method* method = vfst.method(); |
1224 | |
1225 | // stop at the first privileged frame |
1226 | if (method->method_holder() == SystemDictionary::AccessController_klass() && |
1227 | method->name() == vmSymbols::executePrivileged_name()) |
1228 | { |
1229 | // this frame is privileged |
1230 | is_privileged = true; |
1231 | |
1232 | javaVFrame *priv = vfst.asJavaVFrame(); // executePrivileged |
1233 | |
1234 | StackValueCollection* locals = priv->locals(); |
1235 | StackValue* ctx_sv = locals->at(1); // AccessControlContext context |
1236 | StackValue* clr_sv = locals->at(2); // Class<?> caller |
1237 | assert(!ctx_sv->obj_is_scalar_replaced(), "found scalar-replaced object" ); |
1238 | assert(!clr_sv->obj_is_scalar_replaced(), "found scalar-replaced object" ); |
1239 | privileged_context = ctx_sv->get_obj(); |
1240 | Handle caller = clr_sv->get_obj(); |
1241 | |
1242 | Klass *caller_klass = java_lang_Class::as_Klass(caller()); |
1243 | protection_domain = caller_klass->protection_domain(); |
1244 | } else { |
1245 | protection_domain = method->method_holder()->protection_domain(); |
1246 | } |
1247 | |
1248 | if ((!oopDesc::equals(previous_protection_domain, protection_domain)) && (protection_domain != NULL)) { |
1249 | local_array->push(protection_domain); |
1250 | previous_protection_domain = protection_domain; |
1251 | } |
1252 | |
1253 | if (is_privileged) break; |
1254 | } |
1255 | |
1256 | |
1257 | // either all the domains on the stack were system domains, or |
1258 | // we had a privileged system domain |
1259 | if (local_array->is_empty()) { |
1260 | if (is_privileged && privileged_context.is_null()) return NULL; |
1261 | |
1262 | oop result = java_security_AccessControlContext::create(objArrayHandle(), is_privileged, privileged_context, CHECK_NULL); |
1263 | return JNIHandles::make_local(env, result); |
1264 | } |
1265 | |
1266 | // the resource area must be registered in case of a gc |
1267 | RegisterArrayForGC ragc(thread, local_array); |
1268 | objArrayOop context = oopFactory::new_objArray(SystemDictionary::ProtectionDomain_klass(), |
1269 | local_array->length(), CHECK_NULL); |
1270 | objArrayHandle h_context(thread, context); |
1271 | for (int index = 0; index < local_array->length(); index++) { |
1272 | h_context->obj_at_put(index, local_array->at(index)); |
1273 | } |
1274 | |
1275 | oop result = java_security_AccessControlContext::create(h_context, is_privileged, privileged_context, CHECK_NULL); |
1276 | |
1277 | return JNIHandles::make_local(env, result); |
1278 | JVM_END |
1279 | |
1280 | |
1281 | JVM_QUICK_ENTRY(jboolean, JVM_IsArrayClass(JNIEnv *env, jclass cls)) |
1282 | JVMWrapper("JVM_IsArrayClass" ); |
1283 | Klass* k = java_lang_Class::as_Klass(JNIHandles::resolve_non_null(cls)); |
1284 | return (k != NULL) && k->is_array_klass() ? true : false; |
1285 | JVM_END |
1286 | |
1287 | |
1288 | JVM_QUICK_ENTRY(jboolean, JVM_IsPrimitiveClass(JNIEnv *env, jclass cls)) |
1289 | JVMWrapper("JVM_IsPrimitiveClass" ); |
1290 | oop mirror = JNIHandles::resolve_non_null(cls); |
1291 | return (jboolean) java_lang_Class::is_primitive(mirror); |
1292 | JVM_END |
1293 | |
1294 | |
1295 | JVM_ENTRY(jint, JVM_GetClassModifiers(JNIEnv *env, jclass cls)) |
1296 | JVMWrapper("JVM_GetClassModifiers" ); |
1297 | if (java_lang_Class::is_primitive(JNIHandles::resolve_non_null(cls))) { |
1298 | // Primitive type |
1299 | return JVM_ACC_ABSTRACT | JVM_ACC_FINAL | JVM_ACC_PUBLIC; |
1300 | } |
1301 | |
1302 | Klass* k = java_lang_Class::as_Klass(JNIHandles::resolve_non_null(cls)); |
1303 | debug_only(int computed_modifiers = k->compute_modifier_flags(CHECK_0)); |
1304 | assert(k->modifier_flags() == computed_modifiers, "modifiers cache is OK" ); |
1305 | return k->modifier_flags(); |
1306 | JVM_END |
1307 | |
1308 | |
1309 | // Inner class reflection /////////////////////////////////////////////////////////////////////////////// |
1310 | |
1311 | JVM_ENTRY(jobjectArray, JVM_GetDeclaredClasses(JNIEnv *env, jclass ofClass)) |
1312 | JvmtiVMObjectAllocEventCollector oam; |
1313 | // ofClass is a reference to a java_lang_Class object. The mirror object |
1314 | // of an InstanceKlass |
1315 | |
1316 | if (java_lang_Class::is_primitive(JNIHandles::resolve_non_null(ofClass)) || |
1317 | ! java_lang_Class::as_Klass(JNIHandles::resolve_non_null(ofClass))->is_instance_klass()) { |
1318 | oop result = oopFactory::new_objArray(SystemDictionary::Class_klass(), 0, CHECK_NULL); |
1319 | return (jobjectArray)JNIHandles::make_local(env, result); |
1320 | } |
1321 | |
1322 | InstanceKlass* k = InstanceKlass::cast(java_lang_Class::as_Klass(JNIHandles::resolve_non_null(ofClass))); |
1323 | InnerClassesIterator iter(k); |
1324 | |
1325 | if (iter.length() == 0) { |
1326 | // Neither an inner nor outer class |
1327 | oop result = oopFactory::new_objArray(SystemDictionary::Class_klass(), 0, CHECK_NULL); |
1328 | return (jobjectArray)JNIHandles::make_local(env, result); |
1329 | } |
1330 | |
1331 | // find inner class info |
1332 | constantPoolHandle cp(thread, k->constants()); |
1333 | int length = iter.length(); |
1334 | |
1335 | // Allocate temp. result array |
1336 | objArrayOop r = oopFactory::new_objArray(SystemDictionary::Class_klass(), length/4, CHECK_NULL); |
1337 | objArrayHandle result (THREAD, r); |
1338 | int members = 0; |
1339 | |
1340 | for (; !iter.done(); iter.next()) { |
1341 | int ioff = iter.inner_class_info_index(); |
1342 | int ooff = iter.outer_class_info_index(); |
1343 | |
1344 | if (ioff != 0 && ooff != 0) { |
1345 | // Check to see if the name matches the class we're looking for |
1346 | // before attempting to find the class. |
1347 | if (cp->klass_name_at_matches(k, ooff)) { |
1348 | Klass* outer_klass = cp->klass_at(ooff, CHECK_NULL); |
1349 | if (outer_klass == k) { |
1350 | Klass* ik = cp->klass_at(ioff, CHECK_NULL); |
1351 | InstanceKlass* inner_klass = InstanceKlass::cast(ik); |
1352 | |
1353 | // Throws an exception if outer klass has not declared k as |
1354 | // an inner klass |
1355 | Reflection::check_for_inner_class(k, inner_klass, true, CHECK_NULL); |
1356 | |
1357 | result->obj_at_put(members, inner_klass->java_mirror()); |
1358 | members++; |
1359 | } |
1360 | } |
1361 | } |
1362 | } |
1363 | |
1364 | if (members != length) { |
1365 | // Return array of right length |
1366 | objArrayOop res = oopFactory::new_objArray(SystemDictionary::Class_klass(), members, CHECK_NULL); |
1367 | for(int i = 0; i < members; i++) { |
1368 | res->obj_at_put(i, result->obj_at(i)); |
1369 | } |
1370 | return (jobjectArray)JNIHandles::make_local(env, res); |
1371 | } |
1372 | |
1373 | return (jobjectArray)JNIHandles::make_local(env, result()); |
1374 | JVM_END |
1375 | |
1376 | |
1377 | JVM_ENTRY(jclass, JVM_GetDeclaringClass(JNIEnv *env, jclass ofClass)) |
1378 | { |
1379 | // ofClass is a reference to a java_lang_Class object. |
1380 | if (java_lang_Class::is_primitive(JNIHandles::resolve_non_null(ofClass)) || |
1381 | ! java_lang_Class::as_Klass(JNIHandles::resolve_non_null(ofClass))->is_instance_klass()) { |
1382 | return NULL; |
1383 | } |
1384 | |
1385 | bool inner_is_member = false; |
1386 | Klass* outer_klass |
1387 | = InstanceKlass::cast(java_lang_Class::as_Klass(JNIHandles::resolve_non_null(ofClass)) |
1388 | )->compute_enclosing_class(&inner_is_member, CHECK_NULL); |
1389 | if (outer_klass == NULL) return NULL; // already a top-level class |
1390 | if (!inner_is_member) return NULL; // an anonymous class (inside a method) |
1391 | return (jclass) JNIHandles::make_local(env, outer_klass->java_mirror()); |
1392 | } |
1393 | JVM_END |
1394 | |
1395 | JVM_ENTRY(jstring, JVM_GetSimpleBinaryName(JNIEnv *env, jclass cls)) |
1396 | { |
1397 | oop mirror = JNIHandles::resolve_non_null(cls); |
1398 | if (java_lang_Class::is_primitive(mirror) || |
1399 | !java_lang_Class::as_Klass(mirror)->is_instance_klass()) { |
1400 | return NULL; |
1401 | } |
1402 | InstanceKlass* k = InstanceKlass::cast(java_lang_Class::as_Klass(mirror)); |
1403 | int ooff = 0, noff = 0; |
1404 | if (k->find_inner_classes_attr(&ooff, &noff, THREAD)) { |
1405 | if (noff != 0) { |
1406 | constantPoolHandle i_cp(thread, k->constants()); |
1407 | Symbol* name = i_cp->symbol_at(noff); |
1408 | Handle str = java_lang_String::create_from_symbol(name, CHECK_NULL); |
1409 | return (jstring) JNIHandles::make_local(env, str()); |
1410 | } |
1411 | } |
1412 | return NULL; |
1413 | } |
1414 | JVM_END |
1415 | |
1416 | JVM_ENTRY(jstring, JVM_GetClassSignature(JNIEnv *env, jclass cls)) |
1417 | assert (cls != NULL, "illegal class" ); |
1418 | JVMWrapper("JVM_GetClassSignature" ); |
1419 | JvmtiVMObjectAllocEventCollector oam; |
1420 | ResourceMark rm(THREAD); |
1421 | // Return null for arrays and primatives |
1422 | if (!java_lang_Class::is_primitive(JNIHandles::resolve(cls))) { |
1423 | Klass* k = java_lang_Class::as_Klass(JNIHandles::resolve(cls)); |
1424 | if (k->is_instance_klass()) { |
1425 | Symbol* sym = InstanceKlass::cast(k)->generic_signature(); |
1426 | if (sym == NULL) return NULL; |
1427 | Handle str = java_lang_String::create_from_symbol(sym, CHECK_NULL); |
1428 | return (jstring) JNIHandles::make_local(env, str()); |
1429 | } |
1430 | } |
1431 | return NULL; |
1432 | JVM_END |
1433 | |
1434 | |
1435 | JVM_ENTRY(jbyteArray, JVM_GetClassAnnotations(JNIEnv *env, jclass cls)) |
1436 | assert (cls != NULL, "illegal class" ); |
1437 | JVMWrapper("JVM_GetClassAnnotations" ); |
1438 | |
1439 | // Return null for arrays and primitives |
1440 | if (!java_lang_Class::is_primitive(JNIHandles::resolve(cls))) { |
1441 | Klass* k = java_lang_Class::as_Klass(JNIHandles::resolve(cls)); |
1442 | if (k->is_instance_klass()) { |
1443 | typeArrayOop a = Annotations::make_java_array(InstanceKlass::cast(k)->class_annotations(), CHECK_NULL); |
1444 | return (jbyteArray) JNIHandles::make_local(env, a); |
1445 | } |
1446 | } |
1447 | return NULL; |
1448 | JVM_END |
1449 | |
1450 | |
1451 | static bool jvm_get_field_common(jobject field, fieldDescriptor& fd, TRAPS) { |
1452 | // some of this code was adapted from from jni_FromReflectedField |
1453 | |
1454 | oop reflected = JNIHandles::resolve_non_null(field); |
1455 | oop mirror = java_lang_reflect_Field::clazz(reflected); |
1456 | Klass* k = java_lang_Class::as_Klass(mirror); |
1457 | int slot = java_lang_reflect_Field::slot(reflected); |
1458 | int modifiers = java_lang_reflect_Field::modifiers(reflected); |
1459 | |
1460 | InstanceKlass* ik = InstanceKlass::cast(k); |
1461 | intptr_t offset = ik->field_offset(slot); |
1462 | |
1463 | if (modifiers & JVM_ACC_STATIC) { |
1464 | // for static fields we only look in the current class |
1465 | if (!ik->find_local_field_from_offset(offset, true, &fd)) { |
1466 | assert(false, "cannot find static field" ); |
1467 | return false; |
1468 | } |
1469 | } else { |
1470 | // for instance fields we start with the current class and work |
1471 | // our way up through the superclass chain |
1472 | if (!ik->find_field_from_offset(offset, false, &fd)) { |
1473 | assert(false, "cannot find instance field" ); |
1474 | return false; |
1475 | } |
1476 | } |
1477 | return true; |
1478 | } |
1479 | |
1480 | static Method* jvm_get_method_common(jobject method) { |
1481 | // some of this code was adapted from from jni_FromReflectedMethod |
1482 | |
1483 | oop reflected = JNIHandles::resolve_non_null(method); |
1484 | oop mirror = NULL; |
1485 | int slot = 0; |
1486 | |
1487 | if (reflected->klass() == SystemDictionary::reflect_Constructor_klass()) { |
1488 | mirror = java_lang_reflect_Constructor::clazz(reflected); |
1489 | slot = java_lang_reflect_Constructor::slot(reflected); |
1490 | } else { |
1491 | assert(reflected->klass() == SystemDictionary::reflect_Method_klass(), |
1492 | "wrong type" ); |
1493 | mirror = java_lang_reflect_Method::clazz(reflected); |
1494 | slot = java_lang_reflect_Method::slot(reflected); |
1495 | } |
1496 | Klass* k = java_lang_Class::as_Klass(mirror); |
1497 | |
1498 | Method* m = InstanceKlass::cast(k)->method_with_idnum(slot); |
1499 | assert(m != NULL, "cannot find method" ); |
1500 | return m; // caller has to deal with NULL in product mode |
1501 | } |
1502 | |
1503 | /* Type use annotations support (JDK 1.8) */ |
1504 | |
1505 | JVM_ENTRY(jbyteArray, JVM_GetClassTypeAnnotations(JNIEnv *env, jclass cls)) |
1506 | assert (cls != NULL, "illegal class" ); |
1507 | JVMWrapper("JVM_GetClassTypeAnnotations" ); |
1508 | ResourceMark rm(THREAD); |
1509 | // Return null for arrays and primitives |
1510 | if (!java_lang_Class::is_primitive(JNIHandles::resolve(cls))) { |
1511 | Klass* k = java_lang_Class::as_Klass(JNIHandles::resolve(cls)); |
1512 | if (k->is_instance_klass()) { |
1513 | AnnotationArray* type_annotations = InstanceKlass::cast(k)->class_type_annotations(); |
1514 | if (type_annotations != NULL) { |
1515 | typeArrayOop a = Annotations::make_java_array(type_annotations, CHECK_NULL); |
1516 | return (jbyteArray) JNIHandles::make_local(env, a); |
1517 | } |
1518 | } |
1519 | } |
1520 | return NULL; |
1521 | JVM_END |
1522 | |
1523 | JVM_ENTRY(jbyteArray, JVM_GetMethodTypeAnnotations(JNIEnv *env, jobject method)) |
1524 | assert (method != NULL, "illegal method" ); |
1525 | JVMWrapper("JVM_GetMethodTypeAnnotations" ); |
1526 | |
1527 | // method is a handle to a java.lang.reflect.Method object |
1528 | Method* m = jvm_get_method_common(method); |
1529 | if (m == NULL) { |
1530 | return NULL; |
1531 | } |
1532 | |
1533 | AnnotationArray* type_annotations = m->type_annotations(); |
1534 | if (type_annotations != NULL) { |
1535 | typeArrayOop a = Annotations::make_java_array(type_annotations, CHECK_NULL); |
1536 | return (jbyteArray) JNIHandles::make_local(env, a); |
1537 | } |
1538 | |
1539 | return NULL; |
1540 | JVM_END |
1541 | |
1542 | JVM_ENTRY(jbyteArray, JVM_GetFieldTypeAnnotations(JNIEnv *env, jobject field)) |
1543 | assert (field != NULL, "illegal field" ); |
1544 | JVMWrapper("JVM_GetFieldTypeAnnotations" ); |
1545 | |
1546 | fieldDescriptor fd; |
1547 | bool gotFd = jvm_get_field_common(field, fd, CHECK_NULL); |
1548 | if (!gotFd) { |
1549 | return NULL; |
1550 | } |
1551 | |
1552 | return (jbyteArray) JNIHandles::make_local(env, Annotations::make_java_array(fd.type_annotations(), THREAD)); |
1553 | JVM_END |
1554 | |
1555 | static void bounds_check(const constantPoolHandle& cp, jint index, TRAPS) { |
1556 | if (!cp->is_within_bounds(index)) { |
1557 | THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(), "Constant pool index out of bounds" ); |
1558 | } |
1559 | } |
1560 | |
1561 | JVM_ENTRY(jobjectArray, JVM_GetMethodParameters(JNIEnv *env, jobject method)) |
1562 | { |
1563 | JVMWrapper("JVM_GetMethodParameters" ); |
1564 | // method is a handle to a java.lang.reflect.Method object |
1565 | Method* method_ptr = jvm_get_method_common(method); |
1566 | methodHandle mh (THREAD, method_ptr); |
1567 | Handle reflected_method (THREAD, JNIHandles::resolve_non_null(method)); |
1568 | const int num_params = mh->method_parameters_length(); |
1569 | |
1570 | if (num_params < 0) { |
1571 | // A -1 return value from method_parameters_length means there is no |
1572 | // parameter data. Return null to indicate this to the reflection |
1573 | // API. |
1574 | assert(num_params == -1, "num_params should be -1 if it is less than zero" ); |
1575 | return (jobjectArray)NULL; |
1576 | } else { |
1577 | // Otherwise, we return something up to reflection, even if it is |
1578 | // a zero-length array. Why? Because in some cases this can |
1579 | // trigger a MalformedParametersException. |
1580 | |
1581 | // make sure all the symbols are properly formatted |
1582 | for (int i = 0; i < num_params; i++) { |
1583 | MethodParametersElement* params = mh->method_parameters_start(); |
1584 | int index = params[i].name_cp_index; |
1585 | bounds_check(mh->constants(), index, CHECK_NULL); |
1586 | |
1587 | if (0 != index && !mh->constants()->tag_at(index).is_utf8()) { |
1588 | THROW_MSG_0(vmSymbols::java_lang_IllegalArgumentException(), |
1589 | "Wrong type at constant pool index" ); |
1590 | } |
1591 | |
1592 | } |
1593 | |
1594 | objArrayOop result_oop = oopFactory::new_objArray(SystemDictionary::reflect_Parameter_klass(), num_params, CHECK_NULL); |
1595 | objArrayHandle result (THREAD, result_oop); |
1596 | |
1597 | for (int i = 0; i < num_params; i++) { |
1598 | MethodParametersElement* params = mh->method_parameters_start(); |
1599 | // For a 0 index, give a NULL symbol |
1600 | Symbol* sym = 0 != params[i].name_cp_index ? |
1601 | mh->constants()->symbol_at(params[i].name_cp_index) : NULL; |
1602 | int flags = params[i].flags; |
1603 | oop param = Reflection::new_parameter(reflected_method, i, sym, |
1604 | flags, CHECK_NULL); |
1605 | result->obj_at_put(i, param); |
1606 | } |
1607 | return (jobjectArray)JNIHandles::make_local(env, result()); |
1608 | } |
1609 | } |
1610 | JVM_END |
1611 | |
1612 | // New (JDK 1.4) reflection implementation ///////////////////////////////////// |
1613 | |
1614 | JVM_ENTRY(jobjectArray, JVM_GetClassDeclaredFields(JNIEnv *env, jclass ofClass, jboolean publicOnly)) |
1615 | { |
1616 | JVMWrapper("JVM_GetClassDeclaredFields" ); |
1617 | JvmtiVMObjectAllocEventCollector oam; |
1618 | |
1619 | // Exclude primitive types and array types |
1620 | if (java_lang_Class::is_primitive(JNIHandles::resolve_non_null(ofClass)) || |
1621 | java_lang_Class::as_Klass(JNIHandles::resolve_non_null(ofClass))->is_array_klass()) { |
1622 | // Return empty array |
1623 | oop res = oopFactory::new_objArray(SystemDictionary::reflect_Field_klass(), 0, CHECK_NULL); |
1624 | return (jobjectArray) JNIHandles::make_local(env, res); |
1625 | } |
1626 | |
1627 | InstanceKlass* k = InstanceKlass::cast(java_lang_Class::as_Klass(JNIHandles::resolve_non_null(ofClass))); |
1628 | constantPoolHandle cp(THREAD, k->constants()); |
1629 | |
1630 | // Ensure class is linked |
1631 | k->link_class(CHECK_NULL); |
1632 | |
1633 | // Allocate result |
1634 | int num_fields; |
1635 | |
1636 | if (publicOnly) { |
1637 | num_fields = 0; |
1638 | for (JavaFieldStream fs(k); !fs.done(); fs.next()) { |
1639 | if (fs.access_flags().is_public()) ++num_fields; |
1640 | } |
1641 | } else { |
1642 | num_fields = k->java_fields_count(); |
1643 | } |
1644 | |
1645 | objArrayOop r = oopFactory::new_objArray(SystemDictionary::reflect_Field_klass(), num_fields, CHECK_NULL); |
1646 | objArrayHandle result (THREAD, r); |
1647 | |
1648 | int out_idx = 0; |
1649 | fieldDescriptor fd; |
1650 | for (JavaFieldStream fs(k); !fs.done(); fs.next()) { |
1651 | if (!publicOnly || fs.access_flags().is_public()) { |
1652 | fd.reinitialize(k, fs.index()); |
1653 | oop field = Reflection::new_field(&fd, CHECK_NULL); |
1654 | result->obj_at_put(out_idx, field); |
1655 | ++out_idx; |
1656 | } |
1657 | } |
1658 | assert(out_idx == num_fields, "just checking" ); |
1659 | return (jobjectArray) JNIHandles::make_local(env, result()); |
1660 | } |
1661 | JVM_END |
1662 | |
1663 | static bool select_method(const methodHandle& method, bool want_constructor) { |
1664 | if (want_constructor) { |
1665 | return (method->is_initializer() && !method->is_static()); |
1666 | } else { |
1667 | return (!method->is_initializer() && !method->is_overpass()); |
1668 | } |
1669 | } |
1670 | |
1671 | static jobjectArray get_class_declared_methods_helper( |
1672 | JNIEnv *env, |
1673 | jclass ofClass, jboolean publicOnly, |
1674 | bool want_constructor, |
1675 | Klass* klass, TRAPS) { |
1676 | |
1677 | JvmtiVMObjectAllocEventCollector oam; |
1678 | |
1679 | // Exclude primitive types and array types |
1680 | if (java_lang_Class::is_primitive(JNIHandles::resolve_non_null(ofClass)) |
1681 | || java_lang_Class::as_Klass(JNIHandles::resolve_non_null(ofClass))->is_array_klass()) { |
1682 | // Return empty array |
1683 | oop res = oopFactory::new_objArray(klass, 0, CHECK_NULL); |
1684 | return (jobjectArray) JNIHandles::make_local(env, res); |
1685 | } |
1686 | |
1687 | InstanceKlass* k = InstanceKlass::cast(java_lang_Class::as_Klass(JNIHandles::resolve_non_null(ofClass))); |
1688 | |
1689 | // Ensure class is linked |
1690 | k->link_class(CHECK_NULL); |
1691 | |
1692 | Array<Method*>* methods = k->methods(); |
1693 | int methods_length = methods->length(); |
1694 | |
1695 | // Save original method_idnum in case of redefinition, which can change |
1696 | // the idnum of obsolete methods. The new method will have the same idnum |
1697 | // but if we refresh the methods array, the counts will be wrong. |
1698 | ResourceMark rm(THREAD); |
1699 | GrowableArray<int>* idnums = new GrowableArray<int>(methods_length); |
1700 | int num_methods = 0; |
1701 | |
1702 | for (int i = 0; i < methods_length; i++) { |
1703 | methodHandle method(THREAD, methods->at(i)); |
1704 | if (select_method(method, want_constructor)) { |
1705 | if (!publicOnly || method->is_public()) { |
1706 | idnums->push(method->method_idnum()); |
1707 | ++num_methods; |
1708 | } |
1709 | } |
1710 | } |
1711 | |
1712 | // Allocate result |
1713 | objArrayOop r = oopFactory::new_objArray(klass, num_methods, CHECK_NULL); |
1714 | objArrayHandle result (THREAD, r); |
1715 | |
1716 | // Now just put the methods that we selected above, but go by their idnum |
1717 | // in case of redefinition. The methods can be redefined at any safepoint, |
1718 | // so above when allocating the oop array and below when creating reflect |
1719 | // objects. |
1720 | for (int i = 0; i < num_methods; i++) { |
1721 | methodHandle method(THREAD, k->method_with_idnum(idnums->at(i))); |
1722 | if (method.is_null()) { |
1723 | // Method may have been deleted and seems this API can handle null |
1724 | // Otherwise should probably put a method that throws NSME |
1725 | result->obj_at_put(i, NULL); |
1726 | } else { |
1727 | oop m; |
1728 | if (want_constructor) { |
1729 | m = Reflection::new_constructor(method, CHECK_NULL); |
1730 | } else { |
1731 | m = Reflection::new_method(method, false, CHECK_NULL); |
1732 | } |
1733 | result->obj_at_put(i, m); |
1734 | } |
1735 | } |
1736 | |
1737 | return (jobjectArray) JNIHandles::make_local(env, result()); |
1738 | } |
1739 | |
1740 | JVM_ENTRY(jobjectArray, JVM_GetClassDeclaredMethods(JNIEnv *env, jclass ofClass, jboolean publicOnly)) |
1741 | { |
1742 | JVMWrapper("JVM_GetClassDeclaredMethods" ); |
1743 | return get_class_declared_methods_helper(env, ofClass, publicOnly, |
1744 | /*want_constructor*/ false, |
1745 | SystemDictionary::reflect_Method_klass(), THREAD); |
1746 | } |
1747 | JVM_END |
1748 | |
1749 | JVM_ENTRY(jobjectArray, JVM_GetClassDeclaredConstructors(JNIEnv *env, jclass ofClass, jboolean publicOnly)) |
1750 | { |
1751 | JVMWrapper("JVM_GetClassDeclaredConstructors" ); |
1752 | return get_class_declared_methods_helper(env, ofClass, publicOnly, |
1753 | /*want_constructor*/ true, |
1754 | SystemDictionary::reflect_Constructor_klass(), THREAD); |
1755 | } |
1756 | JVM_END |
1757 | |
1758 | JVM_ENTRY(jint, JVM_GetClassAccessFlags(JNIEnv *env, jclass cls)) |
1759 | { |
1760 | JVMWrapper("JVM_GetClassAccessFlags" ); |
1761 | if (java_lang_Class::is_primitive(JNIHandles::resolve_non_null(cls))) { |
1762 | // Primitive type |
1763 | return JVM_ACC_ABSTRACT | JVM_ACC_FINAL | JVM_ACC_PUBLIC; |
1764 | } |
1765 | |
1766 | Klass* k = java_lang_Class::as_Klass(JNIHandles::resolve_non_null(cls)); |
1767 | return k->access_flags().as_int() & JVM_ACC_WRITTEN_FLAGS; |
1768 | } |
1769 | JVM_END |
1770 | |
1771 | JVM_ENTRY(jboolean, JVM_AreNestMates(JNIEnv *env, jclass current, jclass member)) |
1772 | { |
1773 | JVMWrapper("JVM_AreNestMates" ); |
1774 | Klass* c = java_lang_Class::as_Klass(JNIHandles::resolve_non_null(current)); |
1775 | assert(c->is_instance_klass(), "must be" ); |
1776 | InstanceKlass* ck = InstanceKlass::cast(c); |
1777 | Klass* m = java_lang_Class::as_Klass(JNIHandles::resolve_non_null(member)); |
1778 | assert(m->is_instance_klass(), "must be" ); |
1779 | InstanceKlass* mk = InstanceKlass::cast(m); |
1780 | return ck->has_nestmate_access_to(mk, THREAD); |
1781 | } |
1782 | JVM_END |
1783 | |
1784 | JVM_ENTRY(jclass, JVM_GetNestHost(JNIEnv* env, jclass current)) |
1785 | { |
1786 | // current is not a primitive or array class |
1787 | JVMWrapper("JVM_GetNestHost" ); |
1788 | Klass* c = java_lang_Class::as_Klass(JNIHandles::resolve_non_null(current)); |
1789 | assert(c->is_instance_klass(), "must be" ); |
1790 | InstanceKlass* ck = InstanceKlass::cast(c); |
1791 | // Don't post exceptions if validation fails |
1792 | InstanceKlass* host = ck->nest_host(NULL, THREAD); |
1793 | return (jclass) (host == NULL ? NULL : |
1794 | JNIHandles::make_local(THREAD, host->java_mirror())); |
1795 | } |
1796 | JVM_END |
1797 | |
1798 | JVM_ENTRY(jobjectArray, JVM_GetNestMembers(JNIEnv* env, jclass current)) |
1799 | { |
1800 | // current is not a primitive or array class |
1801 | JVMWrapper("JVM_GetNestMembers" ); |
1802 | Klass* c = java_lang_Class::as_Klass(JNIHandles::resolve_non_null(current)); |
1803 | assert(c->is_instance_klass(), "must be" ); |
1804 | InstanceKlass* ck = InstanceKlass::cast(c); |
1805 | // Get the nest host for this nest - throw ICCE if validation fails |
1806 | Symbol* icce = vmSymbols::java_lang_IncompatibleClassChangeError(); |
1807 | InstanceKlass* host = ck->nest_host(icce, CHECK_NULL); |
1808 | |
1809 | { |
1810 | JvmtiVMObjectAllocEventCollector oam; |
1811 | Array<u2>* members = host->nest_members(); |
1812 | int length = members == NULL ? 0 : members->length(); |
1813 | // nest host is first in the array so make it one bigger |
1814 | objArrayOop r = oopFactory::new_objArray(SystemDictionary::Class_klass(), |
1815 | length + 1, CHECK_NULL); |
1816 | objArrayHandle result (THREAD, r); |
1817 | result->obj_at_put(0, host->java_mirror()); |
1818 | if (length != 0) { |
1819 | int i; |
1820 | for (i = 0; i < length; i++) { |
1821 | int cp_index = members->at(i); |
1822 | Klass* k = host->constants()->klass_at(cp_index, CHECK_NULL); |
1823 | if (k->is_instance_klass()) { |
1824 | InstanceKlass* nest_host_k = |
1825 | InstanceKlass::cast(k)->nest_host(icce, CHECK_NULL); |
1826 | if (nest_host_k == host) { |
1827 | result->obj_at_put(i+1, k->java_mirror()); |
1828 | } |
1829 | else { |
1830 | // k's nest host is legal but it isn't our host so |
1831 | // throw ICCE |
1832 | ResourceMark rm(THREAD); |
1833 | Exceptions::fthrow(THREAD_AND_LOCATION, |
1834 | icce, |
1835 | "Nest member %s in %s declares a different nest host of %s" , |
1836 | k->external_name(), |
1837 | host->external_name(), |
1838 | nest_host_k->external_name() |
1839 | ); |
1840 | return NULL; |
1841 | } |
1842 | } |
1843 | else { |
1844 | // we have a bad nest member entry - throw ICCE |
1845 | ResourceMark rm(THREAD); |
1846 | Exceptions::fthrow(THREAD_AND_LOCATION, |
1847 | icce, |
1848 | "Class %s can not be a nest member of %s" , |
1849 | k->external_name(), |
1850 | host->external_name() |
1851 | ); |
1852 | return NULL; |
1853 | } |
1854 | } |
1855 | } |
1856 | else { |
1857 | assert(host == ck, "must be singleton nest" ); |
1858 | } |
1859 | return (jobjectArray)JNIHandles::make_local(THREAD, result()); |
1860 | } |
1861 | } |
1862 | JVM_END |
1863 | |
1864 | // Constant pool access ////////////////////////////////////////////////////////// |
1865 | |
1866 | JVM_ENTRY(jobject, JVM_GetClassConstantPool(JNIEnv *env, jclass cls)) |
1867 | { |
1868 | JVMWrapper("JVM_GetClassConstantPool" ); |
1869 | JvmtiVMObjectAllocEventCollector oam; |
1870 | |
1871 | // Return null for primitives and arrays |
1872 | if (!java_lang_Class::is_primitive(JNIHandles::resolve_non_null(cls))) { |
1873 | Klass* k = java_lang_Class::as_Klass(JNIHandles::resolve_non_null(cls)); |
1874 | if (k->is_instance_klass()) { |
1875 | InstanceKlass* k_h = InstanceKlass::cast(k); |
1876 | Handle jcp = reflect_ConstantPool::create(CHECK_NULL); |
1877 | reflect_ConstantPool::set_cp(jcp(), k_h->constants()); |
1878 | return JNIHandles::make_local(jcp()); |
1879 | } |
1880 | } |
1881 | return NULL; |
1882 | } |
1883 | JVM_END |
1884 | |
1885 | |
1886 | JVM_ENTRY(jint, JVM_ConstantPoolGetSize(JNIEnv *env, jobject obj, jobject unused)) |
1887 | { |
1888 | JVMWrapper("JVM_ConstantPoolGetSize" ); |
1889 | constantPoolHandle cp = constantPoolHandle(THREAD, reflect_ConstantPool::get_cp(JNIHandles::resolve_non_null(obj))); |
1890 | return cp->length(); |
1891 | } |
1892 | JVM_END |
1893 | |
1894 | |
1895 | JVM_ENTRY(jclass, JVM_ConstantPoolGetClassAt(JNIEnv *env, jobject obj, jobject unused, jint index)) |
1896 | { |
1897 | JVMWrapper("JVM_ConstantPoolGetClassAt" ); |
1898 | constantPoolHandle cp = constantPoolHandle(THREAD, reflect_ConstantPool::get_cp(JNIHandles::resolve_non_null(obj))); |
1899 | bounds_check(cp, index, CHECK_NULL); |
1900 | constantTag tag = cp->tag_at(index); |
1901 | if (!tag.is_klass() && !tag.is_unresolved_klass()) { |
1902 | THROW_MSG_0(vmSymbols::java_lang_IllegalArgumentException(), "Wrong type at constant pool index" ); |
1903 | } |
1904 | Klass* k = cp->klass_at(index, CHECK_NULL); |
1905 | return (jclass) JNIHandles::make_local(k->java_mirror()); |
1906 | } |
1907 | JVM_END |
1908 | |
1909 | JVM_ENTRY(jclass, JVM_ConstantPoolGetClassAtIfLoaded(JNIEnv *env, jobject obj, jobject unused, jint index)) |
1910 | { |
1911 | JVMWrapper("JVM_ConstantPoolGetClassAtIfLoaded" ); |
1912 | constantPoolHandle cp = constantPoolHandle(THREAD, reflect_ConstantPool::get_cp(JNIHandles::resolve_non_null(obj))); |
1913 | bounds_check(cp, index, CHECK_NULL); |
1914 | constantTag tag = cp->tag_at(index); |
1915 | if (!tag.is_klass() && !tag.is_unresolved_klass()) { |
1916 | THROW_MSG_0(vmSymbols::java_lang_IllegalArgumentException(), "Wrong type at constant pool index" ); |
1917 | } |
1918 | Klass* k = ConstantPool::klass_at_if_loaded(cp, index); |
1919 | if (k == NULL) return NULL; |
1920 | return (jclass) JNIHandles::make_local(k->java_mirror()); |
1921 | } |
1922 | JVM_END |
1923 | |
1924 | static jobject get_method_at_helper(const constantPoolHandle& cp, jint index, bool force_resolution, TRAPS) { |
1925 | constantTag tag = cp->tag_at(index); |
1926 | if (!tag.is_method() && !tag.is_interface_method()) { |
1927 | THROW_MSG_0(vmSymbols::java_lang_IllegalArgumentException(), "Wrong type at constant pool index" ); |
1928 | } |
1929 | int klass_ref = cp->uncached_klass_ref_index_at(index); |
1930 | Klass* k_o; |
1931 | if (force_resolution) { |
1932 | k_o = cp->klass_at(klass_ref, CHECK_NULL); |
1933 | } else { |
1934 | k_o = ConstantPool::klass_at_if_loaded(cp, klass_ref); |
1935 | if (k_o == NULL) return NULL; |
1936 | } |
1937 | InstanceKlass* k = InstanceKlass::cast(k_o); |
1938 | Symbol* name = cp->uncached_name_ref_at(index); |
1939 | Symbol* sig = cp->uncached_signature_ref_at(index); |
1940 | methodHandle m (THREAD, k->find_method(name, sig)); |
1941 | if (m.is_null()) { |
1942 | THROW_MSG_0(vmSymbols::java_lang_RuntimeException(), "Unable to look up method in target class" ); |
1943 | } |
1944 | oop method; |
1945 | if (!m->is_initializer() || m->is_static()) { |
1946 | method = Reflection::new_method(m, true, CHECK_NULL); |
1947 | } else { |
1948 | method = Reflection::new_constructor(m, CHECK_NULL); |
1949 | } |
1950 | return JNIHandles::make_local(method); |
1951 | } |
1952 | |
1953 | JVM_ENTRY(jobject, JVM_ConstantPoolGetMethodAt(JNIEnv *env, jobject obj, jobject unused, jint index)) |
1954 | { |
1955 | JVMWrapper("JVM_ConstantPoolGetMethodAt" ); |
1956 | JvmtiVMObjectAllocEventCollector oam; |
1957 | constantPoolHandle cp = constantPoolHandle(THREAD, reflect_ConstantPool::get_cp(JNIHandles::resolve_non_null(obj))); |
1958 | bounds_check(cp, index, CHECK_NULL); |
1959 | jobject res = get_method_at_helper(cp, index, true, CHECK_NULL); |
1960 | return res; |
1961 | } |
1962 | JVM_END |
1963 | |
1964 | JVM_ENTRY(jobject, JVM_ConstantPoolGetMethodAtIfLoaded(JNIEnv *env, jobject obj, jobject unused, jint index)) |
1965 | { |
1966 | JVMWrapper("JVM_ConstantPoolGetMethodAtIfLoaded" ); |
1967 | JvmtiVMObjectAllocEventCollector oam; |
1968 | constantPoolHandle cp = constantPoolHandle(THREAD, reflect_ConstantPool::get_cp(JNIHandles::resolve_non_null(obj))); |
1969 | bounds_check(cp, index, CHECK_NULL); |
1970 | jobject res = get_method_at_helper(cp, index, false, CHECK_NULL); |
1971 | return res; |
1972 | } |
1973 | JVM_END |
1974 | |
1975 | static jobject get_field_at_helper(constantPoolHandle cp, jint index, bool force_resolution, TRAPS) { |
1976 | constantTag tag = cp->tag_at(index); |
1977 | if (!tag.is_field()) { |
1978 | THROW_MSG_0(vmSymbols::java_lang_IllegalArgumentException(), "Wrong type at constant pool index" ); |
1979 | } |
1980 | int klass_ref = cp->uncached_klass_ref_index_at(index); |
1981 | Klass* k_o; |
1982 | if (force_resolution) { |
1983 | k_o = cp->klass_at(klass_ref, CHECK_NULL); |
1984 | } else { |
1985 | k_o = ConstantPool::klass_at_if_loaded(cp, klass_ref); |
1986 | if (k_o == NULL) return NULL; |
1987 | } |
1988 | InstanceKlass* k = InstanceKlass::cast(k_o); |
1989 | Symbol* name = cp->uncached_name_ref_at(index); |
1990 | Symbol* sig = cp->uncached_signature_ref_at(index); |
1991 | fieldDescriptor fd; |
1992 | Klass* target_klass = k->find_field(name, sig, &fd); |
1993 | if (target_klass == NULL) { |
1994 | THROW_MSG_0(vmSymbols::java_lang_RuntimeException(), "Unable to look up field in target class" ); |
1995 | } |
1996 | oop field = Reflection::new_field(&fd, CHECK_NULL); |
1997 | return JNIHandles::make_local(field); |
1998 | } |
1999 | |
2000 | JVM_ENTRY(jobject, JVM_ConstantPoolGetFieldAt(JNIEnv *env, jobject obj, jobject unusedl, jint index)) |
2001 | { |
2002 | JVMWrapper("JVM_ConstantPoolGetFieldAt" ); |
2003 | JvmtiVMObjectAllocEventCollector oam; |
2004 | constantPoolHandle cp = constantPoolHandle(THREAD, reflect_ConstantPool::get_cp(JNIHandles::resolve_non_null(obj))); |
2005 | bounds_check(cp, index, CHECK_NULL); |
2006 | jobject res = get_field_at_helper(cp, index, true, CHECK_NULL); |
2007 | return res; |
2008 | } |
2009 | JVM_END |
2010 | |
2011 | JVM_ENTRY(jobject, JVM_ConstantPoolGetFieldAtIfLoaded(JNIEnv *env, jobject obj, jobject unused, jint index)) |
2012 | { |
2013 | JVMWrapper("JVM_ConstantPoolGetFieldAtIfLoaded" ); |
2014 | JvmtiVMObjectAllocEventCollector oam; |
2015 | constantPoolHandle cp = constantPoolHandle(THREAD, reflect_ConstantPool::get_cp(JNIHandles::resolve_non_null(obj))); |
2016 | bounds_check(cp, index, CHECK_NULL); |
2017 | jobject res = get_field_at_helper(cp, index, false, CHECK_NULL); |
2018 | return res; |
2019 | } |
2020 | JVM_END |
2021 | |
2022 | JVM_ENTRY(jobjectArray, JVM_ConstantPoolGetMemberRefInfoAt(JNIEnv *env, jobject obj, jobject unused, jint index)) |
2023 | { |
2024 | JVMWrapper("JVM_ConstantPoolGetMemberRefInfoAt" ); |
2025 | JvmtiVMObjectAllocEventCollector oam; |
2026 | constantPoolHandle cp = constantPoolHandle(THREAD, reflect_ConstantPool::get_cp(JNIHandles::resolve_non_null(obj))); |
2027 | bounds_check(cp, index, CHECK_NULL); |
2028 | constantTag tag = cp->tag_at(index); |
2029 | if (!tag.is_field_or_method()) { |
2030 | THROW_MSG_0(vmSymbols::java_lang_IllegalArgumentException(), "Wrong type at constant pool index" ); |
2031 | } |
2032 | int klass_ref = cp->uncached_klass_ref_index_at(index); |
2033 | Symbol* klass_name = cp->klass_name_at(klass_ref); |
2034 | Symbol* member_name = cp->uncached_name_ref_at(index); |
2035 | Symbol* member_sig = cp->uncached_signature_ref_at(index); |
2036 | objArrayOop dest_o = oopFactory::new_objArray(SystemDictionary::String_klass(), 3, CHECK_NULL); |
2037 | objArrayHandle dest(THREAD, dest_o); |
2038 | Handle str = java_lang_String::create_from_symbol(klass_name, CHECK_NULL); |
2039 | dest->obj_at_put(0, str()); |
2040 | str = java_lang_String::create_from_symbol(member_name, CHECK_NULL); |
2041 | dest->obj_at_put(1, str()); |
2042 | str = java_lang_String::create_from_symbol(member_sig, CHECK_NULL); |
2043 | dest->obj_at_put(2, str()); |
2044 | return (jobjectArray) JNIHandles::make_local(dest()); |
2045 | } |
2046 | JVM_END |
2047 | |
2048 | JVM_ENTRY(jint, JVM_ConstantPoolGetClassRefIndexAt(JNIEnv *env, jobject obj, jobject unused, jint index)) |
2049 | { |
2050 | JVMWrapper("JVM_ConstantPoolGetClassRefIndexAt" ); |
2051 | JvmtiVMObjectAllocEventCollector oam; |
2052 | constantPoolHandle cp(THREAD, reflect_ConstantPool::get_cp(JNIHandles::resolve_non_null(obj))); |
2053 | bounds_check(cp, index, CHECK_0); |
2054 | constantTag tag = cp->tag_at(index); |
2055 | if (!tag.is_field_or_method()) { |
2056 | THROW_MSG_0(vmSymbols::java_lang_IllegalArgumentException(), "Wrong type at constant pool index" ); |
2057 | } |
2058 | return (jint) cp->uncached_klass_ref_index_at(index); |
2059 | } |
2060 | JVM_END |
2061 | |
2062 | JVM_ENTRY(jint, JVM_ConstantPoolGetNameAndTypeRefIndexAt(JNIEnv *env, jobject obj, jobject unused, jint index)) |
2063 | { |
2064 | JVMWrapper("JVM_ConstantPoolGetNameAndTypeRefIndexAt" ); |
2065 | JvmtiVMObjectAllocEventCollector oam; |
2066 | constantPoolHandle cp(THREAD, reflect_ConstantPool::get_cp(JNIHandles::resolve_non_null(obj))); |
2067 | bounds_check(cp, index, CHECK_0); |
2068 | constantTag tag = cp->tag_at(index); |
2069 | if (!tag.is_invoke_dynamic() && !tag.is_field_or_method()) { |
2070 | THROW_MSG_0(vmSymbols::java_lang_IllegalArgumentException(), "Wrong type at constant pool index" ); |
2071 | } |
2072 | return (jint) cp->uncached_name_and_type_ref_index_at(index); |
2073 | } |
2074 | JVM_END |
2075 | |
2076 | JVM_ENTRY(jobjectArray, JVM_ConstantPoolGetNameAndTypeRefInfoAt(JNIEnv *env, jobject obj, jobject unused, jint index)) |
2077 | { |
2078 | JVMWrapper("JVM_ConstantPoolGetNameAndTypeRefInfoAt" ); |
2079 | JvmtiVMObjectAllocEventCollector oam; |
2080 | constantPoolHandle cp(THREAD, reflect_ConstantPool::get_cp(JNIHandles::resolve_non_null(obj))); |
2081 | bounds_check(cp, index, CHECK_NULL); |
2082 | constantTag tag = cp->tag_at(index); |
2083 | if (!tag.is_name_and_type()) { |
2084 | THROW_MSG_0(vmSymbols::java_lang_IllegalArgumentException(), "Wrong type at constant pool index" ); |
2085 | } |
2086 | Symbol* member_name = cp->symbol_at(cp->name_ref_index_at(index)); |
2087 | Symbol* member_sig = cp->symbol_at(cp->signature_ref_index_at(index)); |
2088 | objArrayOop dest_o = oopFactory::new_objArray(SystemDictionary::String_klass(), 2, CHECK_NULL); |
2089 | objArrayHandle dest(THREAD, dest_o); |
2090 | Handle str = java_lang_String::create_from_symbol(member_name, CHECK_NULL); |
2091 | dest->obj_at_put(0, str()); |
2092 | str = java_lang_String::create_from_symbol(member_sig, CHECK_NULL); |
2093 | dest->obj_at_put(1, str()); |
2094 | return (jobjectArray) JNIHandles::make_local(dest()); |
2095 | } |
2096 | JVM_END |
2097 | |
2098 | JVM_ENTRY(jint, JVM_ConstantPoolGetIntAt(JNIEnv *env, jobject obj, jobject unused, jint index)) |
2099 | { |
2100 | JVMWrapper("JVM_ConstantPoolGetIntAt" ); |
2101 | constantPoolHandle cp = constantPoolHandle(THREAD, reflect_ConstantPool::get_cp(JNIHandles::resolve_non_null(obj))); |
2102 | bounds_check(cp, index, CHECK_0); |
2103 | constantTag tag = cp->tag_at(index); |
2104 | if (!tag.is_int()) { |
2105 | THROW_MSG_0(vmSymbols::java_lang_IllegalArgumentException(), "Wrong type at constant pool index" ); |
2106 | } |
2107 | return cp->int_at(index); |
2108 | } |
2109 | JVM_END |
2110 | |
2111 | JVM_ENTRY(jlong, JVM_ConstantPoolGetLongAt(JNIEnv *env, jobject obj, jobject unused, jint index)) |
2112 | { |
2113 | JVMWrapper("JVM_ConstantPoolGetLongAt" ); |
2114 | constantPoolHandle cp = constantPoolHandle(THREAD, reflect_ConstantPool::get_cp(JNIHandles::resolve_non_null(obj))); |
2115 | bounds_check(cp, index, CHECK_(0L)); |
2116 | constantTag tag = cp->tag_at(index); |
2117 | if (!tag.is_long()) { |
2118 | THROW_MSG_0(vmSymbols::java_lang_IllegalArgumentException(), "Wrong type at constant pool index" ); |
2119 | } |
2120 | return cp->long_at(index); |
2121 | } |
2122 | JVM_END |
2123 | |
2124 | JVM_ENTRY(jfloat, JVM_ConstantPoolGetFloatAt(JNIEnv *env, jobject obj, jobject unused, jint index)) |
2125 | { |
2126 | JVMWrapper("JVM_ConstantPoolGetFloatAt" ); |
2127 | constantPoolHandle cp = constantPoolHandle(THREAD, reflect_ConstantPool::get_cp(JNIHandles::resolve_non_null(obj))); |
2128 | bounds_check(cp, index, CHECK_(0.0f)); |
2129 | constantTag tag = cp->tag_at(index); |
2130 | if (!tag.is_float()) { |
2131 | THROW_MSG_0(vmSymbols::java_lang_IllegalArgumentException(), "Wrong type at constant pool index" ); |
2132 | } |
2133 | return cp->float_at(index); |
2134 | } |
2135 | JVM_END |
2136 | |
2137 | JVM_ENTRY(jdouble, JVM_ConstantPoolGetDoubleAt(JNIEnv *env, jobject obj, jobject unused, jint index)) |
2138 | { |
2139 | JVMWrapper("JVM_ConstantPoolGetDoubleAt" ); |
2140 | constantPoolHandle cp = constantPoolHandle(THREAD, reflect_ConstantPool::get_cp(JNIHandles::resolve_non_null(obj))); |
2141 | bounds_check(cp, index, CHECK_(0.0)); |
2142 | constantTag tag = cp->tag_at(index); |
2143 | if (!tag.is_double()) { |
2144 | THROW_MSG_0(vmSymbols::java_lang_IllegalArgumentException(), "Wrong type at constant pool index" ); |
2145 | } |
2146 | return cp->double_at(index); |
2147 | } |
2148 | JVM_END |
2149 | |
2150 | JVM_ENTRY(jstring, JVM_ConstantPoolGetStringAt(JNIEnv *env, jobject obj, jobject unused, jint index)) |
2151 | { |
2152 | JVMWrapper("JVM_ConstantPoolGetStringAt" ); |
2153 | constantPoolHandle cp = constantPoolHandle(THREAD, reflect_ConstantPool::get_cp(JNIHandles::resolve_non_null(obj))); |
2154 | bounds_check(cp, index, CHECK_NULL); |
2155 | constantTag tag = cp->tag_at(index); |
2156 | if (!tag.is_string()) { |
2157 | THROW_MSG_0(vmSymbols::java_lang_IllegalArgumentException(), "Wrong type at constant pool index" ); |
2158 | } |
2159 | oop str = cp->string_at(index, CHECK_NULL); |
2160 | return (jstring) JNIHandles::make_local(str); |
2161 | } |
2162 | JVM_END |
2163 | |
2164 | JVM_ENTRY(jstring, JVM_ConstantPoolGetUTF8At(JNIEnv *env, jobject obj, jobject unused, jint index)) |
2165 | { |
2166 | JVMWrapper("JVM_ConstantPoolGetUTF8At" ); |
2167 | JvmtiVMObjectAllocEventCollector oam; |
2168 | constantPoolHandle cp = constantPoolHandle(THREAD, reflect_ConstantPool::get_cp(JNIHandles::resolve_non_null(obj))); |
2169 | bounds_check(cp, index, CHECK_NULL); |
2170 | constantTag tag = cp->tag_at(index); |
2171 | if (!tag.is_symbol()) { |
2172 | THROW_MSG_0(vmSymbols::java_lang_IllegalArgumentException(), "Wrong type at constant pool index" ); |
2173 | } |
2174 | Symbol* sym = cp->symbol_at(index); |
2175 | Handle str = java_lang_String::create_from_symbol(sym, CHECK_NULL); |
2176 | return (jstring) JNIHandles::make_local(str()); |
2177 | } |
2178 | JVM_END |
2179 | |
2180 | JVM_ENTRY(jbyte, JVM_ConstantPoolGetTagAt(JNIEnv *env, jobject obj, jobject unused, jint index)) |
2181 | { |
2182 | JVMWrapper("JVM_ConstantPoolGetTagAt" ); |
2183 | constantPoolHandle cp = constantPoolHandle(THREAD, reflect_ConstantPool::get_cp(JNIHandles::resolve_non_null(obj))); |
2184 | bounds_check(cp, index, CHECK_0); |
2185 | constantTag tag = cp->tag_at(index); |
2186 | jbyte result = tag.value(); |
2187 | // If returned tag values are not from the JVM spec, e.g. tags from 100 to 105, |
2188 | // they are changed to the corresponding tags from the JVM spec, so that java code in |
2189 | // sun.reflect.ConstantPool will return only tags from the JVM spec, not internal ones. |
2190 | if (tag.is_klass_or_reference()) { |
2191 | result = JVM_CONSTANT_Class; |
2192 | } else if (tag.is_string_index()) { |
2193 | result = JVM_CONSTANT_String; |
2194 | } else if (tag.is_method_type_in_error()) { |
2195 | result = JVM_CONSTANT_MethodType; |
2196 | } else if (tag.is_method_handle_in_error()) { |
2197 | result = JVM_CONSTANT_MethodHandle; |
2198 | } else if (tag.is_dynamic_constant_in_error()) { |
2199 | result = JVM_CONSTANT_Dynamic; |
2200 | } |
2201 | return result; |
2202 | } |
2203 | JVM_END |
2204 | |
2205 | // Assertion support. ////////////////////////////////////////////////////////// |
2206 | |
2207 | JVM_ENTRY(jboolean, JVM_DesiredAssertionStatus(JNIEnv *env, jclass unused, jclass cls)) |
2208 | JVMWrapper("JVM_DesiredAssertionStatus" ); |
2209 | assert(cls != NULL, "bad class" ); |
2210 | |
2211 | oop r = JNIHandles::resolve(cls); |
2212 | assert(! java_lang_Class::is_primitive(r), "primitive classes not allowed" ); |
2213 | if (java_lang_Class::is_primitive(r)) return false; |
2214 | |
2215 | Klass* k = java_lang_Class::as_Klass(r); |
2216 | assert(k->is_instance_klass(), "must be an instance klass" ); |
2217 | if (!k->is_instance_klass()) return false; |
2218 | |
2219 | ResourceMark rm(THREAD); |
2220 | const char* name = k->name()->as_C_string(); |
2221 | bool system_class = k->class_loader() == NULL; |
2222 | return JavaAssertions::enabled(name, system_class); |
2223 | |
2224 | JVM_END |
2225 | |
2226 | |
2227 | // Return a new AssertionStatusDirectives object with the fields filled in with |
2228 | // command-line assertion arguments (i.e., -ea, -da). |
2229 | JVM_ENTRY(jobject, JVM_AssertionStatusDirectives(JNIEnv *env, jclass unused)) |
2230 | JVMWrapper("JVM_AssertionStatusDirectives" ); |
2231 | JvmtiVMObjectAllocEventCollector oam; |
2232 | oop asd = JavaAssertions::createAssertionStatusDirectives(CHECK_NULL); |
2233 | return JNIHandles::make_local(env, asd); |
2234 | JVM_END |
2235 | |
2236 | // Verification //////////////////////////////////////////////////////////////////////////////// |
2237 | |
2238 | // Reflection for the verifier ///////////////////////////////////////////////////////////////// |
2239 | |
2240 | // RedefineClasses support: bug 6214132 caused verification to fail. |
2241 | // All functions from this section should call the jvmtiThreadSate function: |
2242 | // Klass* class_to_verify_considering_redefinition(Klass* klass). |
2243 | // The function returns a Klass* of the _scratch_class if the verifier |
2244 | // was invoked in the middle of the class redefinition. |
2245 | // Otherwise it returns its argument value which is the _the_class Klass*. |
2246 | // Please, refer to the description in the jvmtiThreadSate.hpp. |
2247 | |
2248 | JVM_ENTRY(const char*, JVM_GetClassNameUTF(JNIEnv *env, jclass cls)) |
2249 | JVMWrapper("JVM_GetClassNameUTF" ); |
2250 | Klass* k = java_lang_Class::as_Klass(JNIHandles::resolve_non_null(cls)); |
2251 | k = JvmtiThreadState::class_to_verify_considering_redefinition(k, thread); |
2252 | return k->name()->as_utf8(); |
2253 | JVM_END |
2254 | |
2255 | |
2256 | JVM_QUICK_ENTRY(void, JVM_GetClassCPTypes(JNIEnv *env, jclass cls, unsigned char *types)) |
2257 | JVMWrapper("JVM_GetClassCPTypes" ); |
2258 | Klass* k = java_lang_Class::as_Klass(JNIHandles::resolve_non_null(cls)); |
2259 | k = JvmtiThreadState::class_to_verify_considering_redefinition(k, thread); |
2260 | // types will have length zero if this is not an InstanceKlass |
2261 | // (length is determined by call to JVM_GetClassCPEntriesCount) |
2262 | if (k->is_instance_klass()) { |
2263 | ConstantPool* cp = InstanceKlass::cast(k)->constants(); |
2264 | for (int index = cp->length() - 1; index >= 0; index--) { |
2265 | constantTag tag = cp->tag_at(index); |
2266 | types[index] = (tag.is_unresolved_klass()) ? JVM_CONSTANT_Class : tag.value(); |
2267 | } |
2268 | } |
2269 | JVM_END |
2270 | |
2271 | |
2272 | JVM_QUICK_ENTRY(jint, JVM_GetClassCPEntriesCount(JNIEnv *env, jclass cls)) |
2273 | JVMWrapper("JVM_GetClassCPEntriesCount" ); |
2274 | Klass* k = java_lang_Class::as_Klass(JNIHandles::resolve_non_null(cls)); |
2275 | k = JvmtiThreadState::class_to_verify_considering_redefinition(k, thread); |
2276 | return (!k->is_instance_klass()) ? 0 : InstanceKlass::cast(k)->constants()->length(); |
2277 | JVM_END |
2278 | |
2279 | |
2280 | JVM_QUICK_ENTRY(jint, JVM_GetClassFieldsCount(JNIEnv *env, jclass cls)) |
2281 | JVMWrapper("JVM_GetClassFieldsCount" ); |
2282 | Klass* k = java_lang_Class::as_Klass(JNIHandles::resolve_non_null(cls)); |
2283 | k = JvmtiThreadState::class_to_verify_considering_redefinition(k, thread); |
2284 | return (!k->is_instance_klass()) ? 0 : InstanceKlass::cast(k)->java_fields_count(); |
2285 | JVM_END |
2286 | |
2287 | |
2288 | JVM_QUICK_ENTRY(jint, JVM_GetClassMethodsCount(JNIEnv *env, jclass cls)) |
2289 | JVMWrapper("JVM_GetClassMethodsCount" ); |
2290 | Klass* k = java_lang_Class::as_Klass(JNIHandles::resolve_non_null(cls)); |
2291 | k = JvmtiThreadState::class_to_verify_considering_redefinition(k, thread); |
2292 | return (!k->is_instance_klass()) ? 0 : InstanceKlass::cast(k)->methods()->length(); |
2293 | JVM_END |
2294 | |
2295 | |
2296 | // The following methods, used for the verifier, are never called with |
2297 | // array klasses, so a direct cast to InstanceKlass is safe. |
2298 | // Typically, these methods are called in a loop with bounds determined |
2299 | // by the results of JVM_GetClass{Fields,Methods}Count, which return |
2300 | // zero for arrays. |
2301 | JVM_QUICK_ENTRY(void, JVM_GetMethodIxExceptionIndexes(JNIEnv *env, jclass cls, jint method_index, unsigned short *exceptions)) |
2302 | JVMWrapper("JVM_GetMethodIxExceptionIndexes" ); |
2303 | Klass* k = java_lang_Class::as_Klass(JNIHandles::resolve_non_null(cls)); |
2304 | k = JvmtiThreadState::class_to_verify_considering_redefinition(k, thread); |
2305 | Method* method = InstanceKlass::cast(k)->methods()->at(method_index); |
2306 | int length = method->checked_exceptions_length(); |
2307 | if (length > 0) { |
2308 | CheckedExceptionElement* table= method->checked_exceptions_start(); |
2309 | for (int i = 0; i < length; i++) { |
2310 | exceptions[i] = table[i].class_cp_index; |
2311 | } |
2312 | } |
2313 | JVM_END |
2314 | |
2315 | |
2316 | JVM_QUICK_ENTRY(jint, JVM_GetMethodIxExceptionsCount(JNIEnv *env, jclass cls, jint method_index)) |
2317 | JVMWrapper("JVM_GetMethodIxExceptionsCount" ); |
2318 | Klass* k = java_lang_Class::as_Klass(JNIHandles::resolve_non_null(cls)); |
2319 | k = JvmtiThreadState::class_to_verify_considering_redefinition(k, thread); |
2320 | Method* method = InstanceKlass::cast(k)->methods()->at(method_index); |
2321 | return method->checked_exceptions_length(); |
2322 | JVM_END |
2323 | |
2324 | |
2325 | JVM_QUICK_ENTRY(void, JVM_GetMethodIxByteCode(JNIEnv *env, jclass cls, jint method_index, unsigned char *code)) |
2326 | JVMWrapper("JVM_GetMethodIxByteCode" ); |
2327 | Klass* k = java_lang_Class::as_Klass(JNIHandles::resolve_non_null(cls)); |
2328 | k = JvmtiThreadState::class_to_verify_considering_redefinition(k, thread); |
2329 | Method* method = InstanceKlass::cast(k)->methods()->at(method_index); |
2330 | memcpy(code, method->code_base(), method->code_size()); |
2331 | JVM_END |
2332 | |
2333 | |
2334 | JVM_QUICK_ENTRY(jint, JVM_GetMethodIxByteCodeLength(JNIEnv *env, jclass cls, jint method_index)) |
2335 | JVMWrapper("JVM_GetMethodIxByteCodeLength" ); |
2336 | Klass* k = java_lang_Class::as_Klass(JNIHandles::resolve_non_null(cls)); |
2337 | k = JvmtiThreadState::class_to_verify_considering_redefinition(k, thread); |
2338 | Method* method = InstanceKlass::cast(k)->methods()->at(method_index); |
2339 | return method->code_size(); |
2340 | JVM_END |
2341 | |
2342 | |
2343 | JVM_QUICK_ENTRY(void, JVM_GetMethodIxExceptionTableEntry(JNIEnv *env, jclass cls, jint method_index, jint entry_index, JVM_ExceptionTableEntryType *entry)) |
2344 | JVMWrapper("JVM_GetMethodIxExceptionTableEntry" ); |
2345 | Klass* k = java_lang_Class::as_Klass(JNIHandles::resolve_non_null(cls)); |
2346 | k = JvmtiThreadState::class_to_verify_considering_redefinition(k, thread); |
2347 | Method* method = InstanceKlass::cast(k)->methods()->at(method_index); |
2348 | ExceptionTable extable(method); |
2349 | entry->start_pc = extable.start_pc(entry_index); |
2350 | entry->end_pc = extable.end_pc(entry_index); |
2351 | entry->handler_pc = extable.handler_pc(entry_index); |
2352 | entry->catchType = extable.catch_type_index(entry_index); |
2353 | JVM_END |
2354 | |
2355 | |
2356 | JVM_QUICK_ENTRY(jint, JVM_GetMethodIxExceptionTableLength(JNIEnv *env, jclass cls, int method_index)) |
2357 | JVMWrapper("JVM_GetMethodIxExceptionTableLength" ); |
2358 | Klass* k = java_lang_Class::as_Klass(JNIHandles::resolve_non_null(cls)); |
2359 | k = JvmtiThreadState::class_to_verify_considering_redefinition(k, thread); |
2360 | Method* method = InstanceKlass::cast(k)->methods()->at(method_index); |
2361 | return method->exception_table_length(); |
2362 | JVM_END |
2363 | |
2364 | |
2365 | JVM_QUICK_ENTRY(jint, JVM_GetMethodIxModifiers(JNIEnv *env, jclass cls, int method_index)) |
2366 | JVMWrapper("JVM_GetMethodIxModifiers" ); |
2367 | Klass* k = java_lang_Class::as_Klass(JNIHandles::resolve_non_null(cls)); |
2368 | k = JvmtiThreadState::class_to_verify_considering_redefinition(k, thread); |
2369 | Method* method = InstanceKlass::cast(k)->methods()->at(method_index); |
2370 | return method->access_flags().as_int() & JVM_RECOGNIZED_METHOD_MODIFIERS; |
2371 | JVM_END |
2372 | |
2373 | |
2374 | JVM_QUICK_ENTRY(jint, JVM_GetFieldIxModifiers(JNIEnv *env, jclass cls, int field_index)) |
2375 | JVMWrapper("JVM_GetFieldIxModifiers" ); |
2376 | Klass* k = java_lang_Class::as_Klass(JNIHandles::resolve_non_null(cls)); |
2377 | k = JvmtiThreadState::class_to_verify_considering_redefinition(k, thread); |
2378 | return InstanceKlass::cast(k)->field_access_flags(field_index) & JVM_RECOGNIZED_FIELD_MODIFIERS; |
2379 | JVM_END |
2380 | |
2381 | |
2382 | JVM_QUICK_ENTRY(jint, JVM_GetMethodIxLocalsCount(JNIEnv *env, jclass cls, int method_index)) |
2383 | JVMWrapper("JVM_GetMethodIxLocalsCount" ); |
2384 | Klass* k = java_lang_Class::as_Klass(JNIHandles::resolve_non_null(cls)); |
2385 | k = JvmtiThreadState::class_to_verify_considering_redefinition(k, thread); |
2386 | Method* method = InstanceKlass::cast(k)->methods()->at(method_index); |
2387 | return method->max_locals(); |
2388 | JVM_END |
2389 | |
2390 | |
2391 | JVM_QUICK_ENTRY(jint, JVM_GetMethodIxArgsSize(JNIEnv *env, jclass cls, int method_index)) |
2392 | JVMWrapper("JVM_GetMethodIxArgsSize" ); |
2393 | Klass* k = java_lang_Class::as_Klass(JNIHandles::resolve_non_null(cls)); |
2394 | k = JvmtiThreadState::class_to_verify_considering_redefinition(k, thread); |
2395 | Method* method = InstanceKlass::cast(k)->methods()->at(method_index); |
2396 | return method->size_of_parameters(); |
2397 | JVM_END |
2398 | |
2399 | |
2400 | JVM_QUICK_ENTRY(jint, JVM_GetMethodIxMaxStack(JNIEnv *env, jclass cls, int method_index)) |
2401 | JVMWrapper("JVM_GetMethodIxMaxStack" ); |
2402 | Klass* k = java_lang_Class::as_Klass(JNIHandles::resolve_non_null(cls)); |
2403 | k = JvmtiThreadState::class_to_verify_considering_redefinition(k, thread); |
2404 | Method* method = InstanceKlass::cast(k)->methods()->at(method_index); |
2405 | return method->verifier_max_stack(); |
2406 | JVM_END |
2407 | |
2408 | |
2409 | JVM_QUICK_ENTRY(jboolean, JVM_IsConstructorIx(JNIEnv *env, jclass cls, int method_index)) |
2410 | JVMWrapper("JVM_IsConstructorIx" ); |
2411 | ResourceMark rm(THREAD); |
2412 | Klass* k = java_lang_Class::as_Klass(JNIHandles::resolve_non_null(cls)); |
2413 | k = JvmtiThreadState::class_to_verify_considering_redefinition(k, thread); |
2414 | Method* method = InstanceKlass::cast(k)->methods()->at(method_index); |
2415 | return method->name() == vmSymbols::object_initializer_name(); |
2416 | JVM_END |
2417 | |
2418 | |
2419 | JVM_QUICK_ENTRY(jboolean, JVM_IsVMGeneratedMethodIx(JNIEnv *env, jclass cls, int method_index)) |
2420 | JVMWrapper("JVM_IsVMGeneratedMethodIx" ); |
2421 | ResourceMark rm(THREAD); |
2422 | Klass* k = java_lang_Class::as_Klass(JNIHandles::resolve_non_null(cls)); |
2423 | k = JvmtiThreadState::class_to_verify_considering_redefinition(k, thread); |
2424 | Method* method = InstanceKlass::cast(k)->methods()->at(method_index); |
2425 | return method->is_overpass(); |
2426 | JVM_END |
2427 | |
2428 | JVM_ENTRY(const char*, JVM_GetMethodIxNameUTF(JNIEnv *env, jclass cls, jint method_index)) |
2429 | JVMWrapper("JVM_GetMethodIxIxUTF" ); |
2430 | Klass* k = java_lang_Class::as_Klass(JNIHandles::resolve_non_null(cls)); |
2431 | k = JvmtiThreadState::class_to_verify_considering_redefinition(k, thread); |
2432 | Method* method = InstanceKlass::cast(k)->methods()->at(method_index); |
2433 | return method->name()->as_utf8(); |
2434 | JVM_END |
2435 | |
2436 | |
2437 | JVM_ENTRY(const char*, JVM_GetMethodIxSignatureUTF(JNIEnv *env, jclass cls, jint method_index)) |
2438 | JVMWrapper("JVM_GetMethodIxSignatureUTF" ); |
2439 | Klass* k = java_lang_Class::as_Klass(JNIHandles::resolve_non_null(cls)); |
2440 | k = JvmtiThreadState::class_to_verify_considering_redefinition(k, thread); |
2441 | Method* method = InstanceKlass::cast(k)->methods()->at(method_index); |
2442 | return method->signature()->as_utf8(); |
2443 | JVM_END |
2444 | |
2445 | /** |
2446 | * All of these JVM_GetCP-xxx methods are used by the old verifier to |
2447 | * read entries in the constant pool. Since the old verifier always |
2448 | * works on a copy of the code, it will not see any rewriting that |
2449 | * may possibly occur in the middle of verification. So it is important |
2450 | * that nothing it calls tries to use the cpCache instead of the raw |
2451 | * constant pool, so we must use cp->uncached_x methods when appropriate. |
2452 | */ |
2453 | JVM_ENTRY(const char*, JVM_GetCPFieldNameUTF(JNIEnv *env, jclass cls, jint cp_index)) |
2454 | JVMWrapper("JVM_GetCPFieldNameUTF" ); |
2455 | Klass* k = java_lang_Class::as_Klass(JNIHandles::resolve_non_null(cls)); |
2456 | k = JvmtiThreadState::class_to_verify_considering_redefinition(k, thread); |
2457 | ConstantPool* cp = InstanceKlass::cast(k)->constants(); |
2458 | switch (cp->tag_at(cp_index).value()) { |
2459 | case JVM_CONSTANT_Fieldref: |
2460 | return cp->uncached_name_ref_at(cp_index)->as_utf8(); |
2461 | default: |
2462 | fatal("JVM_GetCPFieldNameUTF: illegal constant" ); |
2463 | } |
2464 | ShouldNotReachHere(); |
2465 | return NULL; |
2466 | JVM_END |
2467 | |
2468 | |
2469 | JVM_ENTRY(const char*, JVM_GetCPMethodNameUTF(JNIEnv *env, jclass cls, jint cp_index)) |
2470 | JVMWrapper("JVM_GetCPMethodNameUTF" ); |
2471 | Klass* k = java_lang_Class::as_Klass(JNIHandles::resolve_non_null(cls)); |
2472 | k = JvmtiThreadState::class_to_verify_considering_redefinition(k, thread); |
2473 | ConstantPool* cp = InstanceKlass::cast(k)->constants(); |
2474 | switch (cp->tag_at(cp_index).value()) { |
2475 | case JVM_CONSTANT_InterfaceMethodref: |
2476 | case JVM_CONSTANT_Methodref: |
2477 | return cp->uncached_name_ref_at(cp_index)->as_utf8(); |
2478 | default: |
2479 | fatal("JVM_GetCPMethodNameUTF: illegal constant" ); |
2480 | } |
2481 | ShouldNotReachHere(); |
2482 | return NULL; |
2483 | JVM_END |
2484 | |
2485 | |
2486 | JVM_ENTRY(const char*, JVM_GetCPMethodSignatureUTF(JNIEnv *env, jclass cls, jint cp_index)) |
2487 | JVMWrapper("JVM_GetCPMethodSignatureUTF" ); |
2488 | Klass* k = java_lang_Class::as_Klass(JNIHandles::resolve_non_null(cls)); |
2489 | k = JvmtiThreadState::class_to_verify_considering_redefinition(k, thread); |
2490 | ConstantPool* cp = InstanceKlass::cast(k)->constants(); |
2491 | switch (cp->tag_at(cp_index).value()) { |
2492 | case JVM_CONSTANT_InterfaceMethodref: |
2493 | case JVM_CONSTANT_Methodref: |
2494 | return cp->uncached_signature_ref_at(cp_index)->as_utf8(); |
2495 | default: |
2496 | fatal("JVM_GetCPMethodSignatureUTF: illegal constant" ); |
2497 | } |
2498 | ShouldNotReachHere(); |
2499 | return NULL; |
2500 | JVM_END |
2501 | |
2502 | |
2503 | JVM_ENTRY(const char*, JVM_GetCPFieldSignatureUTF(JNIEnv *env, jclass cls, jint cp_index)) |
2504 | JVMWrapper("JVM_GetCPFieldSignatureUTF" ); |
2505 | Klass* k = java_lang_Class::as_Klass(JNIHandles::resolve_non_null(cls)); |
2506 | k = JvmtiThreadState::class_to_verify_considering_redefinition(k, thread); |
2507 | ConstantPool* cp = InstanceKlass::cast(k)->constants(); |
2508 | switch (cp->tag_at(cp_index).value()) { |
2509 | case JVM_CONSTANT_Fieldref: |
2510 | return cp->uncached_signature_ref_at(cp_index)->as_utf8(); |
2511 | default: |
2512 | fatal("JVM_GetCPFieldSignatureUTF: illegal constant" ); |
2513 | } |
2514 | ShouldNotReachHere(); |
2515 | return NULL; |
2516 | JVM_END |
2517 | |
2518 | |
2519 | JVM_ENTRY(const char*, JVM_GetCPClassNameUTF(JNIEnv *env, jclass cls, jint cp_index)) |
2520 | JVMWrapper("JVM_GetCPClassNameUTF" ); |
2521 | Klass* k = java_lang_Class::as_Klass(JNIHandles::resolve_non_null(cls)); |
2522 | k = JvmtiThreadState::class_to_verify_considering_redefinition(k, thread); |
2523 | ConstantPool* cp = InstanceKlass::cast(k)->constants(); |
2524 | Symbol* classname = cp->klass_name_at(cp_index); |
2525 | return classname->as_utf8(); |
2526 | JVM_END |
2527 | |
2528 | |
2529 | JVM_ENTRY(const char*, JVM_GetCPFieldClassNameUTF(JNIEnv *env, jclass cls, jint cp_index)) |
2530 | JVMWrapper("JVM_GetCPFieldClassNameUTF" ); |
2531 | Klass* k = java_lang_Class::as_Klass(JNIHandles::resolve_non_null(cls)); |
2532 | k = JvmtiThreadState::class_to_verify_considering_redefinition(k, thread); |
2533 | ConstantPool* cp = InstanceKlass::cast(k)->constants(); |
2534 | switch (cp->tag_at(cp_index).value()) { |
2535 | case JVM_CONSTANT_Fieldref: { |
2536 | int class_index = cp->uncached_klass_ref_index_at(cp_index); |
2537 | Symbol* classname = cp->klass_name_at(class_index); |
2538 | return classname->as_utf8(); |
2539 | } |
2540 | default: |
2541 | fatal("JVM_GetCPFieldClassNameUTF: illegal constant" ); |
2542 | } |
2543 | ShouldNotReachHere(); |
2544 | return NULL; |
2545 | JVM_END |
2546 | |
2547 | |
2548 | JVM_ENTRY(const char*, JVM_GetCPMethodClassNameUTF(JNIEnv *env, jclass cls, jint cp_index)) |
2549 | JVMWrapper("JVM_GetCPMethodClassNameUTF" ); |
2550 | Klass* k = java_lang_Class::as_Klass(JNIHandles::resolve_non_null(cls)); |
2551 | k = JvmtiThreadState::class_to_verify_considering_redefinition(k, thread); |
2552 | ConstantPool* cp = InstanceKlass::cast(k)->constants(); |
2553 | switch (cp->tag_at(cp_index).value()) { |
2554 | case JVM_CONSTANT_Methodref: |
2555 | case JVM_CONSTANT_InterfaceMethodref: { |
2556 | int class_index = cp->uncached_klass_ref_index_at(cp_index); |
2557 | Symbol* classname = cp->klass_name_at(class_index); |
2558 | return classname->as_utf8(); |
2559 | } |
2560 | default: |
2561 | fatal("JVM_GetCPMethodClassNameUTF: illegal constant" ); |
2562 | } |
2563 | ShouldNotReachHere(); |
2564 | return NULL; |
2565 | JVM_END |
2566 | |
2567 | |
2568 | JVM_ENTRY(jint, JVM_GetCPFieldModifiers(JNIEnv *env, jclass cls, int cp_index, jclass called_cls)) |
2569 | JVMWrapper("JVM_GetCPFieldModifiers" ); |
2570 | Klass* k = java_lang_Class::as_Klass(JNIHandles::resolve_non_null(cls)); |
2571 | Klass* k_called = java_lang_Class::as_Klass(JNIHandles::resolve_non_null(called_cls)); |
2572 | k = JvmtiThreadState::class_to_verify_considering_redefinition(k, thread); |
2573 | k_called = JvmtiThreadState::class_to_verify_considering_redefinition(k_called, thread); |
2574 | ConstantPool* cp = InstanceKlass::cast(k)->constants(); |
2575 | ConstantPool* cp_called = InstanceKlass::cast(k_called)->constants(); |
2576 | switch (cp->tag_at(cp_index).value()) { |
2577 | case JVM_CONSTANT_Fieldref: { |
2578 | Symbol* name = cp->uncached_name_ref_at(cp_index); |
2579 | Symbol* signature = cp->uncached_signature_ref_at(cp_index); |
2580 | InstanceKlass* ik = InstanceKlass::cast(k_called); |
2581 | for (JavaFieldStream fs(ik); !fs.done(); fs.next()) { |
2582 | if (fs.name() == name && fs.signature() == signature) { |
2583 | return fs.access_flags().as_short() & JVM_RECOGNIZED_FIELD_MODIFIERS; |
2584 | } |
2585 | } |
2586 | return -1; |
2587 | } |
2588 | default: |
2589 | fatal("JVM_GetCPFieldModifiers: illegal constant" ); |
2590 | } |
2591 | ShouldNotReachHere(); |
2592 | return 0; |
2593 | JVM_END |
2594 | |
2595 | |
2596 | JVM_QUICK_ENTRY(jint, JVM_GetCPMethodModifiers(JNIEnv *env, jclass cls, int cp_index, jclass called_cls)) |
2597 | JVMWrapper("JVM_GetCPMethodModifiers" ); |
2598 | Klass* k = java_lang_Class::as_Klass(JNIHandles::resolve_non_null(cls)); |
2599 | Klass* k_called = java_lang_Class::as_Klass(JNIHandles::resolve_non_null(called_cls)); |
2600 | k = JvmtiThreadState::class_to_verify_considering_redefinition(k, thread); |
2601 | k_called = JvmtiThreadState::class_to_verify_considering_redefinition(k_called, thread); |
2602 | ConstantPool* cp = InstanceKlass::cast(k)->constants(); |
2603 | switch (cp->tag_at(cp_index).value()) { |
2604 | case JVM_CONSTANT_Methodref: |
2605 | case JVM_CONSTANT_InterfaceMethodref: { |
2606 | Symbol* name = cp->uncached_name_ref_at(cp_index); |
2607 | Symbol* signature = cp->uncached_signature_ref_at(cp_index); |
2608 | Array<Method*>* methods = InstanceKlass::cast(k_called)->methods(); |
2609 | int methods_count = methods->length(); |
2610 | for (int i = 0; i < methods_count; i++) { |
2611 | Method* method = methods->at(i); |
2612 | if (method->name() == name && method->signature() == signature) { |
2613 | return method->access_flags().as_int() & JVM_RECOGNIZED_METHOD_MODIFIERS; |
2614 | } |
2615 | } |
2616 | return -1; |
2617 | } |
2618 | default: |
2619 | fatal("JVM_GetCPMethodModifiers: illegal constant" ); |
2620 | } |
2621 | ShouldNotReachHere(); |
2622 | return 0; |
2623 | JVM_END |
2624 | |
2625 | |
2626 | // Misc ////////////////////////////////////////////////////////////////////////////////////////////// |
2627 | |
2628 | JVM_LEAF(void, JVM_ReleaseUTF(const char *utf)) |
2629 | // So long as UTF8::convert_to_utf8 returns resource strings, we don't have to do anything |
2630 | JVM_END |
2631 | |
2632 | |
2633 | JVM_ENTRY(jboolean, JVM_IsSameClassPackage(JNIEnv *env, jclass class1, jclass class2)) |
2634 | JVMWrapper("JVM_IsSameClassPackage" ); |
2635 | oop class1_mirror = JNIHandles::resolve_non_null(class1); |
2636 | oop class2_mirror = JNIHandles::resolve_non_null(class2); |
2637 | Klass* klass1 = java_lang_Class::as_Klass(class1_mirror); |
2638 | Klass* klass2 = java_lang_Class::as_Klass(class2_mirror); |
2639 | return (jboolean) Reflection::is_same_class_package(klass1, klass2); |
2640 | JVM_END |
2641 | |
2642 | // Printing support ////////////////////////////////////////////////// |
2643 | extern "C" { |
2644 | |
2645 | ATTRIBUTE_PRINTF(3, 0) |
2646 | int jio_vsnprintf(char *str, size_t count, const char *fmt, va_list args) { |
2647 | // Reject count values that are negative signed values converted to |
2648 | // unsigned; see bug 4399518, 4417214 |
2649 | if ((intptr_t)count <= 0) return -1; |
2650 | |
2651 | int result = os::vsnprintf(str, count, fmt, args); |
2652 | if (result > 0 && (size_t)result >= count) { |
2653 | result = -1; |
2654 | } |
2655 | |
2656 | return result; |
2657 | } |
2658 | |
2659 | ATTRIBUTE_PRINTF(3, 4) |
2660 | int jio_snprintf(char *str, size_t count, const char *fmt, ...) { |
2661 | va_list args; |
2662 | int len; |
2663 | va_start(args, fmt); |
2664 | len = jio_vsnprintf(str, count, fmt, args); |
2665 | va_end(args); |
2666 | return len; |
2667 | } |
2668 | |
2669 | ATTRIBUTE_PRINTF(2, 3) |
2670 | int jio_fprintf(FILE* f, const char *fmt, ...) { |
2671 | int len; |
2672 | va_list args; |
2673 | va_start(args, fmt); |
2674 | len = jio_vfprintf(f, fmt, args); |
2675 | va_end(args); |
2676 | return len; |
2677 | } |
2678 | |
2679 | ATTRIBUTE_PRINTF(2, 0) |
2680 | int jio_vfprintf(FILE* f, const char *fmt, va_list args) { |
2681 | if (Arguments::vfprintf_hook() != NULL) { |
2682 | return Arguments::vfprintf_hook()(f, fmt, args); |
2683 | } else { |
2684 | return vfprintf(f, fmt, args); |
2685 | } |
2686 | } |
2687 | |
2688 | ATTRIBUTE_PRINTF(1, 2) |
2689 | JNIEXPORT int jio_printf(const char *fmt, ...) { |
2690 | int len; |
2691 | va_list args; |
2692 | va_start(args, fmt); |
2693 | len = jio_vfprintf(defaultStream::output_stream(), fmt, args); |
2694 | va_end(args); |
2695 | return len; |
2696 | } |
2697 | |
2698 | // HotSpot specific jio method |
2699 | void jio_print(const char* s, size_t len) { |
2700 | // Try to make this function as atomic as possible. |
2701 | if (Arguments::vfprintf_hook() != NULL) { |
2702 | jio_fprintf(defaultStream::output_stream(), "%.*s" , (int)len, s); |
2703 | } else { |
2704 | // Make an unused local variable to avoid warning from gcc 4.x compiler. |
2705 | size_t count = ::write(defaultStream::output_fd(), s, (int)len); |
2706 | } |
2707 | } |
2708 | |
2709 | } // Extern C |
2710 | |
2711 | // java.lang.Thread ////////////////////////////////////////////////////////////////////////////// |
2712 | |
2713 | // In most of the JVM thread support functions we need to access the |
2714 | // thread through a ThreadsListHandle to prevent it from exiting and |
2715 | // being reclaimed while we try to operate on it. The exceptions to this |
2716 | // rule are when operating on the current thread, or if the monitor of |
2717 | // the target java.lang.Thread is locked at the Java level - in both |
2718 | // cases the target cannot exit. |
2719 | |
2720 | static void thread_entry(JavaThread* thread, TRAPS) { |
2721 | HandleMark hm(THREAD); |
2722 | Handle obj(THREAD, thread->threadObj()); |
2723 | JavaValue result(T_VOID); |
2724 | JavaCalls::call_virtual(&result, |
2725 | obj, |
2726 | SystemDictionary::Thread_klass(), |
2727 | vmSymbols::run_method_name(), |
2728 | vmSymbols::void_method_signature(), |
2729 | THREAD); |
2730 | } |
2731 | |
2732 | |
2733 | JVM_ENTRY(void, JVM_StartThread(JNIEnv* env, jobject jthread)) |
2734 | JVMWrapper("JVM_StartThread" ); |
2735 | JavaThread *native_thread = NULL; |
2736 | |
2737 | // We cannot hold the Threads_lock when we throw an exception, |
2738 | // due to rank ordering issues. Example: we might need to grab the |
2739 | // Heap_lock while we construct the exception. |
2740 | bool throw_illegal_thread_state = false; |
2741 | |
2742 | // We must release the Threads_lock before we can post a jvmti event |
2743 | // in Thread::start. |
2744 | { |
2745 | // Ensure that the C++ Thread and OSThread structures aren't freed before |
2746 | // we operate. |
2747 | MutexLocker mu(Threads_lock); |
2748 | |
2749 | // Since JDK 5 the java.lang.Thread threadStatus is used to prevent |
2750 | // re-starting an already started thread, so we should usually find |
2751 | // that the JavaThread is null. However for a JNI attached thread |
2752 | // there is a small window between the Thread object being created |
2753 | // (with its JavaThread set) and the update to its threadStatus, so we |
2754 | // have to check for this |
2755 | if (java_lang_Thread::thread(JNIHandles::resolve_non_null(jthread)) != NULL) { |
2756 | throw_illegal_thread_state = true; |
2757 | } else { |
2758 | // We could also check the stillborn flag to see if this thread was already stopped, but |
2759 | // for historical reasons we let the thread detect that itself when it starts running |
2760 | |
2761 | jlong size = |
2762 | java_lang_Thread::stackSize(JNIHandles::resolve_non_null(jthread)); |
2763 | // Allocate the C++ Thread structure and create the native thread. The |
2764 | // stack size retrieved from java is 64-bit signed, but the constructor takes |
2765 | // size_t (an unsigned type), which may be 32 or 64-bit depending on the platform. |
2766 | // - Avoid truncating on 32-bit platforms if size is greater than UINT_MAX. |
2767 | // - Avoid passing negative values which would result in really large stacks. |
2768 | NOT_LP64(if (size > SIZE_MAX) size = SIZE_MAX;) |
2769 | size_t sz = size > 0 ? (size_t) size : 0; |
2770 | native_thread = new JavaThread(&thread_entry, sz); |
2771 | |
2772 | // At this point it may be possible that no osthread was created for the |
2773 | // JavaThread due to lack of memory. Check for this situation and throw |
2774 | // an exception if necessary. Eventually we may want to change this so |
2775 | // that we only grab the lock if the thread was created successfully - |
2776 | // then we can also do this check and throw the exception in the |
2777 | // JavaThread constructor. |
2778 | if (native_thread->osthread() != NULL) { |
2779 | // Note: the current thread is not being used within "prepare". |
2780 | native_thread->prepare(jthread); |
2781 | } |
2782 | } |
2783 | } |
2784 | |
2785 | if (throw_illegal_thread_state) { |
2786 | THROW(vmSymbols::java_lang_IllegalThreadStateException()); |
2787 | } |
2788 | |
2789 | assert(native_thread != NULL, "Starting null thread?" ); |
2790 | |
2791 | if (native_thread->osthread() == NULL) { |
2792 | // No one should hold a reference to the 'native_thread'. |
2793 | native_thread->smr_delete(); |
2794 | if (JvmtiExport::should_post_resource_exhausted()) { |
2795 | JvmtiExport::post_resource_exhausted( |
2796 | JVMTI_RESOURCE_EXHAUSTED_OOM_ERROR | JVMTI_RESOURCE_EXHAUSTED_THREADS, |
2797 | os::native_thread_creation_failed_msg()); |
2798 | } |
2799 | THROW_MSG(vmSymbols::java_lang_OutOfMemoryError(), |
2800 | os::native_thread_creation_failed_msg()); |
2801 | } |
2802 | |
2803 | Thread::start(native_thread); |
2804 | |
2805 | JVM_END |
2806 | |
2807 | |
2808 | // JVM_Stop is implemented using a VM_Operation, so threads are forced to safepoints |
2809 | // before the quasi-asynchronous exception is delivered. This is a little obtrusive, |
2810 | // but is thought to be reliable and simple. In the case, where the receiver is the |
2811 | // same thread as the sender, no VM_Operation is needed. |
2812 | JVM_ENTRY(void, JVM_StopThread(JNIEnv* env, jobject jthread, jobject throwable)) |
2813 | JVMWrapper("JVM_StopThread" ); |
2814 | |
2815 | // A nested ThreadsListHandle will grab the Threads_lock so create |
2816 | // tlh before we resolve throwable. |
2817 | ThreadsListHandle tlh(thread); |
2818 | oop java_throwable = JNIHandles::resolve(throwable); |
2819 | if (java_throwable == NULL) { |
2820 | THROW(vmSymbols::java_lang_NullPointerException()); |
2821 | } |
2822 | oop java_thread = NULL; |
2823 | JavaThread* receiver = NULL; |
2824 | bool is_alive = tlh.cv_internal_thread_to_JavaThread(jthread, &receiver, &java_thread); |
2825 | Events::log_exception(thread, |
2826 | "JVM_StopThread thread JavaThread " INTPTR_FORMAT " as oop " INTPTR_FORMAT " [exception " INTPTR_FORMAT "]" , |
2827 | p2i(receiver), p2i((address)java_thread), p2i(throwable)); |
2828 | |
2829 | if (is_alive) { |
2830 | // jthread refers to a live JavaThread. |
2831 | if (thread == receiver) { |
2832 | // Exception is getting thrown at self so no VM_Operation needed. |
2833 | THROW_OOP(java_throwable); |
2834 | } else { |
2835 | // Use a VM_Operation to throw the exception. |
2836 | Thread::send_async_exception(java_thread, java_throwable); |
2837 | } |
2838 | } else { |
2839 | // Either: |
2840 | // - target thread has not been started before being stopped, or |
2841 | // - target thread already terminated |
2842 | // We could read the threadStatus to determine which case it is |
2843 | // but that is overkill as it doesn't matter. We must set the |
2844 | // stillborn flag for the first case, and if the thread has already |
2845 | // exited setting this flag has no effect. |
2846 | java_lang_Thread::set_stillborn(java_thread); |
2847 | } |
2848 | JVM_END |
2849 | |
2850 | |
2851 | JVM_ENTRY(jboolean, JVM_IsThreadAlive(JNIEnv* env, jobject jthread)) |
2852 | JVMWrapper("JVM_IsThreadAlive" ); |
2853 | |
2854 | oop thread_oop = JNIHandles::resolve_non_null(jthread); |
2855 | return java_lang_Thread::is_alive(thread_oop); |
2856 | JVM_END |
2857 | |
2858 | |
2859 | JVM_ENTRY(void, JVM_SuspendThread(JNIEnv* env, jobject jthread)) |
2860 | JVMWrapper("JVM_SuspendThread" ); |
2861 | |
2862 | ThreadsListHandle tlh(thread); |
2863 | JavaThread* receiver = NULL; |
2864 | bool is_alive = tlh.cv_internal_thread_to_JavaThread(jthread, &receiver, NULL); |
2865 | if (is_alive) { |
2866 | // jthread refers to a live JavaThread. |
2867 | { |
2868 | MutexLocker ml(receiver->SR_lock(), Mutex::_no_safepoint_check_flag); |
2869 | if (receiver->is_external_suspend()) { |
2870 | // Don't allow nested external suspend requests. We can't return |
2871 | // an error from this interface so just ignore the problem. |
2872 | return; |
2873 | } |
2874 | if (receiver->is_exiting()) { // thread is in the process of exiting |
2875 | return; |
2876 | } |
2877 | receiver->set_external_suspend(); |
2878 | } |
2879 | |
2880 | // java_suspend() will catch threads in the process of exiting |
2881 | // and will ignore them. |
2882 | receiver->java_suspend(); |
2883 | |
2884 | // It would be nice to have the following assertion in all the |
2885 | // time, but it is possible for a racing resume request to have |
2886 | // resumed this thread right after we suspended it. Temporarily |
2887 | // enable this assertion if you are chasing a different kind of |
2888 | // bug. |
2889 | // |
2890 | // assert(java_lang_Thread::thread(receiver->threadObj()) == NULL || |
2891 | // receiver->is_being_ext_suspended(), "thread is not suspended"); |
2892 | } |
2893 | JVM_END |
2894 | |
2895 | |
2896 | JVM_ENTRY(void, JVM_ResumeThread(JNIEnv* env, jobject jthread)) |
2897 | JVMWrapper("JVM_ResumeThread" ); |
2898 | |
2899 | ThreadsListHandle tlh(thread); |
2900 | JavaThread* receiver = NULL; |
2901 | bool is_alive = tlh.cv_internal_thread_to_JavaThread(jthread, &receiver, NULL); |
2902 | if (is_alive) { |
2903 | // jthread refers to a live JavaThread. |
2904 | |
2905 | // This is the original comment for this Threads_lock grab: |
2906 | // We need to *always* get the threads lock here, since this operation cannot be allowed during |
2907 | // a safepoint. The safepoint code relies on suspending a thread to examine its state. If other |
2908 | // threads randomly resumes threads, then a thread might not be suspended when the safepoint code |
2909 | // looks at it. |
2910 | // |
2911 | // The above comment dates back to when we had both internal and |
2912 | // external suspend APIs that shared a common underlying mechanism. |
2913 | // External suspend is now entirely cooperative and doesn't share |
2914 | // anything with internal suspend. That said, there are some |
2915 | // assumptions in the VM that an external resume grabs the |
2916 | // Threads_lock. We can't drop the Threads_lock grab here until we |
2917 | // resolve the assumptions that exist elsewhere. |
2918 | // |
2919 | MutexLocker ml(Threads_lock); |
2920 | receiver->java_resume(); |
2921 | } |
2922 | JVM_END |
2923 | |
2924 | |
2925 | JVM_ENTRY(void, JVM_SetThreadPriority(JNIEnv* env, jobject jthread, jint prio)) |
2926 | JVMWrapper("JVM_SetThreadPriority" ); |
2927 | |
2928 | ThreadsListHandle tlh(thread); |
2929 | oop java_thread = NULL; |
2930 | JavaThread* receiver = NULL; |
2931 | bool is_alive = tlh.cv_internal_thread_to_JavaThread(jthread, &receiver, &java_thread); |
2932 | java_lang_Thread::set_priority(java_thread, (ThreadPriority)prio); |
2933 | |
2934 | if (is_alive) { |
2935 | // jthread refers to a live JavaThread. |
2936 | Thread::set_priority(receiver, (ThreadPriority)prio); |
2937 | } |
2938 | // Implied else: If the JavaThread hasn't started yet, then the |
2939 | // priority set in the java.lang.Thread object above will be pushed |
2940 | // down when it does start. |
2941 | JVM_END |
2942 | |
2943 | |
2944 | JVM_ENTRY(void, JVM_Yield(JNIEnv *env, jclass threadClass)) |
2945 | JVMWrapper("JVM_Yield" ); |
2946 | if (os::dont_yield()) return; |
2947 | HOTSPOT_THREAD_YIELD(); |
2948 | os::naked_yield(); |
2949 | JVM_END |
2950 | |
2951 | static void post_thread_sleep_event(EventThreadSleep* event, jlong millis) { |
2952 | assert(event != NULL, "invariant" ); |
2953 | assert(event->should_commit(), "invariant" ); |
2954 | event->set_time(millis); |
2955 | event->commit(); |
2956 | } |
2957 | |
2958 | JVM_ENTRY(void, JVM_Sleep(JNIEnv* env, jclass threadClass, jlong millis)) |
2959 | JVMWrapper("JVM_Sleep" ); |
2960 | |
2961 | if (millis < 0) { |
2962 | THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(), "timeout value is negative" ); |
2963 | } |
2964 | |
2965 | if (Thread::is_interrupted (THREAD, true) && !HAS_PENDING_EXCEPTION) { |
2966 | THROW_MSG(vmSymbols::java_lang_InterruptedException(), "sleep interrupted" ); |
2967 | } |
2968 | |
2969 | // Save current thread state and restore it at the end of this block. |
2970 | // And set new thread state to SLEEPING. |
2971 | JavaThreadSleepState jtss(thread); |
2972 | |
2973 | HOTSPOT_THREAD_SLEEP_BEGIN(millis); |
2974 | EventThreadSleep event; |
2975 | |
2976 | if (millis == 0) { |
2977 | os::naked_yield(); |
2978 | } else { |
2979 | ThreadState old_state = thread->osthread()->get_state(); |
2980 | thread->osthread()->set_state(SLEEPING); |
2981 | if (os::sleep(thread, millis, true) == OS_INTRPT) { |
2982 | // An asynchronous exception (e.g., ThreadDeathException) could have been thrown on |
2983 | // us while we were sleeping. We do not overwrite those. |
2984 | if (!HAS_PENDING_EXCEPTION) { |
2985 | if (event.should_commit()) { |
2986 | post_thread_sleep_event(&event, millis); |
2987 | } |
2988 | HOTSPOT_THREAD_SLEEP_END(1); |
2989 | |
2990 | // TODO-FIXME: THROW_MSG returns which means we will not call set_state() |
2991 | // to properly restore the thread state. That's likely wrong. |
2992 | THROW_MSG(vmSymbols::java_lang_InterruptedException(), "sleep interrupted" ); |
2993 | } |
2994 | } |
2995 | thread->osthread()->set_state(old_state); |
2996 | } |
2997 | if (event.should_commit()) { |
2998 | post_thread_sleep_event(&event, millis); |
2999 | } |
3000 | HOTSPOT_THREAD_SLEEP_END(0); |
3001 | JVM_END |
3002 | |
3003 | JVM_ENTRY(jobject, JVM_CurrentThread(JNIEnv* env, jclass threadClass)) |
3004 | JVMWrapper("JVM_CurrentThread" ); |
3005 | oop jthread = thread->threadObj(); |
3006 | assert (thread != NULL, "no current thread!" ); |
3007 | return JNIHandles::make_local(env, jthread); |
3008 | JVM_END |
3009 | |
3010 | class CountStackFramesTC : public ThreadClosure { |
3011 | int _count; |
3012 | bool _suspended; |
3013 | public: |
3014 | CountStackFramesTC() : _count(0), _suspended(false) {} |
3015 | virtual void do_thread(Thread* thread) { |
3016 | JavaThread* jt = (JavaThread*)thread; |
3017 | if (!jt->is_external_suspend()) { |
3018 | // To keep same behavior we fail this operation, |
3019 | // even if it would work perfectly. |
3020 | return; |
3021 | } |
3022 | _suspended = true; |
3023 | // Count all java activation, i.e., number of vframes. |
3024 | for (vframeStream vfst(jt); !vfst.at_end(); vfst.next()) { |
3025 | // Native frames are not counted. |
3026 | if (!vfst.method()->is_native()) _count++; |
3027 | } |
3028 | } |
3029 | int count() { return _count; } |
3030 | int suspended() { return _suspended; } |
3031 | }; |
3032 | |
3033 | JVM_ENTRY(jint, JVM_CountStackFrames(JNIEnv* env, jobject jthread)) |
3034 | JVMWrapper("JVM_CountStackFrames" ); |
3035 | |
3036 | ThreadsListHandle tlh(thread); |
3037 | JavaThread* receiver = NULL; |
3038 | bool is_alive = tlh.cv_internal_thread_to_JavaThread(jthread, &receiver, NULL); |
3039 | if (is_alive) { |
3040 | // jthread refers to a live JavaThread. |
3041 | CountStackFramesTC csf; |
3042 | Handshake::execute(&csf, receiver); |
3043 | if (!csf.suspended()) { |
3044 | THROW_MSG_0(vmSymbols::java_lang_IllegalThreadStateException(), |
3045 | "this thread is not suspended" ); |
3046 | } |
3047 | return csf.count(); |
3048 | } |
3049 | // Implied else: if JavaThread is not alive simply return a count of 0. |
3050 | return 0; |
3051 | JVM_END |
3052 | |
3053 | |
3054 | JVM_ENTRY(void, JVM_Interrupt(JNIEnv* env, jobject jthread)) |
3055 | JVMWrapper("JVM_Interrupt" ); |
3056 | |
3057 | ThreadsListHandle tlh(thread); |
3058 | JavaThread* receiver = NULL; |
3059 | bool is_alive = tlh.cv_internal_thread_to_JavaThread(jthread, &receiver, NULL); |
3060 | if (is_alive) { |
3061 | // jthread refers to a live JavaThread. |
3062 | Thread::interrupt(receiver); |
3063 | } |
3064 | JVM_END |
3065 | |
3066 | |
3067 | JVM_QUICK_ENTRY(jboolean, JVM_IsInterrupted(JNIEnv* env, jobject jthread, jboolean clear_interrupted)) |
3068 | JVMWrapper("JVM_IsInterrupted" ); |
3069 | |
3070 | ThreadsListHandle tlh(thread); |
3071 | JavaThread* receiver = NULL; |
3072 | bool is_alive = tlh.cv_internal_thread_to_JavaThread(jthread, &receiver, NULL); |
3073 | if (is_alive) { |
3074 | // jthread refers to a live JavaThread. |
3075 | return (jboolean) Thread::is_interrupted(receiver, clear_interrupted != 0); |
3076 | } else { |
3077 | return JNI_FALSE; |
3078 | } |
3079 | JVM_END |
3080 | |
3081 | |
3082 | // Return true iff the current thread has locked the object passed in |
3083 | |
3084 | JVM_ENTRY(jboolean, JVM_HoldsLock(JNIEnv* env, jclass threadClass, jobject obj)) |
3085 | JVMWrapper("JVM_HoldsLock" ); |
3086 | assert(THREAD->is_Java_thread(), "sanity check" ); |
3087 | if (obj == NULL) { |
3088 | THROW_(vmSymbols::java_lang_NullPointerException(), JNI_FALSE); |
3089 | } |
3090 | Handle h_obj(THREAD, JNIHandles::resolve(obj)); |
3091 | return ObjectSynchronizer::current_thread_holds_lock((JavaThread*)THREAD, h_obj); |
3092 | JVM_END |
3093 | |
3094 | |
3095 | JVM_ENTRY(void, JVM_DumpAllStacks(JNIEnv* env, jclass)) |
3096 | JVMWrapper("JVM_DumpAllStacks" ); |
3097 | VM_PrintThreads op; |
3098 | VMThread::execute(&op); |
3099 | if (JvmtiExport::should_post_data_dump()) { |
3100 | JvmtiExport::post_data_dump(); |
3101 | } |
3102 | JVM_END |
3103 | |
3104 | JVM_ENTRY(void, JVM_SetNativeThreadName(JNIEnv* env, jobject jthread, jstring name)) |
3105 | JVMWrapper("JVM_SetNativeThreadName" ); |
3106 | |
3107 | // We don't use a ThreadsListHandle here because the current thread |
3108 | // must be alive. |
3109 | oop java_thread = JNIHandles::resolve_non_null(jthread); |
3110 | JavaThread* thr = java_lang_Thread::thread(java_thread); |
3111 | if (thread == thr && !thr->has_attached_via_jni()) { |
3112 | // Thread naming is only supported for the current thread and |
3113 | // we don't set the name of an attached thread to avoid stepping |
3114 | // on other programs. |
3115 | ResourceMark rm(thread); |
3116 | const char *thread_name = java_lang_String::as_utf8_string(JNIHandles::resolve_non_null(name)); |
3117 | os::set_native_thread_name(thread_name); |
3118 | } |
3119 | JVM_END |
3120 | |
3121 | // java.lang.SecurityManager /////////////////////////////////////////////////////////////////////// |
3122 | |
3123 | JVM_ENTRY(jobjectArray, JVM_GetClassContext(JNIEnv *env)) |
3124 | JVMWrapper("JVM_GetClassContext" ); |
3125 | ResourceMark rm(THREAD); |
3126 | JvmtiVMObjectAllocEventCollector oam; |
3127 | vframeStream vfst(thread); |
3128 | |
3129 | if (SystemDictionary::reflect_CallerSensitive_klass() != NULL) { |
3130 | // This must only be called from SecurityManager.getClassContext |
3131 | Method* m = vfst.method(); |
3132 | if (!(m->method_holder() == SystemDictionary::SecurityManager_klass() && |
3133 | m->name() == vmSymbols::getClassContext_name() && |
3134 | m->signature() == vmSymbols::void_class_array_signature())) { |
3135 | THROW_MSG_NULL(vmSymbols::java_lang_InternalError(), "JVM_GetClassContext must only be called from SecurityManager.getClassContext" ); |
3136 | } |
3137 | } |
3138 | |
3139 | // Collect method holders |
3140 | GrowableArray<Klass*>* klass_array = new GrowableArray<Klass*>(); |
3141 | for (; !vfst.at_end(); vfst.security_next()) { |
3142 | Method* m = vfst.method(); |
3143 | // Native frames are not returned |
3144 | if (!m->is_ignored_by_security_stack_walk() && !m->is_native()) { |
3145 | Klass* holder = m->method_holder(); |
3146 | assert(holder->is_klass(), "just checking" ); |
3147 | klass_array->append(holder); |
3148 | } |
3149 | } |
3150 | |
3151 | // Create result array of type [Ljava/lang/Class; |
3152 | objArrayOop result = oopFactory::new_objArray(SystemDictionary::Class_klass(), klass_array->length(), CHECK_NULL); |
3153 | // Fill in mirrors corresponding to method holders |
3154 | for (int i = 0; i < klass_array->length(); i++) { |
3155 | result->obj_at_put(i, klass_array->at(i)->java_mirror()); |
3156 | } |
3157 | |
3158 | return (jobjectArray) JNIHandles::make_local(env, result); |
3159 | JVM_END |
3160 | |
3161 | |
3162 | // java.lang.Package //////////////////////////////////////////////////////////////// |
3163 | |
3164 | |
3165 | JVM_ENTRY(jstring, JVM_GetSystemPackage(JNIEnv *env, jstring name)) |
3166 | JVMWrapper("JVM_GetSystemPackage" ); |
3167 | ResourceMark rm(THREAD); |
3168 | JvmtiVMObjectAllocEventCollector oam; |
3169 | char* str = java_lang_String::as_utf8_string(JNIHandles::resolve_non_null(name)); |
3170 | oop result = ClassLoader::get_system_package(str, CHECK_NULL); |
3171 | return (jstring) JNIHandles::make_local(result); |
3172 | JVM_END |
3173 | |
3174 | |
3175 | JVM_ENTRY(jobjectArray, JVM_GetSystemPackages(JNIEnv *env)) |
3176 | JVMWrapper("JVM_GetSystemPackages" ); |
3177 | JvmtiVMObjectAllocEventCollector oam; |
3178 | objArrayOop result = ClassLoader::get_system_packages(CHECK_NULL); |
3179 | return (jobjectArray) JNIHandles::make_local(result); |
3180 | JVM_END |
3181 | |
3182 | |
3183 | // java.lang.ref.Reference /////////////////////////////////////////////////////////////// |
3184 | |
3185 | |
3186 | JVM_ENTRY(jobject, JVM_GetAndClearReferencePendingList(JNIEnv* env)) |
3187 | JVMWrapper("JVM_GetAndClearReferencePendingList" ); |
3188 | |
3189 | MonitorLocker ml(Heap_lock); |
3190 | oop ref = Universe::reference_pending_list(); |
3191 | if (ref != NULL) { |
3192 | Universe::set_reference_pending_list(NULL); |
3193 | } |
3194 | return JNIHandles::make_local(env, ref); |
3195 | JVM_END |
3196 | |
3197 | JVM_ENTRY(jboolean, JVM_HasReferencePendingList(JNIEnv* env)) |
3198 | JVMWrapper("JVM_HasReferencePendingList" ); |
3199 | MonitorLocker ml(Heap_lock); |
3200 | return Universe::has_reference_pending_list(); |
3201 | JVM_END |
3202 | |
3203 | JVM_ENTRY(void, JVM_WaitForReferencePendingList(JNIEnv* env)) |
3204 | JVMWrapper("JVM_WaitForReferencePendingList" ); |
3205 | MonitorLocker ml(Heap_lock); |
3206 | while (!Universe::has_reference_pending_list()) { |
3207 | ml.wait(); |
3208 | } |
3209 | JVM_END |
3210 | |
3211 | |
3212 | // ObjectInputStream /////////////////////////////////////////////////////////////// |
3213 | |
3214 | // Return the first user-defined class loader up the execution stack, or null |
3215 | // if only code from the bootstrap or platform class loader is on the stack. |
3216 | |
3217 | JVM_ENTRY(jobject, JVM_LatestUserDefinedLoader(JNIEnv *env)) |
3218 | for (vframeStream vfst(thread); !vfst.at_end(); vfst.next()) { |
3219 | vfst.skip_reflection_related_frames(); // Only needed for 1.4 reflection |
3220 | oop loader = vfst.method()->method_holder()->class_loader(); |
3221 | if (loader != NULL && !SystemDictionary::is_platform_class_loader(loader)) { |
3222 | return JNIHandles::make_local(env, loader); |
3223 | } |
3224 | } |
3225 | return NULL; |
3226 | JVM_END |
3227 | |
3228 | |
3229 | // Array /////////////////////////////////////////////////////////////////////////////////////////// |
3230 | |
3231 | |
3232 | // resolve array handle and check arguments |
3233 | static inline arrayOop check_array(JNIEnv *env, jobject arr, bool type_array_only, TRAPS) { |
3234 | if (arr == NULL) { |
3235 | THROW_0(vmSymbols::java_lang_NullPointerException()); |
3236 | } |
3237 | oop a = JNIHandles::resolve_non_null(arr); |
3238 | if (!a->is_array()) { |
3239 | THROW_MSG_0(vmSymbols::java_lang_IllegalArgumentException(), "Argument is not an array" ); |
3240 | } else if (type_array_only && !a->is_typeArray()) { |
3241 | THROW_MSG_0(vmSymbols::java_lang_IllegalArgumentException(), "Argument is not an array of primitive type" ); |
3242 | } |
3243 | return arrayOop(a); |
3244 | } |
3245 | |
3246 | |
3247 | JVM_ENTRY(jint, JVM_GetArrayLength(JNIEnv *env, jobject arr)) |
3248 | JVMWrapper("JVM_GetArrayLength" ); |
3249 | arrayOop a = check_array(env, arr, false, CHECK_0); |
3250 | return a->length(); |
3251 | JVM_END |
3252 | |
3253 | |
3254 | JVM_ENTRY(jobject, JVM_GetArrayElement(JNIEnv *env, jobject arr, jint index)) |
3255 | JVMWrapper("JVM_Array_Get" ); |
3256 | JvmtiVMObjectAllocEventCollector oam; |
3257 | arrayOop a = check_array(env, arr, false, CHECK_NULL); |
3258 | jvalue value; |
3259 | BasicType type = Reflection::array_get(&value, a, index, CHECK_NULL); |
3260 | oop box = Reflection::box(&value, type, CHECK_NULL); |
3261 | return JNIHandles::make_local(env, box); |
3262 | JVM_END |
3263 | |
3264 | |
3265 | JVM_ENTRY(jvalue, JVM_GetPrimitiveArrayElement(JNIEnv *env, jobject arr, jint index, jint wCode)) |
3266 | JVMWrapper("JVM_GetPrimitiveArrayElement" ); |
3267 | jvalue value; |
3268 | value.i = 0; // to initialize value before getting used in CHECK |
3269 | arrayOop a = check_array(env, arr, true, CHECK_(value)); |
3270 | assert(a->is_typeArray(), "just checking" ); |
3271 | BasicType type = Reflection::array_get(&value, a, index, CHECK_(value)); |
3272 | BasicType wide_type = (BasicType) wCode; |
3273 | if (type != wide_type) { |
3274 | Reflection::widen(&value, type, wide_type, CHECK_(value)); |
3275 | } |
3276 | return value; |
3277 | JVM_END |
3278 | |
3279 | |
3280 | JVM_ENTRY(void, JVM_SetArrayElement(JNIEnv *env, jobject arr, jint index, jobject val)) |
3281 | JVMWrapper("JVM_SetArrayElement" ); |
3282 | arrayOop a = check_array(env, arr, false, CHECK); |
3283 | oop box = JNIHandles::resolve(val); |
3284 | jvalue value; |
3285 | value.i = 0; // to initialize value before getting used in CHECK |
3286 | BasicType value_type; |
3287 | if (a->is_objArray()) { |
3288 | // Make sure we do no unbox e.g. java/lang/Integer instances when storing into an object array |
3289 | value_type = Reflection::unbox_for_regular_object(box, &value); |
3290 | } else { |
3291 | value_type = Reflection::unbox_for_primitive(box, &value, CHECK); |
3292 | } |
3293 | Reflection::array_set(&value, a, index, value_type, CHECK); |
3294 | JVM_END |
3295 | |
3296 | |
3297 | JVM_ENTRY(void, JVM_SetPrimitiveArrayElement(JNIEnv *env, jobject arr, jint index, jvalue v, unsigned char vCode)) |
3298 | JVMWrapper("JVM_SetPrimitiveArrayElement" ); |
3299 | arrayOop a = check_array(env, arr, true, CHECK); |
3300 | assert(a->is_typeArray(), "just checking" ); |
3301 | BasicType value_type = (BasicType) vCode; |
3302 | Reflection::array_set(&v, a, index, value_type, CHECK); |
3303 | JVM_END |
3304 | |
3305 | |
3306 | JVM_ENTRY(jobject, JVM_NewArray(JNIEnv *env, jclass eltClass, jint length)) |
3307 | JVMWrapper("JVM_NewArray" ); |
3308 | JvmtiVMObjectAllocEventCollector oam; |
3309 | oop element_mirror = JNIHandles::resolve(eltClass); |
3310 | oop result = Reflection::reflect_new_array(element_mirror, length, CHECK_NULL); |
3311 | return JNIHandles::make_local(env, result); |
3312 | JVM_END |
3313 | |
3314 | |
3315 | JVM_ENTRY(jobject, JVM_NewMultiArray(JNIEnv *env, jclass eltClass, jintArray dim)) |
3316 | JVMWrapper("JVM_NewMultiArray" ); |
3317 | JvmtiVMObjectAllocEventCollector oam; |
3318 | arrayOop dim_array = check_array(env, dim, true, CHECK_NULL); |
3319 | oop element_mirror = JNIHandles::resolve(eltClass); |
3320 | assert(dim_array->is_typeArray(), "just checking" ); |
3321 | oop result = Reflection::reflect_new_multi_array(element_mirror, typeArrayOop(dim_array), CHECK_NULL); |
3322 | return JNIHandles::make_local(env, result); |
3323 | JVM_END |
3324 | |
3325 | |
3326 | // Library support /////////////////////////////////////////////////////////////////////////// |
3327 | |
3328 | JVM_ENTRY_NO_ENV(void*, JVM_LoadLibrary(const char* name)) |
3329 | //%note jvm_ct |
3330 | JVMWrapper("JVM_LoadLibrary" ); |
3331 | char ebuf[1024]; |
3332 | void *load_result; |
3333 | { |
3334 | ThreadToNativeFromVM ttnfvm(thread); |
3335 | load_result = os::dll_load(name, ebuf, sizeof ebuf); |
3336 | } |
3337 | if (load_result == NULL) { |
3338 | char msg[1024]; |
3339 | jio_snprintf(msg, sizeof msg, "%s: %s" , name, ebuf); |
3340 | // Since 'ebuf' may contain a string encoded using |
3341 | // platform encoding scheme, we need to pass |
3342 | // Exceptions::unsafe_to_utf8 to the new_exception method |
3343 | // as the last argument. See bug 6367357. |
3344 | Handle h_exception = |
3345 | Exceptions::new_exception(thread, |
3346 | vmSymbols::java_lang_UnsatisfiedLinkError(), |
3347 | msg, Exceptions::unsafe_to_utf8); |
3348 | |
3349 | THROW_HANDLE_0(h_exception); |
3350 | } |
3351 | return load_result; |
3352 | JVM_END |
3353 | |
3354 | |
3355 | JVM_LEAF(void, JVM_UnloadLibrary(void* handle)) |
3356 | JVMWrapper("JVM_UnloadLibrary" ); |
3357 | os::dll_unload(handle); |
3358 | JVM_END |
3359 | |
3360 | |
3361 | JVM_LEAF(void*, JVM_FindLibraryEntry(void* handle, const char* name)) |
3362 | JVMWrapper("JVM_FindLibraryEntry" ); |
3363 | return os::dll_lookup(handle, name); |
3364 | JVM_END |
3365 | |
3366 | |
3367 | // JNI version /////////////////////////////////////////////////////////////////////////////// |
3368 | |
3369 | JVM_LEAF(jboolean, JVM_IsSupportedJNIVersion(jint version)) |
3370 | JVMWrapper("JVM_IsSupportedJNIVersion" ); |
3371 | return Threads::is_supported_jni_version_including_1_1(version); |
3372 | JVM_END |
3373 | |
3374 | |
3375 | // String support /////////////////////////////////////////////////////////////////////////// |
3376 | |
3377 | JVM_ENTRY(jstring, JVM_InternString(JNIEnv *env, jstring str)) |
3378 | JVMWrapper("JVM_InternString" ); |
3379 | JvmtiVMObjectAllocEventCollector oam; |
3380 | if (str == NULL) return NULL; |
3381 | oop string = JNIHandles::resolve_non_null(str); |
3382 | oop result = StringTable::intern(string, CHECK_NULL); |
3383 | return (jstring) JNIHandles::make_local(env, result); |
3384 | JVM_END |
3385 | |
3386 | |
3387 | // Raw monitor support ////////////////////////////////////////////////////////////////////// |
3388 | |
3389 | // The lock routine below calls lock_without_safepoint_check in order to get a raw lock |
3390 | // without interfering with the safepoint mechanism. The routines are not JVM_LEAF because |
3391 | // they might be called by non-java threads. The JVM_LEAF installs a NoHandleMark check |
3392 | // that only works with java threads. |
3393 | |
3394 | |
3395 | JNIEXPORT void* JNICALL JVM_RawMonitorCreate(void) { |
3396 | VM_Exit::block_if_vm_exited(); |
3397 | JVMWrapper("JVM_RawMonitorCreate" ); |
3398 | return new Mutex(Mutex::native, "JVM_RawMonitorCreate" ); |
3399 | } |
3400 | |
3401 | |
3402 | JNIEXPORT void JNICALL JVM_RawMonitorDestroy(void *mon) { |
3403 | VM_Exit::block_if_vm_exited(); |
3404 | JVMWrapper("JVM_RawMonitorDestroy" ); |
3405 | delete ((Mutex*) mon); |
3406 | } |
3407 | |
3408 | |
3409 | JNIEXPORT jint JNICALL JVM_RawMonitorEnter(void *mon) { |
3410 | VM_Exit::block_if_vm_exited(); |
3411 | JVMWrapper("JVM_RawMonitorEnter" ); |
3412 | ((Mutex*) mon)->jvm_raw_lock(); |
3413 | return 0; |
3414 | } |
3415 | |
3416 | |
3417 | JNIEXPORT void JNICALL JVM_RawMonitorExit(void *mon) { |
3418 | VM_Exit::block_if_vm_exited(); |
3419 | JVMWrapper("JVM_RawMonitorExit" ); |
3420 | ((Mutex*) mon)->jvm_raw_unlock(); |
3421 | } |
3422 | |
3423 | |
3424 | // Shared JNI/JVM entry points ////////////////////////////////////////////////////////////// |
3425 | |
3426 | jclass find_class_from_class_loader(JNIEnv* env, Symbol* name, jboolean init, |
3427 | Handle loader, Handle protection_domain, |
3428 | jboolean throwError, TRAPS) { |
3429 | // Security Note: |
3430 | // The Java level wrapper will perform the necessary security check allowing |
3431 | // us to pass the NULL as the initiating class loader. The VM is responsible for |
3432 | // the checkPackageAccess relative to the initiating class loader via the |
3433 | // protection_domain. The protection_domain is passed as NULL by the java code |
3434 | // if there is no security manager in 3-arg Class.forName(). |
3435 | Klass* klass = SystemDictionary::resolve_or_fail(name, loader, protection_domain, throwError != 0, CHECK_NULL); |
3436 | |
3437 | // Check if we should initialize the class |
3438 | if (init && klass->is_instance_klass()) { |
3439 | klass->initialize(CHECK_NULL); |
3440 | } |
3441 | return (jclass) JNIHandles::make_local(env, klass->java_mirror()); |
3442 | } |
3443 | |
3444 | |
3445 | // Method /////////////////////////////////////////////////////////////////////////////////////////// |
3446 | |
3447 | JVM_ENTRY(jobject, JVM_InvokeMethod(JNIEnv *env, jobject method, jobject obj, jobjectArray args0)) |
3448 | JVMWrapper("JVM_InvokeMethod" ); |
3449 | Handle method_handle; |
3450 | if (thread->stack_available((address) &method_handle) >= JVMInvokeMethodSlack) { |
3451 | method_handle = Handle(THREAD, JNIHandles::resolve(method)); |
3452 | Handle receiver(THREAD, JNIHandles::resolve(obj)); |
3453 | objArrayHandle args(THREAD, objArrayOop(JNIHandles::resolve(args0))); |
3454 | oop result = Reflection::invoke_method(method_handle(), receiver, args, CHECK_NULL); |
3455 | jobject res = JNIHandles::make_local(env, result); |
3456 | if (JvmtiExport::should_post_vm_object_alloc()) { |
3457 | oop ret_type = java_lang_reflect_Method::return_type(method_handle()); |
3458 | assert(ret_type != NULL, "sanity check: ret_type oop must not be NULL!" ); |
3459 | if (java_lang_Class::is_primitive(ret_type)) { |
3460 | // Only for primitive type vm allocates memory for java object. |
3461 | // See box() method. |
3462 | JvmtiExport::post_vm_object_alloc(JavaThread::current(), result); |
3463 | } |
3464 | } |
3465 | return res; |
3466 | } else { |
3467 | THROW_0(vmSymbols::java_lang_StackOverflowError()); |
3468 | } |
3469 | JVM_END |
3470 | |
3471 | |
3472 | JVM_ENTRY(jobject, JVM_NewInstanceFromConstructor(JNIEnv *env, jobject c, jobjectArray args0)) |
3473 | JVMWrapper("JVM_NewInstanceFromConstructor" ); |
3474 | oop constructor_mirror = JNIHandles::resolve(c); |
3475 | objArrayHandle args(THREAD, objArrayOop(JNIHandles::resolve(args0))); |
3476 | oop result = Reflection::invoke_constructor(constructor_mirror, args, CHECK_NULL); |
3477 | jobject res = JNIHandles::make_local(env, result); |
3478 | if (JvmtiExport::should_post_vm_object_alloc()) { |
3479 | JvmtiExport::post_vm_object_alloc(JavaThread::current(), result); |
3480 | } |
3481 | return res; |
3482 | JVM_END |
3483 | |
3484 | // Atomic /////////////////////////////////////////////////////////////////////////////////////////// |
3485 | |
3486 | JVM_LEAF(jboolean, JVM_SupportsCX8()) |
3487 | JVMWrapper("JVM_SupportsCX8" ); |
3488 | return VM_Version::supports_cx8(); |
3489 | JVM_END |
3490 | |
3491 | JVM_ENTRY(void, JVM_InitializeFromArchive(JNIEnv* env, jclass cls)) |
3492 | JVMWrapper("JVM_InitializeFromArchive" ); |
3493 | Klass* k = java_lang_Class::as_Klass(JNIHandles::resolve(cls)); |
3494 | assert(k->is_klass(), "just checking" ); |
3495 | HeapShared::initialize_from_archived_subgraph(k); |
3496 | JVM_END |
3497 | |
3498 | // Returns an array of all live Thread objects (VM internal JavaThreads, |
3499 | // jvmti agent threads, and JNI attaching threads are skipped) |
3500 | // See CR 6404306 regarding JNI attaching threads |
3501 | JVM_ENTRY(jobjectArray, JVM_GetAllThreads(JNIEnv *env, jclass dummy)) |
3502 | ResourceMark rm(THREAD); |
3503 | ThreadsListEnumerator tle(THREAD, false, false); |
3504 | JvmtiVMObjectAllocEventCollector oam; |
3505 | |
3506 | int num_threads = tle.num_threads(); |
3507 | objArrayOop r = oopFactory::new_objArray(SystemDictionary::Thread_klass(), num_threads, CHECK_NULL); |
3508 | objArrayHandle threads_ah(THREAD, r); |
3509 | |
3510 | for (int i = 0; i < num_threads; i++) { |
3511 | Handle h = tle.get_threadObj(i); |
3512 | threads_ah->obj_at_put(i, h()); |
3513 | } |
3514 | |
3515 | return (jobjectArray) JNIHandles::make_local(env, threads_ah()); |
3516 | JVM_END |
3517 | |
3518 | |
3519 | // Support for java.lang.Thread.getStackTrace() and getAllStackTraces() methods |
3520 | // Return StackTraceElement[][], each element is the stack trace of a thread in |
3521 | // the corresponding entry in the given threads array |
3522 | JVM_ENTRY(jobjectArray, JVM_DumpThreads(JNIEnv *env, jclass threadClass, jobjectArray threads)) |
3523 | JVMWrapper("JVM_DumpThreads" ); |
3524 | JvmtiVMObjectAllocEventCollector oam; |
3525 | |
3526 | // Check if threads is null |
3527 | if (threads == NULL) { |
3528 | THROW_(vmSymbols::java_lang_NullPointerException(), 0); |
3529 | } |
3530 | |
3531 | objArrayOop a = objArrayOop(JNIHandles::resolve_non_null(threads)); |
3532 | objArrayHandle ah(THREAD, a); |
3533 | int num_threads = ah->length(); |
3534 | // check if threads is non-empty array |
3535 | if (num_threads == 0) { |
3536 | THROW_(vmSymbols::java_lang_IllegalArgumentException(), 0); |
3537 | } |
3538 | |
3539 | // check if threads is not an array of objects of Thread class |
3540 | Klass* k = ObjArrayKlass::cast(ah->klass())->element_klass(); |
3541 | if (k != SystemDictionary::Thread_klass()) { |
3542 | THROW_(vmSymbols::java_lang_IllegalArgumentException(), 0); |
3543 | } |
3544 | |
3545 | ResourceMark rm(THREAD); |
3546 | |
3547 | GrowableArray<instanceHandle>* thread_handle_array = new GrowableArray<instanceHandle>(num_threads); |
3548 | for (int i = 0; i < num_threads; i++) { |
3549 | oop thread_obj = ah->obj_at(i); |
3550 | instanceHandle h(THREAD, (instanceOop) thread_obj); |
3551 | thread_handle_array->append(h); |
3552 | } |
3553 | |
3554 | // The JavaThread references in thread_handle_array are validated |
3555 | // in VM_ThreadDump::doit(). |
3556 | Handle stacktraces = ThreadService::dump_stack_traces(thread_handle_array, num_threads, CHECK_NULL); |
3557 | return (jobjectArray)JNIHandles::make_local(env, stacktraces()); |
3558 | |
3559 | JVM_END |
3560 | |
3561 | // JVM monitoring and management support |
3562 | JVM_ENTRY_NO_ENV(void*, JVM_GetManagement(jint version)) |
3563 | return Management::get_jmm_interface(version); |
3564 | JVM_END |
3565 | |
3566 | // com.sun.tools.attach.VirtualMachine agent properties support |
3567 | // |
3568 | // Initialize the agent properties with the properties maintained in the VM |
3569 | JVM_ENTRY(jobject, JVM_InitAgentProperties(JNIEnv *env, jobject properties)) |
3570 | JVMWrapper("JVM_InitAgentProperties" ); |
3571 | ResourceMark rm; |
3572 | |
3573 | Handle props(THREAD, JNIHandles::resolve_non_null(properties)); |
3574 | |
3575 | PUTPROP(props, "sun.java.command" , Arguments::java_command()); |
3576 | PUTPROP(props, "sun.jvm.flags" , Arguments::jvm_flags()); |
3577 | PUTPROP(props, "sun.jvm.args" , Arguments::jvm_args()); |
3578 | return properties; |
3579 | JVM_END |
3580 | |
3581 | JVM_ENTRY(jobjectArray, JVM_GetEnclosingMethodInfo(JNIEnv *env, jclass ofClass)) |
3582 | { |
3583 | JVMWrapper("JVM_GetEnclosingMethodInfo" ); |
3584 | JvmtiVMObjectAllocEventCollector oam; |
3585 | |
3586 | if (ofClass == NULL) { |
3587 | return NULL; |
3588 | } |
3589 | Handle mirror(THREAD, JNIHandles::resolve_non_null(ofClass)); |
3590 | // Special handling for primitive objects |
3591 | if (java_lang_Class::is_primitive(mirror())) { |
3592 | return NULL; |
3593 | } |
3594 | Klass* k = java_lang_Class::as_Klass(mirror()); |
3595 | if (!k->is_instance_klass()) { |
3596 | return NULL; |
3597 | } |
3598 | InstanceKlass* ik = InstanceKlass::cast(k); |
3599 | int encl_method_class_idx = ik->enclosing_method_class_index(); |
3600 | if (encl_method_class_idx == 0) { |
3601 | return NULL; |
3602 | } |
3603 | objArrayOop dest_o = oopFactory::new_objArray(SystemDictionary::Object_klass(), 3, CHECK_NULL); |
3604 | objArrayHandle dest(THREAD, dest_o); |
3605 | Klass* enc_k = ik->constants()->klass_at(encl_method_class_idx, CHECK_NULL); |
3606 | dest->obj_at_put(0, enc_k->java_mirror()); |
3607 | int encl_method_method_idx = ik->enclosing_method_method_index(); |
3608 | if (encl_method_method_idx != 0) { |
3609 | Symbol* sym = ik->constants()->symbol_at( |
3610 | extract_low_short_from_int( |
3611 | ik->constants()->name_and_type_at(encl_method_method_idx))); |
3612 | Handle str = java_lang_String::create_from_symbol(sym, CHECK_NULL); |
3613 | dest->obj_at_put(1, str()); |
3614 | sym = ik->constants()->symbol_at( |
3615 | extract_high_short_from_int( |
3616 | ik->constants()->name_and_type_at(encl_method_method_idx))); |
3617 | str = java_lang_String::create_from_symbol(sym, CHECK_NULL); |
3618 | dest->obj_at_put(2, str()); |
3619 | } |
3620 | return (jobjectArray) JNIHandles::make_local(dest()); |
3621 | } |
3622 | JVM_END |
3623 | |
3624 | JVM_ENTRY(void, JVM_GetVersionInfo(JNIEnv* env, jvm_version_info* info, size_t info_size)) |
3625 | { |
3626 | memset(info, 0, info_size); |
3627 | |
3628 | info->jvm_version = VM_Version::jvm_version(); |
3629 | info->patch_version = VM_Version::vm_patch_version(); |
3630 | |
3631 | // when we add a new capability in the jvm_version_info struct, we should also |
3632 | // consider to expose this new capability in the sun.rt.jvmCapabilities jvmstat |
3633 | // counter defined in runtimeService.cpp. |
3634 | info->is_attach_supported = AttachListener::is_attach_supported(); |
3635 | } |
3636 | JVM_END |
3637 | |
3638 | // Returns an array of java.lang.String objects containing the input arguments to the VM. |
3639 | JVM_ENTRY(jobjectArray, JVM_GetVmArguments(JNIEnv *env)) |
3640 | ResourceMark rm(THREAD); |
3641 | |
3642 | if (Arguments::num_jvm_args() == 0 && Arguments::num_jvm_flags() == 0) { |
3643 | return NULL; |
3644 | } |
3645 | |
3646 | char** vm_flags = Arguments::jvm_flags_array(); |
3647 | char** vm_args = Arguments::jvm_args_array(); |
3648 | int num_flags = Arguments::num_jvm_flags(); |
3649 | int num_args = Arguments::num_jvm_args(); |
3650 | |
3651 | InstanceKlass* ik = SystemDictionary::String_klass(); |
3652 | objArrayOop r = oopFactory::new_objArray(ik, num_args + num_flags, CHECK_NULL); |
3653 | objArrayHandle result_h(THREAD, r); |
3654 | |
3655 | int index = 0; |
3656 | for (int j = 0; j < num_flags; j++, index++) { |
3657 | Handle h = java_lang_String::create_from_platform_dependent_str(vm_flags[j], CHECK_NULL); |
3658 | result_h->obj_at_put(index, h()); |
3659 | } |
3660 | for (int i = 0; i < num_args; i++, index++) { |
3661 | Handle h = java_lang_String::create_from_platform_dependent_str(vm_args[i], CHECK_NULL); |
3662 | result_h->obj_at_put(index, h()); |
3663 | } |
3664 | return (jobjectArray) JNIHandles::make_local(env, result_h()); |
3665 | JVM_END |
3666 | |
3667 | JVM_ENTRY_NO_ENV(jint, JVM_FindSignal(const char *name)) |
3668 | return os::get_signal_number(name); |
3669 | JVM_END |
3670 | |