Mercurial > hg > truffle
annotate src/share/vm/prims/jvm.cpp @ 452:00b023ae2d78
6722113: CMS: Incorrect overflow handling during precleaning of Reference lists
Summary: When we encounter marking stack overflow during precleaning of Reference lists, we were using the overflow list mechanism, which can cause problems on account of mutating the mark word of the header because of conflicts with mutator accesses and updates of that field. Instead we should use the usual mechanism for overflow handling in concurrent phases, namely dirtying of the card on which the overflowed object lies. Since precleaning effectively does a form of discovered list processing, albeit with discovery enabled, we needed to adjust some code to be correct in the face of interleaved processing and discovery.
Reviewed-by: apetrusenko, jcoomes
author | ysr |
---|---|
date | Thu, 20 Nov 2008 12:27:41 -0800 |
parents | a45484ea312d |
children | 2328d1d3f8cf |
rev | line source |
---|---|
0 | 1 /* |
196 | 2 * Copyright 1997-2008 Sun Microsystems, Inc. All Rights Reserved. |
0 | 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. |
4 * | |
5 * This code is free software; you can redistribute it and/or modify it | |
6 * under the terms of the GNU General Public License version 2 only, as | |
7 * published by the Free Software Foundation. | |
8 * | |
9 * This code is distributed in the hope that it will be useful, but WITHOUT | |
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | |
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License | |
12 * version 2 for more details (a copy is included in the LICENSE file that | |
13 * accompanied this code). | |
14 * | |
15 * You should have received a copy of the GNU General Public License version | |
16 * 2 along with this work; if not, write to the Free Software Foundation, | |
17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. | |
18 * | |
19 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, | |
20 * CA 95054 USA or visit www.sun.com if you need additional information or | |
21 * have any questions. | |
22 * | |
23 */ | |
24 | |
25 #include "incls/_precompiled.incl" | |
26 #include "incls/_jvm.cpp.incl" | |
27 #include <errno.h> | |
28 | |
29 /* | |
30 NOTE about use of any ctor or function call that can trigger a safepoint/GC: | |
31 such ctors and calls MUST NOT come between an oop declaration/init and its | |
32 usage because if objects are move this may cause various memory stomps, bus | |
33 errors and segfaults. Here is a cookbook for causing so called "naked oop | |
34 failures": | |
35 | |
36 JVM_ENTRY(jobjectArray, JVM_GetClassDeclaredFields<etc> { | |
37 JVMWrapper("JVM_GetClassDeclaredFields"); | |
38 | |
39 // Object address to be held directly in mirror & not visible to GC | |
40 oop mirror = JNIHandles::resolve_non_null(ofClass); | |
41 | |
42 // If this ctor can hit a safepoint, moving objects around, then | |
43 ComplexConstructor foo; | |
44 | |
45 // Boom! mirror may point to JUNK instead of the intended object | |
46 (some dereference of mirror) | |
47 | |
48 // Here's another call that may block for GC, making mirror stale | |
49 MutexLocker ml(some_lock); | |
50 | |
51 // And here's an initializer that can result in a stale oop | |
52 // all in one step. | |
53 oop o = call_that_can_throw_exception(TRAPS); | |
54 | |
55 | |
56 The solution is to keep the oop declaration BELOW the ctor or function | |
57 call that might cause a GC, do another resolve to reassign the oop, or | |
58 consider use of a Handle instead of an oop so there is immunity from object | |
59 motion. But note that the "QUICK" entries below do not have a handlemark | |
60 and thus can only support use of handles passed in. | |
61 */ | |
62 | |
63 static void trace_class_resolution_impl(klassOop to_class, TRAPS) { | |
64 ResourceMark rm; | |
65 int line_number = -1; | |
66 const char * source_file = NULL; | |
67 klassOop caller = NULL; | |
68 JavaThread* jthread = JavaThread::current(); | |
69 if (jthread->has_last_Java_frame()) { | |
70 vframeStream vfst(jthread); | |
71 | |
72 // scan up the stack skipping ClassLoader, AccessController and PrivilegedAction frames | |
73 symbolHandle access_controller = oopFactory::new_symbol_handle("java/security/AccessController", CHECK); | |
74 klassOop access_controller_klass = SystemDictionary::resolve_or_fail(access_controller, false, CHECK); | |
75 symbolHandle privileged_action = oopFactory::new_symbol_handle("java/security/PrivilegedAction", CHECK); | |
76 klassOop privileged_action_klass = SystemDictionary::resolve_or_fail(privileged_action, false, CHECK); | |
77 | |
78 methodOop last_caller = NULL; | |
79 | |
80 while (!vfst.at_end()) { | |
81 methodOop m = vfst.method(); | |
82 if (!vfst.method()->method_holder()->klass_part()->is_subclass_of(SystemDictionary::classloader_klass())&& | |
83 !vfst.method()->method_holder()->klass_part()->is_subclass_of(access_controller_klass) && | |
84 !vfst.method()->method_holder()->klass_part()->is_subclass_of(privileged_action_klass)) { | |
85 break; | |
86 } | |
87 last_caller = m; | |
88 vfst.next(); | |
89 } | |
90 // if this is called from Class.forName0 and that is called from Class.forName, | |
91 // then print the caller of Class.forName. If this is Class.loadClass, then print | |
92 // that caller, otherwise keep quiet since this should be picked up elsewhere. | |
93 bool found_it = false; | |
94 if (!vfst.at_end() && | |
95 instanceKlass::cast(vfst.method()->method_holder())->name() == vmSymbols::java_lang_Class() && | |
96 vfst.method()->name() == vmSymbols::forName0_name()) { | |
97 vfst.next(); | |
98 if (!vfst.at_end() && | |
99 instanceKlass::cast(vfst.method()->method_holder())->name() == vmSymbols::java_lang_Class() && | |
100 vfst.method()->name() == vmSymbols::forName_name()) { | |
101 vfst.next(); | |
102 found_it = true; | |
103 } | |
104 } else if (last_caller != NULL && | |
105 instanceKlass::cast(last_caller->method_holder())->name() == | |
106 vmSymbols::java_lang_ClassLoader() && | |
107 (last_caller->name() == vmSymbols::loadClassInternal_name() || | |
108 last_caller->name() == vmSymbols::loadClass_name())) { | |
109 found_it = true; | |
110 } | |
111 if (found_it && !vfst.at_end()) { | |
112 // found the caller | |
113 caller = vfst.method()->method_holder(); | |
114 line_number = vfst.method()->line_number_from_bci(vfst.bci()); | |
115 symbolOop s = instanceKlass::cast(vfst.method()->method_holder())->source_file_name(); | |
116 if (s != NULL) { | |
117 source_file = s->as_C_string(); | |
118 } | |
119 } | |
120 } | |
121 if (caller != NULL) { | |
122 if (to_class != caller) { | |
123 const char * from = Klass::cast(caller)->external_name(); | |
124 const char * to = Klass::cast(to_class)->external_name(); | |
125 // print in a single call to reduce interleaving between threads | |
126 if (source_file != NULL) { | |
127 tty->print("RESOLVE %s %s %s:%d (explicit)\n", from, to, source_file, line_number); | |
128 } else { | |
129 tty->print("RESOLVE %s %s (explicit)\n", from, to); | |
130 } | |
131 } | |
132 } | |
133 } | |
134 | |
135 static void trace_class_resolution(klassOop to_class) { | |
136 EXCEPTION_MARK; | |
137 trace_class_resolution_impl(to_class, THREAD); | |
138 if (HAS_PENDING_EXCEPTION) { | |
139 CLEAR_PENDING_EXCEPTION; | |
140 } | |
141 } | |
142 | |
143 // Wrapper to trace JVM functions | |
144 | |
145 #ifdef ASSERT | |
146 class JVMTraceWrapper : public StackObj { | |
147 public: | |
148 JVMTraceWrapper(const char* format, ...) { | |
149 if (TraceJVMCalls) { | |
150 va_list ap; | |
151 va_start(ap, format); | |
152 tty->print("JVM "); | |
153 tty->vprint_cr(format, ap); | |
154 va_end(ap); | |
155 } | |
156 } | |
157 }; | |
158 | |
159 Histogram* JVMHistogram; | |
160 volatile jint JVMHistogram_lock = 0; | |
161 | |
162 class JVMHistogramElement : public HistogramElement { | |
163 public: | |
164 JVMHistogramElement(const char* name); | |
165 }; | |
166 | |
167 JVMHistogramElement::JVMHistogramElement(const char* elementName) { | |
168 _name = elementName; | |
169 uintx count = 0; | |
170 | |
171 while (Atomic::cmpxchg(1, &JVMHistogram_lock, 0) != 0) { | |
172 while (OrderAccess::load_acquire(&JVMHistogram_lock) != 0) { | |
173 count +=1; | |
174 if ( (WarnOnStalledSpinLock > 0) | |
175 && (count % WarnOnStalledSpinLock == 0)) { | |
176 warning("JVMHistogram_lock seems to be stalled"); | |
177 } | |
178 } | |
179 } | |
180 | |
181 if(JVMHistogram == NULL) | |
182 JVMHistogram = new Histogram("JVM Call Counts",100); | |
183 | |
184 JVMHistogram->add_element(this); | |
185 Atomic::dec(&JVMHistogram_lock); | |
186 } | |
187 | |
188 #define JVMCountWrapper(arg) \ | |
189 static JVMHistogramElement* e = new JVMHistogramElement(arg); \ | |
190 if (e != NULL) e->increment_count(); // Due to bug in VC++, we need a NULL check here eventhough it should never happen! | |
191 | |
192 #define JVMWrapper(arg1) JVMCountWrapper(arg1); JVMTraceWrapper(arg1) | |
193 #define JVMWrapper2(arg1, arg2) JVMCountWrapper(arg1); JVMTraceWrapper(arg1, arg2) | |
194 #define JVMWrapper3(arg1, arg2, arg3) JVMCountWrapper(arg1); JVMTraceWrapper(arg1, arg2, arg3) | |
195 #define JVMWrapper4(arg1, arg2, arg3, arg4) JVMCountWrapper(arg1); JVMTraceWrapper(arg1, arg2, arg3, arg4) | |
196 #else | |
197 #define JVMWrapper(arg1) | |
198 #define JVMWrapper2(arg1, arg2) | |
199 #define JVMWrapper3(arg1, arg2, arg3) | |
200 #define JVMWrapper4(arg1, arg2, arg3, arg4) | |
201 #endif | |
202 | |
203 | |
204 // Interface version ///////////////////////////////////////////////////////////////////// | |
205 | |
206 | |
207 JVM_LEAF(jint, JVM_GetInterfaceVersion()) | |
208 return JVM_INTERFACE_VERSION; | |
209 JVM_END | |
210 | |
211 | |
212 // java.lang.System ////////////////////////////////////////////////////////////////////// | |
213 | |
214 | |
215 JVM_LEAF(jlong, JVM_CurrentTimeMillis(JNIEnv *env, jclass ignored)) | |
216 JVMWrapper("JVM_CurrentTimeMillis"); | |
217 return os::javaTimeMillis(); | |
218 JVM_END | |
219 | |
220 JVM_LEAF(jlong, JVM_NanoTime(JNIEnv *env, jclass ignored)) | |
221 JVMWrapper("JVM_NanoTime"); | |
222 return os::javaTimeNanos(); | |
223 JVM_END | |
224 | |
225 | |
226 JVM_ENTRY(void, JVM_ArrayCopy(JNIEnv *env, jclass ignored, jobject src, jint src_pos, | |
227 jobject dst, jint dst_pos, jint length)) | |
228 JVMWrapper("JVM_ArrayCopy"); | |
229 // Check if we have null pointers | |
230 if (src == NULL || dst == NULL) { | |
231 THROW(vmSymbols::java_lang_NullPointerException()); | |
232 } | |
233 arrayOop s = arrayOop(JNIHandles::resolve_non_null(src)); | |
234 arrayOop d = arrayOop(JNIHandles::resolve_non_null(dst)); | |
235 assert(s->is_oop(), "JVM_ArrayCopy: src not an oop"); | |
236 assert(d->is_oop(), "JVM_ArrayCopy: dst not an oop"); | |
237 // Do copy | |
238 Klass::cast(s->klass())->copy_array(s, src_pos, d, dst_pos, length, thread); | |
239 JVM_END | |
240 | |
241 | |
242 static void set_property(Handle props, const char* key, const char* value, TRAPS) { | |
243 JavaValue r(T_OBJECT); | |
244 // public synchronized Object put(Object key, Object value); | |
245 HandleMark hm(THREAD); | |
246 Handle key_str = java_lang_String::create_from_platform_dependent_str(key, CHECK); | |
247 Handle value_str = java_lang_String::create_from_platform_dependent_str((value != NULL ? value : ""), CHECK); | |
248 JavaCalls::call_virtual(&r, | |
249 props, | |
250 KlassHandle(THREAD, SystemDictionary::properties_klass()), | |
251 vmSymbolHandles::put_name(), | |
252 vmSymbolHandles::object_object_object_signature(), | |
253 key_str, | |
254 value_str, | |
255 THREAD); | |
256 } | |
257 | |
258 | |
259 #define PUTPROP(props, name, value) set_property((props), (name), (value), CHECK_(properties)); | |
260 | |
261 | |
262 JVM_ENTRY(jobject, JVM_InitProperties(JNIEnv *env, jobject properties)) | |
263 JVMWrapper("JVM_InitProperties"); | |
264 ResourceMark rm; | |
265 | |
266 Handle props(THREAD, JNIHandles::resolve_non_null(properties)); | |
267 | |
268 // System property list includes both user set via -D option and | |
269 // jvm system specific properties. | |
270 for (SystemProperty* p = Arguments::system_properties(); p != NULL; p = p->next()) { | |
271 PUTPROP(props, p->key(), p->value()); | |
272 } | |
273 | |
274 // Convert the -XX:MaxDirectMemorySize= command line flag | |
275 // to the sun.nio.MaxDirectMemorySize property. | |
276 // Do this after setting user properties to prevent people | |
277 // from setting the value with a -D option, as requested. | |
278 { | |
279 char as_chars[256]; | |
280 jio_snprintf(as_chars, sizeof(as_chars), INTX_FORMAT, MaxDirectMemorySize); | |
281 PUTPROP(props, "sun.nio.MaxDirectMemorySize", as_chars); | |
282 } | |
283 | |
284 // JVM monitoring and management support | |
285 // Add the sun.management.compiler property for the compiler's name | |
286 { | |
287 #undef CSIZE | |
288 #if defined(_LP64) || defined(_WIN64) | |
289 #define CSIZE "64-Bit " | |
290 #else | |
291 #define CSIZE | |
292 #endif // 64bit | |
293 | |
294 #ifdef TIERED | |
295 const char* compiler_name = "HotSpot " CSIZE "Tiered Compilers"; | |
296 #else | |
297 #if defined(COMPILER1) | |
298 const char* compiler_name = "HotSpot " CSIZE "Client Compiler"; | |
299 #elif defined(COMPILER2) | |
300 const char* compiler_name = "HotSpot " CSIZE "Server Compiler"; | |
301 #else | |
302 const char* compiler_name = ""; | |
303 #endif // compilers | |
304 #endif // TIERED | |
305 | |
306 if (*compiler_name != '\0' && | |
307 (Arguments::mode() != Arguments::_int)) { | |
308 PUTPROP(props, "sun.management.compiler", compiler_name); | |
309 } | |
310 } | |
311 | |
312 return properties; | |
313 JVM_END | |
314 | |
315 | |
316 // java.lang.Runtime ///////////////////////////////////////////////////////////////////////// | |
317 | |
318 extern volatile jint vm_created; | |
319 | |
320 JVM_ENTRY_NO_ENV(void, JVM_Exit(jint code)) | |
321 if (vm_created != 0 && (code == 0)) { | |
322 // The VM is about to exit. We call back into Java to check whether finalizers should be run | |
323 Universe::run_finalizers_on_exit(); | |
324 } | |
325 before_exit(thread); | |
326 vm_exit(code); | |
327 JVM_END | |
328 | |
329 | |
330 JVM_ENTRY_NO_ENV(void, JVM_Halt(jint code)) | |
331 before_exit(thread); | |
332 vm_exit(code); | |
333 JVM_END | |
334 | |
335 | |
336 JVM_LEAF(void, JVM_OnExit(void (*func)(void))) | |
337 register_on_exit_function(func); | |
338 JVM_END | |
339 | |
340 | |
341 JVM_ENTRY_NO_ENV(void, JVM_GC(void)) | |
342 JVMWrapper("JVM_GC"); | |
343 if (!DisableExplicitGC) { | |
344 Universe::heap()->collect(GCCause::_java_lang_system_gc); | |
345 } | |
346 JVM_END | |
347 | |
348 | |
349 JVM_LEAF(jlong, JVM_MaxObjectInspectionAge(void)) | |
350 JVMWrapper("JVM_MaxObjectInspectionAge"); | |
351 return Universe::heap()->millis_since_last_gc(); | |
352 JVM_END | |
353 | |
354 | |
355 JVM_LEAF(void, JVM_TraceInstructions(jboolean on)) | |
356 if (PrintJVMWarnings) warning("JVM_TraceInstructions not supported"); | |
357 JVM_END | |
358 | |
359 | |
360 JVM_LEAF(void, JVM_TraceMethodCalls(jboolean on)) | |
361 if (PrintJVMWarnings) warning("JVM_TraceMethodCalls not supported"); | |
362 JVM_END | |
363 | |
364 static inline jlong convert_size_t_to_jlong(size_t val) { | |
365 // In the 64-bit vm, a size_t can overflow a jlong (which is signed). | |
366 NOT_LP64 (return (jlong)val;) | |
367 LP64_ONLY(return (jlong)MIN2(val, (size_t)max_jlong);) | |
368 } | |
369 | |
370 JVM_ENTRY_NO_ENV(jlong, JVM_TotalMemory(void)) | |
371 JVMWrapper("JVM_TotalMemory"); | |
372 size_t n = Universe::heap()->capacity(); | |
373 return convert_size_t_to_jlong(n); | |
374 JVM_END | |
375 | |
376 | |
377 JVM_ENTRY_NO_ENV(jlong, JVM_FreeMemory(void)) | |
378 JVMWrapper("JVM_FreeMemory"); | |
379 CollectedHeap* ch = Universe::heap(); | |
342
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
116
diff
changeset
|
380 size_t n; |
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
116
diff
changeset
|
381 { |
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
116
diff
changeset
|
382 MutexLocker x(Heap_lock); |
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
116
diff
changeset
|
383 n = ch->capacity() - ch->used(); |
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
116
diff
changeset
|
384 } |
0 | 385 return convert_size_t_to_jlong(n); |
386 JVM_END | |
387 | |
388 | |
389 JVM_ENTRY_NO_ENV(jlong, JVM_MaxMemory(void)) | |
390 JVMWrapper("JVM_MaxMemory"); | |
391 size_t n = Universe::heap()->max_capacity(); | |
392 return convert_size_t_to_jlong(n); | |
393 JVM_END | |
394 | |
395 | |
396 JVM_ENTRY_NO_ENV(jint, JVM_ActiveProcessorCount(void)) | |
397 JVMWrapper("JVM_ActiveProcessorCount"); | |
398 return os::active_processor_count(); | |
399 JVM_END | |
400 | |
401 | |
402 | |
403 // java.lang.Throwable ////////////////////////////////////////////////////// | |
404 | |
405 | |
406 JVM_ENTRY(void, JVM_FillInStackTrace(JNIEnv *env, jobject receiver)) | |
407 JVMWrapper("JVM_FillInStackTrace"); | |
408 Handle exception(thread, JNIHandles::resolve_non_null(receiver)); | |
409 java_lang_Throwable::fill_in_stack_trace(exception); | |
410 JVM_END | |
411 | |
412 | |
413 JVM_ENTRY(void, JVM_PrintStackTrace(JNIEnv *env, jobject receiver, jobject printable)) | |
414 JVMWrapper("JVM_PrintStackTrace"); | |
415 // Note: This is no longer used in Merlin, but we still support it for compatibility. | |
416 oop exception = JNIHandles::resolve_non_null(receiver); | |
417 oop stream = JNIHandles::resolve_non_null(printable); | |
418 java_lang_Throwable::print_stack_trace(exception, stream); | |
419 JVM_END | |
420 | |
421 | |
422 JVM_ENTRY(jint, JVM_GetStackTraceDepth(JNIEnv *env, jobject throwable)) | |
423 JVMWrapper("JVM_GetStackTraceDepth"); | |
424 oop exception = JNIHandles::resolve(throwable); | |
425 return java_lang_Throwable::get_stack_trace_depth(exception, THREAD); | |
426 JVM_END | |
427 | |
428 | |
429 JVM_ENTRY(jobject, JVM_GetStackTraceElement(JNIEnv *env, jobject throwable, jint index)) | |
430 JVMWrapper("JVM_GetStackTraceElement"); | |
431 JvmtiVMObjectAllocEventCollector oam; // This ctor (throughout this module) may trigger a safepoint/GC | |
432 oop exception = JNIHandles::resolve(throwable); | |
433 oop element = java_lang_Throwable::get_stack_trace_element(exception, index, CHECK_NULL); | |
434 return JNIHandles::make_local(env, element); | |
435 JVM_END | |
436 | |
437 | |
438 // java.lang.Object /////////////////////////////////////////////// | |
439 | |
440 | |
441 JVM_ENTRY(jint, JVM_IHashCode(JNIEnv* env, jobject handle)) | |
442 JVMWrapper("JVM_IHashCode"); | |
443 // as implemented in the classic virtual machine; return 0 if object is NULL | |
444 return handle == NULL ? 0 : ObjectSynchronizer::FastHashCode (THREAD, JNIHandles::resolve_non_null(handle)) ; | |
445 JVM_END | |
446 | |
447 | |
448 JVM_ENTRY(void, JVM_MonitorWait(JNIEnv* env, jobject handle, jlong ms)) | |
449 JVMWrapper("JVM_MonitorWait"); | |
450 Handle obj(THREAD, JNIHandles::resolve_non_null(handle)); | |
451 assert(obj->is_instance() || obj->is_array(), "JVM_MonitorWait must apply to an object"); | |
452 JavaThreadInObjectWaitState jtiows(thread, ms != 0); | |
453 if (JvmtiExport::should_post_monitor_wait()) { | |
454 JvmtiExport::post_monitor_wait((JavaThread *)THREAD, (oop)obj(), ms); | |
455 } | |
456 ObjectSynchronizer::wait(obj, ms, CHECK); | |
457 JVM_END | |
458 | |
459 | |
460 JVM_ENTRY(void, JVM_MonitorNotify(JNIEnv* env, jobject handle)) | |
461 JVMWrapper("JVM_MonitorNotify"); | |
462 Handle obj(THREAD, JNIHandles::resolve_non_null(handle)); | |
463 assert(obj->is_instance() || obj->is_array(), "JVM_MonitorNotify must apply to an object"); | |
464 ObjectSynchronizer::notify(obj, CHECK); | |
465 JVM_END | |
466 | |
467 | |
468 JVM_ENTRY(void, JVM_MonitorNotifyAll(JNIEnv* env, jobject handle)) | |
469 JVMWrapper("JVM_MonitorNotifyAll"); | |
470 Handle obj(THREAD, JNIHandles::resolve_non_null(handle)); | |
471 assert(obj->is_instance() || obj->is_array(), "JVM_MonitorNotifyAll must apply to an object"); | |
472 ObjectSynchronizer::notifyall(obj, CHECK); | |
473 JVM_END | |
474 | |
475 | |
476 JVM_ENTRY(jobject, JVM_Clone(JNIEnv* env, jobject handle)) | |
477 JVMWrapper("JVM_Clone"); | |
478 Handle obj(THREAD, JNIHandles::resolve_non_null(handle)); | |
479 const KlassHandle klass (THREAD, obj->klass()); | |
480 JvmtiVMObjectAllocEventCollector oam; | |
481 | |
482 #ifdef ASSERT | |
483 // Just checking that the cloneable flag is set correct | |
484 if (obj->is_javaArray()) { | |
485 guarantee(klass->is_cloneable(), "all arrays are cloneable"); | |
486 } else { | |
487 guarantee(obj->is_instance(), "should be instanceOop"); | |
488 bool cloneable = klass->is_subtype_of(SystemDictionary::cloneable_klass()); | |
489 guarantee(cloneable == klass->is_cloneable(), "incorrect cloneable flag"); | |
490 } | |
491 #endif | |
492 | |
493 // Check if class of obj supports the Cloneable interface. | |
494 // All arrays are considered to be cloneable (See JLS 20.1.5) | |
495 if (!klass->is_cloneable()) { | |
496 ResourceMark rm(THREAD); | |
497 THROW_MSG_0(vmSymbols::java_lang_CloneNotSupportedException(), klass->external_name()); | |
498 } | |
499 | |
500 // Make shallow object copy | |
501 const int size = obj->size(); | |
502 oop new_obj = NULL; | |
503 if (obj->is_javaArray()) { | |
504 const int length = ((arrayOop)obj())->length(); | |
505 new_obj = CollectedHeap::array_allocate(klass, size, length, CHECK_NULL); | |
506 } else { | |
507 new_obj = CollectedHeap::obj_allocate(klass, size, CHECK_NULL); | |
508 } | |
509 // 4839641 (4840070): We must do an oop-atomic copy, because if another thread | |
510 // is modifying a reference field in the clonee, a non-oop-atomic copy might | |
511 // be suspended in the middle of copying the pointer and end up with parts | |
512 // of two different pointers in the field. Subsequent dereferences will crash. | |
513 // 4846409: an oop-copy of objects with long or double fields or arrays of same | |
514 // won't copy the longs/doubles atomically in 32-bit vm's, so we copy jlongs instead | |
515 // of oops. We know objects are aligned on a minimum of an jlong boundary. | |
516 // The same is true of StubRoutines::object_copy and the various oop_copy | |
517 // variants, and of the code generated by the inline_native_clone intrinsic. | |
518 assert(MinObjAlignmentInBytes >= BytesPerLong, "objects misaligned"); | |
519 Copy::conjoint_jlongs_atomic((jlong*)obj(), (jlong*)new_obj, | |
520 (size_t)align_object_size(size) / HeapWordsPerLong); | |
521 // Clear the header | |
522 new_obj->init_mark(); | |
523 | |
524 // Store check (mark entire object and let gc sort it out) | |
525 BarrierSet* bs = Universe::heap()->barrier_set(); | |
526 assert(bs->has_write_region_opt(), "Barrier set does not have write_region"); | |
527 bs->write_region(MemRegion((HeapWord*)new_obj, size)); | |
528 | |
529 // Caution: this involves a java upcall, so the clone should be | |
530 // "gc-robust" by this stage. | |
531 if (klass->has_finalizer()) { | |
532 assert(obj->is_instance(), "should be instanceOop"); | |
533 new_obj = instanceKlass::register_finalizer(instanceOop(new_obj), CHECK_NULL); | |
534 } | |
535 | |
536 return JNIHandles::make_local(env, oop(new_obj)); | |
537 JVM_END | |
538 | |
539 // java.lang.Compiler //////////////////////////////////////////////////// | |
540 | |
541 // The initial cuts of the HotSpot VM will not support JITs, and all existing | |
542 // JITs would need extensive changes to work with HotSpot. The JIT-related JVM | |
543 // functions are all silently ignored unless JVM warnings are printed. | |
544 | |
545 JVM_LEAF(void, JVM_InitializeCompiler (JNIEnv *env, jclass compCls)) | |
546 if (PrintJVMWarnings) warning("JVM_InitializeCompiler not supported"); | |
547 JVM_END | |
548 | |
549 | |
550 JVM_LEAF(jboolean, JVM_IsSilentCompiler(JNIEnv *env, jclass compCls)) | |
551 if (PrintJVMWarnings) warning("JVM_IsSilentCompiler not supported"); | |
552 return JNI_FALSE; | |
553 JVM_END | |
554 | |
555 | |
556 JVM_LEAF(jboolean, JVM_CompileClass(JNIEnv *env, jclass compCls, jclass cls)) | |
557 if (PrintJVMWarnings) warning("JVM_CompileClass not supported"); | |
558 return JNI_FALSE; | |
559 JVM_END | |
560 | |
561 | |
562 JVM_LEAF(jboolean, JVM_CompileClasses(JNIEnv *env, jclass cls, jstring jname)) | |
563 if (PrintJVMWarnings) warning("JVM_CompileClasses not supported"); | |
564 return JNI_FALSE; | |
565 JVM_END | |
566 | |
567 | |
568 JVM_LEAF(jobject, JVM_CompilerCommand(JNIEnv *env, jclass compCls, jobject arg)) | |
569 if (PrintJVMWarnings) warning("JVM_CompilerCommand not supported"); | |
570 return NULL; | |
571 JVM_END | |
572 | |
573 | |
574 JVM_LEAF(void, JVM_EnableCompiler(JNIEnv *env, jclass compCls)) | |
575 if (PrintJVMWarnings) warning("JVM_EnableCompiler not supported"); | |
576 JVM_END | |
577 | |
578 | |
579 JVM_LEAF(void, JVM_DisableCompiler(JNIEnv *env, jclass compCls)) | |
580 if (PrintJVMWarnings) warning("JVM_DisableCompiler not supported"); | |
581 JVM_END | |
582 | |
583 | |
584 | |
585 // Error message support ////////////////////////////////////////////////////// | |
586 | |
587 JVM_LEAF(jint, JVM_GetLastErrorString(char *buf, int len)) | |
588 JVMWrapper("JVM_GetLastErrorString"); | |
589 return hpi::lasterror(buf, len); | |
590 JVM_END | |
591 | |
592 | |
593 // java.io.File /////////////////////////////////////////////////////////////// | |
594 | |
595 JVM_LEAF(char*, JVM_NativePath(char* path)) | |
596 JVMWrapper2("JVM_NativePath (%s)", path); | |
597 return hpi::native_path(path); | |
598 JVM_END | |
599 | |
600 | |
601 // Misc. class handling /////////////////////////////////////////////////////////// | |
602 | |
603 | |
604 JVM_ENTRY(jclass, JVM_GetCallerClass(JNIEnv* env, int depth)) | |
605 JVMWrapper("JVM_GetCallerClass"); | |
606 klassOop k = thread->security_get_caller_class(depth); | |
607 return (k == NULL) ? NULL : (jclass) JNIHandles::make_local(env, Klass::cast(k)->java_mirror()); | |
608 JVM_END | |
609 | |
610 | |
611 JVM_ENTRY(jclass, JVM_FindPrimitiveClass(JNIEnv* env, const char* utf)) | |
612 JVMWrapper("JVM_FindPrimitiveClass"); | |
613 oop mirror = NULL; | |
614 BasicType t = name2type(utf); | |
615 if (t != T_ILLEGAL && t != T_OBJECT && t != T_ARRAY) { | |
616 mirror = Universe::java_mirror(t); | |
617 } | |
618 if (mirror == NULL) { | |
619 THROW_MSG_0(vmSymbols::java_lang_ClassNotFoundException(), (char*) utf); | |
620 } else { | |
621 return (jclass) JNIHandles::make_local(env, mirror); | |
622 } | |
623 JVM_END | |
624 | |
625 | |
626 JVM_ENTRY(void, JVM_ResolveClass(JNIEnv* env, jclass cls)) | |
627 JVMWrapper("JVM_ResolveClass"); | |
628 if (PrintJVMWarnings) warning("JVM_ResolveClass not implemented"); | |
629 JVM_END | |
630 | |
388 | 631 // Common implementation for JVM_FindClassFromBootLoader and |
632 // JVM_FindClassFromLoader | |
633 static jclass jvm_find_class_from_class_loader(JNIEnv* env, const char* name, | |
634 jboolean init, jobject loader, | |
635 jboolean throwError, TRAPS) { | |
636 // Java libraries should ensure that name is never null... | |
637 if (name == NULL || (int)strlen(name) > symbolOopDesc::max_length()) { | |
638 // It's impossible to create this class; the name cannot fit | |
639 // into the constant pool. | |
640 if (throwError) { | |
641 THROW_MSG_0(vmSymbols::java_lang_NoClassDefFoundError(), name); | |
642 } else { | |
643 THROW_MSG_0(vmSymbols::java_lang_ClassNotFoundException(), name); | |
644 } | |
645 } | |
646 symbolHandle h_name = oopFactory::new_symbol_handle(name, CHECK_NULL); | |
647 Handle h_loader(THREAD, JNIHandles::resolve(loader)); | |
648 jclass result = find_class_from_class_loader(env, h_name, init, h_loader, | |
649 Handle(), throwError, THREAD); | |
650 | |
651 if (TraceClassResolution && result != NULL) { | |
652 trace_class_resolution(java_lang_Class::as_klassOop(JNIHandles::resolve_non_null(result))); | |
653 } | |
654 return result; | |
655 } | |
656 | |
226
d5ba4f8aa38a
6714758: hotspot: provide an entry point to the BootStrap Class loader[dholmes,acorn]
ksrini
parents:
116
diff
changeset
|
657 // Rationale behind JVM_FindClassFromBootLoader |
d5ba4f8aa38a
6714758: hotspot: provide an entry point to the BootStrap Class loader[dholmes,acorn]
ksrini
parents:
116
diff
changeset
|
658 // a> JVM_FindClassFromClassLoader was never exported in the export tables. |
d5ba4f8aa38a
6714758: hotspot: provide an entry point to the BootStrap Class loader[dholmes,acorn]
ksrini
parents:
116
diff
changeset
|
659 // b> because of (a) java.dll has a direct dependecy on the unexported |
d5ba4f8aa38a
6714758: hotspot: provide an entry point to the BootStrap Class loader[dholmes,acorn]
ksrini
parents:
116
diff
changeset
|
660 // private symbol "_JVM_FindClassFromClassLoader@20". |
d5ba4f8aa38a
6714758: hotspot: provide an entry point to the BootStrap Class loader[dholmes,acorn]
ksrini
parents:
116
diff
changeset
|
661 // c> the launcher cannot use the private symbol as it dynamically opens |
d5ba4f8aa38a
6714758: hotspot: provide an entry point to the BootStrap Class loader[dholmes,acorn]
ksrini
parents:
116
diff
changeset
|
662 // the entry point, so if something changes, the launcher will fail |
d5ba4f8aa38a
6714758: hotspot: provide an entry point to the BootStrap Class loader[dholmes,acorn]
ksrini
parents:
116
diff
changeset
|
663 // unexpectedly at runtime, it is safest for the launcher to dlopen a |
d5ba4f8aa38a
6714758: hotspot: provide an entry point to the BootStrap Class loader[dholmes,acorn]
ksrini
parents:
116
diff
changeset
|
664 // stable exported interface. |
d5ba4f8aa38a
6714758: hotspot: provide an entry point to the BootStrap Class loader[dholmes,acorn]
ksrini
parents:
116
diff
changeset
|
665 // d> re-exporting JVM_FindClassFromClassLoader as public, will cause its |
d5ba4f8aa38a
6714758: hotspot: provide an entry point to the BootStrap Class loader[dholmes,acorn]
ksrini
parents:
116
diff
changeset
|
666 // signature to change from _JVM_FindClassFromClassLoader@20 to |
d5ba4f8aa38a
6714758: hotspot: provide an entry point to the BootStrap Class loader[dholmes,acorn]
ksrini
parents:
116
diff
changeset
|
667 // JVM_FindClassFromClassLoader and will not be backward compatible |
d5ba4f8aa38a
6714758: hotspot: provide an entry point to the BootStrap Class loader[dholmes,acorn]
ksrini
parents:
116
diff
changeset
|
668 // with older JDKs. |
d5ba4f8aa38a
6714758: hotspot: provide an entry point to the BootStrap Class loader[dholmes,acorn]
ksrini
parents:
116
diff
changeset
|
669 // Thus a public/stable exported entry point is the right solution, |
d5ba4f8aa38a
6714758: hotspot: provide an entry point to the BootStrap Class loader[dholmes,acorn]
ksrini
parents:
116
diff
changeset
|
670 // public here means public in linker semantics, and is exported only |
d5ba4f8aa38a
6714758: hotspot: provide an entry point to the BootStrap Class loader[dholmes,acorn]
ksrini
parents:
116
diff
changeset
|
671 // to the JDK, and is not intended to be a public API. |
d5ba4f8aa38a
6714758: hotspot: provide an entry point to the BootStrap Class loader[dholmes,acorn]
ksrini
parents:
116
diff
changeset
|
672 |
d5ba4f8aa38a
6714758: hotspot: provide an entry point to the BootStrap Class loader[dholmes,acorn]
ksrini
parents:
116
diff
changeset
|
673 JVM_ENTRY(jclass, JVM_FindClassFromBootLoader(JNIEnv* env, |
d5ba4f8aa38a
6714758: hotspot: provide an entry point to the BootStrap Class loader[dholmes,acorn]
ksrini
parents:
116
diff
changeset
|
674 const char* name, |
d5ba4f8aa38a
6714758: hotspot: provide an entry point to the BootStrap Class loader[dholmes,acorn]
ksrini
parents:
116
diff
changeset
|
675 jboolean throwError)) |
d5ba4f8aa38a
6714758: hotspot: provide an entry point to the BootStrap Class loader[dholmes,acorn]
ksrini
parents:
116
diff
changeset
|
676 JVMWrapper3("JVM_FindClassFromBootLoader %s throw %s", name, |
d5ba4f8aa38a
6714758: hotspot: provide an entry point to the BootStrap Class loader[dholmes,acorn]
ksrini
parents:
116
diff
changeset
|
677 throwError ? "error" : "exception"); |
388 | 678 return jvm_find_class_from_class_loader(env, name, JNI_FALSE, |
679 (jobject)NULL, throwError, THREAD); | |
226
d5ba4f8aa38a
6714758: hotspot: provide an entry point to the BootStrap Class loader[dholmes,acorn]
ksrini
parents:
116
diff
changeset
|
680 JVM_END |
0 | 681 |
682 JVM_ENTRY(jclass, JVM_FindClassFromClassLoader(JNIEnv* env, const char* name, | |
683 jboolean init, jobject loader, | |
684 jboolean throwError)) | |
685 JVMWrapper3("JVM_FindClassFromClassLoader %s throw %s", name, | |
686 throwError ? "error" : "exception"); | |
388 | 687 return jvm_find_class_from_class_loader(env, name, init, loader, |
688 throwError, THREAD); | |
0 | 689 JVM_END |
690 | |
691 | |
692 JVM_ENTRY(jclass, JVM_FindClassFromClass(JNIEnv *env, const char *name, | |
693 jboolean init, jclass from)) | |
694 JVMWrapper2("JVM_FindClassFromClass %s", name); | |
695 if (name == NULL || (int)strlen(name) > symbolOopDesc::max_length()) { | |
696 // It's impossible to create this class; the name cannot fit | |
697 // into the constant pool. | |
698 THROW_MSG_0(vmSymbols::java_lang_NoClassDefFoundError(), name); | |
699 } | |
700 symbolHandle h_name = oopFactory::new_symbol_handle(name, CHECK_NULL); | |
701 oop from_class_oop = JNIHandles::resolve(from); | |
702 klassOop from_class = (from_class_oop == NULL) | |
703 ? (klassOop)NULL | |
704 : java_lang_Class::as_klassOop(from_class_oop); | |
705 oop class_loader = NULL; | |
706 oop protection_domain = NULL; | |
707 if (from_class != NULL) { | |
708 class_loader = Klass::cast(from_class)->class_loader(); | |
709 protection_domain = Klass::cast(from_class)->protection_domain(); | |
710 } | |
711 Handle h_loader(THREAD, class_loader); | |
712 Handle h_prot (THREAD, protection_domain); | |
713 jclass result = find_class_from_class_loader(env, h_name, init, h_loader, | |
714 h_prot, true, thread); | |
715 | |
716 if (TraceClassResolution && result != NULL) { | |
717 // this function is generally only used for class loading during verification. | |
718 ResourceMark rm; | |
719 oop from_mirror = JNIHandles::resolve_non_null(from); | |
720 klassOop from_class = java_lang_Class::as_klassOop(from_mirror); | |
721 const char * from_name = Klass::cast(from_class)->external_name(); | |
722 | |
723 oop mirror = JNIHandles::resolve_non_null(result); | |
724 klassOop to_class = java_lang_Class::as_klassOop(mirror); | |
725 const char * to = Klass::cast(to_class)->external_name(); | |
726 tty->print("RESOLVE %s %s (verification)\n", from_name, to); | |
727 } | |
728 | |
729 return result; | |
730 JVM_END | |
731 | |
732 static void is_lock_held_by_thread(Handle loader, PerfCounter* counter, TRAPS) { | |
733 if (loader.is_null()) { | |
734 return; | |
735 } | |
736 | |
737 // check whether the current caller thread holds the lock or not. | |
738 // If not, increment the corresponding counter | |
739 if (ObjectSynchronizer::query_lock_ownership((JavaThread*)THREAD, loader) != | |
740 ObjectSynchronizer::owner_self) { | |
741 counter->inc(); | |
742 } | |
743 } | |
744 | |
745 // common code for JVM_DefineClass() and JVM_DefineClassWithSource() | |
746 static jclass jvm_define_class_common(JNIEnv *env, const char *name, jobject loader, const jbyte *buf, jsize len, jobject pd, const char *source, TRAPS) { | |
431
a45484ea312d
6653858: dynamic languages need to be able to load anonymous classes
jrose
parents:
388
diff
changeset
|
747 if (source == NULL) source = "__JVM_DefineClass__"; |
0 | 748 |
749 // Since exceptions can be thrown, class initialization can take place | |
750 // if name is NULL no check for class name in .class stream has to be made. | |
751 symbolHandle class_name; | |
752 if (name != NULL) { | |
753 const int str_len = (int)strlen(name); | |
754 if (str_len > symbolOopDesc::max_length()) { | |
755 // It's impossible to create this class; the name cannot fit | |
756 // into the constant pool. | |
757 THROW_MSG_0(vmSymbols::java_lang_NoClassDefFoundError(), name); | |
758 } | |
759 class_name = oopFactory::new_symbol_handle(name, str_len, CHECK_NULL); | |
760 } | |
761 | |
762 ResourceMark rm(THREAD); | |
763 ClassFileStream st((u1*) buf, len, (char *)source); | |
764 Handle class_loader (THREAD, JNIHandles::resolve(loader)); | |
765 if (UsePerfData) { | |
766 is_lock_held_by_thread(class_loader, | |
767 ClassLoader::sync_JVMDefineClassLockFreeCounter(), | |
768 THREAD); | |
769 } | |
770 Handle protection_domain (THREAD, JNIHandles::resolve(pd)); | |
771 klassOop k = SystemDictionary::resolve_from_stream(class_name, class_loader, | |
772 protection_domain, &st, | |
773 CHECK_NULL); | |
774 | |
775 if (TraceClassResolution && k != NULL) { | |
776 trace_class_resolution(k); | |
777 } | |
778 | |
779 return (jclass) JNIHandles::make_local(env, Klass::cast(k)->java_mirror()); | |
780 } | |
781 | |
782 | |
783 JVM_ENTRY(jclass, JVM_DefineClass(JNIEnv *env, const char *name, jobject loader, const jbyte *buf, jsize len, jobject pd)) | |
784 JVMWrapper2("JVM_DefineClass %s", name); | |
785 | |
431
a45484ea312d
6653858: dynamic languages need to be able to load anonymous classes
jrose
parents:
388
diff
changeset
|
786 return jvm_define_class_common(env, name, loader, buf, len, pd, NULL, THREAD); |
0 | 787 JVM_END |
788 | |
789 | |
790 JVM_ENTRY(jclass, JVM_DefineClassWithSource(JNIEnv *env, const char *name, jobject loader, const jbyte *buf, jsize len, jobject pd, const char *source)) | |
791 JVMWrapper2("JVM_DefineClassWithSource %s", name); | |
792 | |
793 return jvm_define_class_common(env, name, loader, buf, len, pd, source, THREAD); | |
794 JVM_END | |
795 | |
796 | |
797 JVM_ENTRY(jclass, JVM_FindLoadedClass(JNIEnv *env, jobject loader, jstring name)) | |
798 JVMWrapper("JVM_FindLoadedClass"); | |
799 ResourceMark rm(THREAD); | |
800 | |
801 Handle h_name (THREAD, JNIHandles::resolve_non_null(name)); | |
802 Handle string = java_lang_String::internalize_classname(h_name, CHECK_NULL); | |
803 | |
804 const char* str = java_lang_String::as_utf8_string(string()); | |
805 // Sanity check, don't expect null | |
806 if (str == NULL) return NULL; | |
807 | |
808 const int str_len = (int)strlen(str); | |
809 if (str_len > symbolOopDesc::max_length()) { | |
810 // It's impossible to create this class; the name cannot fit | |
811 // into the constant pool. | |
812 return NULL; | |
813 } | |
814 symbolHandle klass_name = oopFactory::new_symbol_handle(str, str_len,CHECK_NULL); | |
815 | |
816 // Security Note: | |
817 // The Java level wrapper will perform the necessary security check allowing | |
818 // us to pass the NULL as the initiating class loader. | |
819 Handle h_loader(THREAD, JNIHandles::resolve(loader)); | |
820 if (UsePerfData) { | |
821 is_lock_held_by_thread(h_loader, | |
822 ClassLoader::sync_JVMFindLoadedClassLockFreeCounter(), | |
823 THREAD); | |
824 } | |
825 | |
826 klassOop k = SystemDictionary::find_instance_or_array_klass(klass_name, | |
827 h_loader, | |
828 Handle(), | |
829 CHECK_NULL); | |
830 | |
831 return (k == NULL) ? NULL : | |
832 (jclass) JNIHandles::make_local(env, Klass::cast(k)->java_mirror()); | |
833 JVM_END | |
834 | |
835 | |
836 // Reflection support ////////////////////////////////////////////////////////////////////////////// | |
837 | |
838 JVM_ENTRY(jstring, JVM_GetClassName(JNIEnv *env, jclass cls)) | |
839 assert (cls != NULL, "illegal class"); | |
840 JVMWrapper("JVM_GetClassName"); | |
841 JvmtiVMObjectAllocEventCollector oam; | |
842 ResourceMark rm(THREAD); | |
843 const char* name; | |
844 if (java_lang_Class::is_primitive(JNIHandles::resolve(cls))) { | |
845 name = type2name(java_lang_Class::primitive_type(JNIHandles::resolve(cls))); | |
846 } else { | |
847 // Consider caching interned string in Klass | |
848 klassOop k = java_lang_Class::as_klassOop(JNIHandles::resolve(cls)); | |
849 assert(k->is_klass(), "just checking"); | |
850 name = Klass::cast(k)->external_name(); | |
851 } | |
852 oop result = StringTable::intern((char*) name, CHECK_NULL); | |
853 return (jstring) JNIHandles::make_local(env, result); | |
854 JVM_END | |
855 | |
856 | |
857 JVM_ENTRY(jobjectArray, JVM_GetClassInterfaces(JNIEnv *env, jclass cls)) | |
858 JVMWrapper("JVM_GetClassInterfaces"); | |
859 JvmtiVMObjectAllocEventCollector oam; | |
860 oop mirror = JNIHandles::resolve_non_null(cls); | |
861 | |
862 // Special handling for primitive objects | |
863 if (java_lang_Class::is_primitive(mirror)) { | |
864 // Primitive objects does not have any interfaces | |
865 objArrayOop r = oopFactory::new_objArray(SystemDictionary::class_klass(), 0, CHECK_NULL); | |
866 return (jobjectArray) JNIHandles::make_local(env, r); | |
867 } | |
868 | |
869 KlassHandle klass(thread, java_lang_Class::as_klassOop(mirror)); | |
870 // Figure size of result array | |
871 int size; | |
872 if (klass->oop_is_instance()) { | |
873 size = instanceKlass::cast(klass())->local_interfaces()->length(); | |
874 } else { | |
875 assert(klass->oop_is_objArray() || klass->oop_is_typeArray(), "Illegal mirror klass"); | |
876 size = 2; | |
877 } | |
878 | |
879 // Allocate result array | |
880 objArrayOop r = oopFactory::new_objArray(SystemDictionary::class_klass(), size, CHECK_NULL); | |
881 objArrayHandle result (THREAD, r); | |
882 // Fill in result | |
883 if (klass->oop_is_instance()) { | |
884 // Regular instance klass, fill in all local interfaces | |
885 for (int index = 0; index < size; index++) { | |
886 klassOop k = klassOop(instanceKlass::cast(klass())->local_interfaces()->obj_at(index)); | |
887 result->obj_at_put(index, Klass::cast(k)->java_mirror()); | |
888 } | |
889 } else { | |
890 // All arrays implement java.lang.Cloneable and java.io.Serializable | |
891 result->obj_at_put(0, Klass::cast(SystemDictionary::cloneable_klass())->java_mirror()); | |
892 result->obj_at_put(1, Klass::cast(SystemDictionary::serializable_klass())->java_mirror()); | |
893 } | |
894 return (jobjectArray) JNIHandles::make_local(env, result()); | |
895 JVM_END | |
896 | |
897 | |
898 JVM_ENTRY(jobject, JVM_GetClassLoader(JNIEnv *env, jclass cls)) | |
899 JVMWrapper("JVM_GetClassLoader"); | |
900 if (java_lang_Class::is_primitive(JNIHandles::resolve_non_null(cls))) { | |
901 return NULL; | |
902 } | |
903 klassOop k = java_lang_Class::as_klassOop(JNIHandles::resolve_non_null(cls)); | |
904 oop loader = Klass::cast(k)->class_loader(); | |
905 return JNIHandles::make_local(env, loader); | |
906 JVM_END | |
907 | |
908 | |
909 JVM_QUICK_ENTRY(jboolean, JVM_IsInterface(JNIEnv *env, jclass cls)) | |
910 JVMWrapper("JVM_IsInterface"); | |
911 oop mirror = JNIHandles::resolve_non_null(cls); | |
912 if (java_lang_Class::is_primitive(mirror)) { | |
913 return JNI_FALSE; | |
914 } | |
915 klassOop k = java_lang_Class::as_klassOop(mirror); | |
916 jboolean result = Klass::cast(k)->is_interface(); | |
917 assert(!result || Klass::cast(k)->oop_is_instance(), | |
918 "all interfaces are instance types"); | |
919 // The compiler intrinsic for isInterface tests the | |
920 // Klass::_access_flags bits in the same way. | |
921 return result; | |
922 JVM_END | |
923 | |
924 | |
925 JVM_ENTRY(jobjectArray, JVM_GetClassSigners(JNIEnv *env, jclass cls)) | |
926 JVMWrapper("JVM_GetClassSigners"); | |
927 JvmtiVMObjectAllocEventCollector oam; | |
928 if (java_lang_Class::is_primitive(JNIHandles::resolve_non_null(cls))) { | |
929 // There are no signers for primitive types | |
930 return NULL; | |
931 } | |
932 | |
933 klassOop k = java_lang_Class::as_klassOop(JNIHandles::resolve_non_null(cls)); | |
934 objArrayOop signers = NULL; | |
935 if (Klass::cast(k)->oop_is_instance()) { | |
936 signers = instanceKlass::cast(k)->signers(); | |
937 } | |
938 | |
939 // If there are no signers set in the class, or if the class | |
940 // is an array, return NULL. | |
941 if (signers == NULL) return NULL; | |
942 | |
943 // copy of the signers array | |
944 klassOop element = objArrayKlass::cast(signers->klass())->element_klass(); | |
945 objArrayOop signers_copy = oopFactory::new_objArray(element, signers->length(), CHECK_NULL); | |
946 for (int index = 0; index < signers->length(); index++) { | |
947 signers_copy->obj_at_put(index, signers->obj_at(index)); | |
948 } | |
949 | |
950 // return the copy | |
951 return (jobjectArray) JNIHandles::make_local(env, signers_copy); | |
952 JVM_END | |
953 | |
954 | |
955 JVM_ENTRY(void, JVM_SetClassSigners(JNIEnv *env, jclass cls, jobjectArray signers)) | |
956 JVMWrapper("JVM_SetClassSigners"); | |
957 if (!java_lang_Class::is_primitive(JNIHandles::resolve_non_null(cls))) { | |
958 // This call is ignored for primitive types and arrays. | |
959 // Signers are only set once, ClassLoader.java, and thus shouldn't | |
960 // be called with an array. Only the bootstrap loader creates arrays. | |
961 klassOop k = java_lang_Class::as_klassOop(JNIHandles::resolve_non_null(cls)); | |
962 if (Klass::cast(k)->oop_is_instance()) { | |
963 instanceKlass::cast(k)->set_signers(objArrayOop(JNIHandles::resolve(signers))); | |
964 } | |
965 } | |
966 JVM_END | |
967 | |
968 | |
969 JVM_ENTRY(jobject, JVM_GetProtectionDomain(JNIEnv *env, jclass cls)) | |
970 JVMWrapper("JVM_GetProtectionDomain"); | |
971 if (JNIHandles::resolve(cls) == NULL) { | |
972 THROW_(vmSymbols::java_lang_NullPointerException(), NULL); | |
973 } | |
974 | |
975 if (java_lang_Class::is_primitive(JNIHandles::resolve(cls))) { | |
976 // Primitive types does not have a protection domain. | |
977 return NULL; | |
978 } | |
979 | |
980 klassOop k = java_lang_Class::as_klassOop(JNIHandles::resolve(cls)); | |
981 return (jobject) JNIHandles::make_local(env, Klass::cast(k)->protection_domain()); | |
982 JVM_END | |
983 | |
984 | |
985 // Obsolete since 1.2 (Class.setProtectionDomain removed), although | |
986 // still defined in core libraries as of 1.5. | |
987 JVM_ENTRY(void, JVM_SetProtectionDomain(JNIEnv *env, jclass cls, jobject protection_domain)) | |
988 JVMWrapper("JVM_SetProtectionDomain"); | |
989 if (JNIHandles::resolve(cls) == NULL) { | |
990 THROW(vmSymbols::java_lang_NullPointerException()); | |
991 } | |
992 if (!java_lang_Class::is_primitive(JNIHandles::resolve(cls))) { | |
993 // Call is ignored for primitive types | |
994 klassOop k = java_lang_Class::as_klassOop(JNIHandles::resolve(cls)); | |
995 | |
996 // cls won't be an array, as this called only from ClassLoader.defineClass | |
997 if (Klass::cast(k)->oop_is_instance()) { | |
998 oop pd = JNIHandles::resolve(protection_domain); | |
999 assert(pd == NULL || pd->is_oop(), "just checking"); | |
1000 instanceKlass::cast(k)->set_protection_domain(pd); | |
1001 } | |
1002 } | |
1003 JVM_END | |
1004 | |
1005 | |
1006 JVM_ENTRY(jobject, JVM_DoPrivileged(JNIEnv *env, jclass cls, jobject action, jobject context, jboolean wrapException)) | |
1007 JVMWrapper("JVM_DoPrivileged"); | |
1008 | |
1009 if (action == NULL) { | |
1010 THROW_MSG_0(vmSymbols::java_lang_NullPointerException(), "Null action"); | |
1011 } | |
1012 | |
1013 // Stack allocated list of privileged stack elements | |
1014 PrivilegedElement pi; | |
1015 | |
1016 // Check that action object understands "Object run()" | |
1017 Handle object (THREAD, JNIHandles::resolve(action)); | |
1018 | |
1019 // get run() method | |
1020 methodOop m_oop = Klass::cast(object->klass())->uncached_lookup_method( | |
1021 vmSymbols::run_method_name(), | |
1022 vmSymbols::void_object_signature()); | |
1023 methodHandle m (THREAD, m_oop); | |
1024 if (m.is_null() || !m->is_method() || !methodOop(m())->is_public() || methodOop(m())->is_static()) { | |
1025 THROW_MSG_0(vmSymbols::java_lang_InternalError(), "No run method"); | |
1026 } | |
1027 | |
1028 // Compute the frame initiating the do privileged operation and setup the privileged stack | |
1029 vframeStream vfst(thread); | |
1030 vfst.security_get_caller_frame(1); | |
1031 | |
1032 if (!vfst.at_end()) { | |
1033 pi.initialize(&vfst, JNIHandles::resolve(context), thread->privileged_stack_top(), CHECK_NULL); | |
1034 thread->set_privileged_stack_top(&pi); | |
1035 } | |
1036 | |
1037 | |
1038 // invoke the Object run() in the action object. We cannot use call_interface here, since the static type | |
1039 // is not really known - it is either java.security.PrivilegedAction or java.security.PrivilegedExceptionAction | |
1040 Handle pending_exception; | |
1041 JavaValue result(T_OBJECT); | |
1042 JavaCallArguments args(object); | |
1043 JavaCalls::call(&result, m, &args, THREAD); | |
1044 | |
1045 // done with action, remove ourselves from the list | |
1046 if (!vfst.at_end()) { | |
1047 assert(thread->privileged_stack_top() != NULL && thread->privileged_stack_top() == &pi, "wrong top element"); | |
1048 thread->set_privileged_stack_top(thread->privileged_stack_top()->next()); | |
1049 } | |
1050 | |
1051 if (HAS_PENDING_EXCEPTION) { | |
1052 pending_exception = Handle(THREAD, PENDING_EXCEPTION); | |
1053 CLEAR_PENDING_EXCEPTION; | |
1054 | |
1055 if ( pending_exception->is_a(SystemDictionary::exception_klass()) && | |
1056 !pending_exception->is_a(SystemDictionary::runtime_exception_klass())) { | |
1057 // Throw a java.security.PrivilegedActionException(Exception e) exception | |
1058 JavaCallArguments args(pending_exception); | |
1059 THROW_ARG_0(vmSymbolHandles::java_security_PrivilegedActionException(), | |
1060 vmSymbolHandles::exception_void_signature(), | |
1061 &args); | |
1062 } | |
1063 } | |
1064 | |
1065 if (pending_exception.not_null()) THROW_OOP_0(pending_exception()); | |
1066 return JNIHandles::make_local(env, (oop) result.get_jobject()); | |
1067 JVM_END | |
1068 | |
1069 | |
1070 // Returns the inherited_access_control_context field of the running thread. | |
1071 JVM_ENTRY(jobject, JVM_GetInheritedAccessControlContext(JNIEnv *env, jclass cls)) | |
1072 JVMWrapper("JVM_GetInheritedAccessControlContext"); | |
1073 oop result = java_lang_Thread::inherited_access_control_context(thread->threadObj()); | |
1074 return JNIHandles::make_local(env, result); | |
1075 JVM_END | |
1076 | |
1077 class RegisterArrayForGC { | |
1078 private: | |
1079 JavaThread *_thread; | |
1080 public: | |
1081 RegisterArrayForGC(JavaThread *thread, GrowableArray<oop>* array) { | |
1082 _thread = thread; | |
1083 _thread->register_array_for_gc(array); | |
1084 } | |
1085 | |
1086 ~RegisterArrayForGC() { | |
1087 _thread->register_array_for_gc(NULL); | |
1088 } | |
1089 }; | |
1090 | |
1091 | |
1092 JVM_ENTRY(jobject, JVM_GetStackAccessControlContext(JNIEnv *env, jclass cls)) | |
1093 JVMWrapper("JVM_GetStackAccessControlContext"); | |
1094 if (!UsePrivilegedStack) return NULL; | |
1095 | |
1096 ResourceMark rm(THREAD); | |
1097 GrowableArray<oop>* local_array = new GrowableArray<oop>(12); | |
1098 JvmtiVMObjectAllocEventCollector oam; | |
1099 | |
1100 // count the protection domains on the execution stack. We collapse | |
1101 // duplicate consecutive protection domains into a single one, as | |
1102 // well as stopping when we hit a privileged frame. | |
1103 | |
1104 // Use vframeStream to iterate through Java frames | |
1105 vframeStream vfst(thread); | |
1106 | |
1107 oop previous_protection_domain = NULL; | |
1108 Handle privileged_context(thread, NULL); | |
1109 bool is_privileged = false; | |
1110 oop protection_domain = NULL; | |
1111 | |
1112 for(; !vfst.at_end(); vfst.next()) { | |
1113 // get method of frame | |
1114 methodOop method = vfst.method(); | |
1115 intptr_t* frame_id = vfst.frame_id(); | |
1116 | |
1117 // check the privileged frames to see if we have a match | |
1118 if (thread->privileged_stack_top() && thread->privileged_stack_top()->frame_id() == frame_id) { | |
1119 // this frame is privileged | |
1120 is_privileged = true; | |
1121 privileged_context = Handle(thread, thread->privileged_stack_top()->privileged_context()); | |
1122 protection_domain = thread->privileged_stack_top()->protection_domain(); | |
1123 } else { | |
1124 protection_domain = instanceKlass::cast(method->method_holder())->protection_domain(); | |
1125 } | |
1126 | |
1127 if ((previous_protection_domain != protection_domain) && (protection_domain != NULL)) { | |
1128 local_array->push(protection_domain); | |
1129 previous_protection_domain = protection_domain; | |
1130 } | |
1131 | |
1132 if (is_privileged) break; | |
1133 } | |
1134 | |
1135 | |
1136 // either all the domains on the stack were system domains, or | |
1137 // we had a privileged system domain | |
1138 if (local_array->is_empty()) { | |
1139 if (is_privileged && privileged_context.is_null()) return NULL; | |
1140 | |
1141 oop result = java_security_AccessControlContext::create(objArrayHandle(), is_privileged, privileged_context, CHECK_NULL); | |
1142 return JNIHandles::make_local(env, result); | |
1143 } | |
1144 | |
1145 // the resource area must be registered in case of a gc | |
1146 RegisterArrayForGC ragc(thread, local_array); | |
1147 objArrayOop context = oopFactory::new_objArray(SystemDictionary::protectionDomain_klass(), | |
1148 local_array->length(), CHECK_NULL); | |
1149 objArrayHandle h_context(thread, context); | |
1150 for (int index = 0; index < local_array->length(); index++) { | |
1151 h_context->obj_at_put(index, local_array->at(index)); | |
1152 } | |
1153 | |
1154 oop result = java_security_AccessControlContext::create(h_context, is_privileged, privileged_context, CHECK_NULL); | |
1155 | |
1156 return JNIHandles::make_local(env, result); | |
1157 JVM_END | |
1158 | |
1159 | |
1160 JVM_QUICK_ENTRY(jboolean, JVM_IsArrayClass(JNIEnv *env, jclass cls)) | |
1161 JVMWrapper("JVM_IsArrayClass"); | |
1162 klassOop k = java_lang_Class::as_klassOop(JNIHandles::resolve_non_null(cls)); | |
1163 return (k != NULL) && Klass::cast(k)->oop_is_javaArray() ? true : false; | |
1164 JVM_END | |
1165 | |
1166 | |
1167 JVM_QUICK_ENTRY(jboolean, JVM_IsPrimitiveClass(JNIEnv *env, jclass cls)) | |
1168 JVMWrapper("JVM_IsPrimitiveClass"); | |
1169 oop mirror = JNIHandles::resolve_non_null(cls); | |
1170 return (jboolean) java_lang_Class::is_primitive(mirror); | |
1171 JVM_END | |
1172 | |
1173 | |
1174 JVM_ENTRY(jclass, JVM_GetComponentType(JNIEnv *env, jclass cls)) | |
1175 JVMWrapper("JVM_GetComponentType"); | |
1176 oop mirror = JNIHandles::resolve_non_null(cls); | |
1177 oop result = Reflection::array_component_type(mirror, CHECK_NULL); | |
1178 return (jclass) JNIHandles::make_local(env, result); | |
1179 JVM_END | |
1180 | |
1181 | |
1182 JVM_ENTRY(jint, JVM_GetClassModifiers(JNIEnv *env, jclass cls)) | |
1183 JVMWrapper("JVM_GetClassModifiers"); | |
1184 if (java_lang_Class::is_primitive(JNIHandles::resolve_non_null(cls))) { | |
1185 // Primitive type | |
1186 return JVM_ACC_ABSTRACT | JVM_ACC_FINAL | JVM_ACC_PUBLIC; | |
1187 } | |
1188 | |
1189 Klass* k = Klass::cast(java_lang_Class::as_klassOop(JNIHandles::resolve_non_null(cls))); | |
1190 debug_only(int computed_modifiers = k->compute_modifier_flags(CHECK_0)); | |
1191 assert(k->modifier_flags() == computed_modifiers, "modifiers cache is OK"); | |
1192 return k->modifier_flags(); | |
1193 JVM_END | |
1194 | |
1195 | |
1196 // Inner class reflection /////////////////////////////////////////////////////////////////////////////// | |
1197 | |
1198 JVM_ENTRY(jobjectArray, JVM_GetDeclaredClasses(JNIEnv *env, jclass ofClass)) | |
1199 const int inner_class_info_index = 0; | |
1200 const int outer_class_info_index = 1; | |
1201 | |
1202 JvmtiVMObjectAllocEventCollector oam; | |
1203 // ofClass is a reference to a java_lang_Class object. The mirror object | |
1204 // of an instanceKlass | |
1205 | |
1206 if (java_lang_Class::is_primitive(JNIHandles::resolve_non_null(ofClass)) || | |
1207 ! Klass::cast(java_lang_Class::as_klassOop(JNIHandles::resolve_non_null(ofClass)))->oop_is_instance()) { | |
1208 oop result = oopFactory::new_objArray(SystemDictionary::class_klass(), 0, CHECK_NULL); | |
1209 return (jobjectArray)JNIHandles::make_local(env, result); | |
1210 } | |
1211 | |
1212 instanceKlassHandle k(thread, java_lang_Class::as_klassOop(JNIHandles::resolve_non_null(ofClass))); | |
1213 | |
1214 if (k->inner_classes()->length() == 0) { | |
1215 // Neither an inner nor outer class | |
1216 oop result = oopFactory::new_objArray(SystemDictionary::class_klass(), 0, CHECK_NULL); | |
1217 return (jobjectArray)JNIHandles::make_local(env, result); | |
1218 } | |
1219 | |
1220 // find inner class info | |
1221 typeArrayHandle icls(thread, k->inner_classes()); | |
1222 constantPoolHandle cp(thread, k->constants()); | |
1223 int length = icls->length(); | |
1224 | |
1225 // Allocate temp. result array | |
1226 objArrayOop r = oopFactory::new_objArray(SystemDictionary::class_klass(), length/4, CHECK_NULL); | |
1227 objArrayHandle result (THREAD, r); | |
1228 int members = 0; | |
1229 | |
1230 for(int i = 0; i < length; i += 4) { | |
1231 int ioff = icls->ushort_at(i + inner_class_info_index); | |
1232 int ooff = icls->ushort_at(i + outer_class_info_index); | |
1233 | |
1234 if (ioff != 0 && ooff != 0) { | |
1235 // Check to see if the name matches the class we're looking for | |
1236 // before attempting to find the class. | |
1237 if (cp->klass_name_at_matches(k, ooff)) { | |
1238 klassOop outer_klass = cp->klass_at(ooff, CHECK_NULL); | |
1239 if (outer_klass == k()) { | |
1240 klassOop ik = cp->klass_at(ioff, CHECK_NULL); | |
1241 instanceKlassHandle inner_klass (THREAD, ik); | |
1242 | |
1243 // Throws an exception if outer klass has not declared k as | |
1244 // an inner klass | |
1245 Reflection::check_for_inner_class(k, inner_klass, CHECK_NULL); | |
1246 | |
1247 result->obj_at_put(members, inner_klass->java_mirror()); | |
1248 members++; | |
1249 } | |
1250 } | |
1251 } | |
1252 } | |
1253 | |
1254 if (members != length) { | |
1255 // Return array of right length | |
1256 objArrayOop res = oopFactory::new_objArray(SystemDictionary::class_klass(), members, CHECK_NULL); | |
1257 for(int i = 0; i < members; i++) { | |
1258 res->obj_at_put(i, result->obj_at(i)); | |
1259 } | |
1260 return (jobjectArray)JNIHandles::make_local(env, res); | |
1261 } | |
1262 | |
1263 return (jobjectArray)JNIHandles::make_local(env, result()); | |
1264 JVM_END | |
1265 | |
1266 | |
1267 JVM_ENTRY(jclass, JVM_GetDeclaringClass(JNIEnv *env, jclass ofClass)) | |
1268 const int inner_class_info_index = 0; | |
1269 const int outer_class_info_index = 1; | |
1270 | |
1271 // ofClass is a reference to a java_lang_Class object. | |
1272 if (java_lang_Class::is_primitive(JNIHandles::resolve_non_null(ofClass)) || | |
1273 ! Klass::cast(java_lang_Class::as_klassOop(JNIHandles::resolve_non_null(ofClass)))->oop_is_instance()) { | |
1274 return NULL; | |
1275 } | |
1276 | |
1277 instanceKlassHandle k(thread, java_lang_Class::as_klassOop(JNIHandles::resolve_non_null(ofClass))); | |
1278 | |
1279 if (k->inner_classes()->length() == 0) { | |
1280 // No inner class info => no declaring class | |
1281 return NULL; | |
1282 } | |
1283 | |
1284 typeArrayHandle i_icls(thread, k->inner_classes()); | |
1285 constantPoolHandle i_cp(thread, k->constants()); | |
1286 int i_length = i_icls->length(); | |
1287 | |
1288 bool found = false; | |
1289 klassOop ok; | |
1290 instanceKlassHandle outer_klass; | |
1291 | |
1292 // Find inner_klass attribute | |
1293 for(int i = 0; i < i_length && !found; i+= 4) { | |
1294 int ioff = i_icls->ushort_at(i + inner_class_info_index); | |
1295 int ooff = i_icls->ushort_at(i + outer_class_info_index); | |
1296 | |
1297 if (ioff != 0 && ooff != 0) { | |
1298 // Check to see if the name matches the class we're looking for | |
1299 // before attempting to find the class. | |
1300 if (i_cp->klass_name_at_matches(k, ioff)) { | |
1301 klassOop inner_klass = i_cp->klass_at(ioff, CHECK_NULL); | |
1302 if (k() == inner_klass) { | |
1303 found = true; | |
1304 ok = i_cp->klass_at(ooff, CHECK_NULL); | |
1305 outer_klass = instanceKlassHandle(thread, ok); | |
1306 } | |
1307 } | |
1308 } | |
1309 } | |
1310 | |
1311 // If no inner class attribute found for this class. | |
1312 if (!found) return NULL; | |
1313 | |
1314 // Throws an exception if outer klass has not declared k as an inner klass | |
1315 Reflection::check_for_inner_class(outer_klass, k, CHECK_NULL); | |
1316 | |
1317 return (jclass)JNIHandles::make_local(env, outer_klass->java_mirror()); | |
1318 JVM_END | |
1319 | |
1320 | |
1321 JVM_ENTRY(jstring, JVM_GetClassSignature(JNIEnv *env, jclass cls)) | |
1322 assert (cls != NULL, "illegal class"); | |
1323 JVMWrapper("JVM_GetClassSignature"); | |
1324 JvmtiVMObjectAllocEventCollector oam; | |
1325 ResourceMark rm(THREAD); | |
1326 // Return null for arrays and primatives | |
1327 if (!java_lang_Class::is_primitive(JNIHandles::resolve(cls))) { | |
1328 klassOop k = java_lang_Class::as_klassOop(JNIHandles::resolve(cls)); | |
1329 if (Klass::cast(k)->oop_is_instance()) { | |
1330 symbolHandle sym = symbolHandle(THREAD, instanceKlass::cast(k)->generic_signature()); | |
1331 if (sym.is_null()) return NULL; | |
1332 Handle str = java_lang_String::create_from_symbol(sym, CHECK_NULL); | |
1333 return (jstring) JNIHandles::make_local(env, str()); | |
1334 } | |
1335 } | |
1336 return NULL; | |
1337 JVM_END | |
1338 | |
1339 | |
1340 JVM_ENTRY(jbyteArray, JVM_GetClassAnnotations(JNIEnv *env, jclass cls)) | |
1341 assert (cls != NULL, "illegal class"); | |
1342 JVMWrapper("JVM_GetClassAnnotations"); | |
1343 ResourceMark rm(THREAD); | |
1344 // Return null for arrays and primitives | |
1345 if (!java_lang_Class::is_primitive(JNIHandles::resolve(cls))) { | |
1346 klassOop k = java_lang_Class::as_klassOop(JNIHandles::resolve(cls)); | |
1347 if (Klass::cast(k)->oop_is_instance()) { | |
1348 return (jbyteArray) JNIHandles::make_local(env, | |
1349 instanceKlass::cast(k)->class_annotations()); | |
1350 } | |
1351 } | |
1352 return NULL; | |
1353 JVM_END | |
1354 | |
1355 | |
1356 JVM_ENTRY(jbyteArray, JVM_GetFieldAnnotations(JNIEnv *env, jobject field)) | |
1357 assert(field != NULL, "illegal field"); | |
1358 JVMWrapper("JVM_GetFieldAnnotations"); | |
1359 | |
1360 // some of this code was adapted from from jni_FromReflectedField | |
1361 | |
1362 // field is a handle to a java.lang.reflect.Field object | |
1363 oop reflected = JNIHandles::resolve_non_null(field); | |
1364 oop mirror = java_lang_reflect_Field::clazz(reflected); | |
1365 klassOop k = java_lang_Class::as_klassOop(mirror); | |
1366 int slot = java_lang_reflect_Field::slot(reflected); | |
1367 int modifiers = java_lang_reflect_Field::modifiers(reflected); | |
1368 | |
1369 fieldDescriptor fd; | |
1370 KlassHandle kh(THREAD, k); | |
1371 intptr_t offset = instanceKlass::cast(kh())->offset_from_fields(slot); | |
1372 | |
1373 if (modifiers & JVM_ACC_STATIC) { | |
1374 // for static fields we only look in the current class | |
1375 if (!instanceKlass::cast(kh())->find_local_field_from_offset(offset, | |
1376 true, &fd)) { | |
1377 assert(false, "cannot find static field"); | |
1378 return NULL; // robustness | |
1379 } | |
1380 } else { | |
1381 // for instance fields we start with the current class and work | |
1382 // our way up through the superclass chain | |
1383 if (!instanceKlass::cast(kh())->find_field_from_offset(offset, false, | |
1384 &fd)) { | |
1385 assert(false, "cannot find instance field"); | |
1386 return NULL; // robustness | |
1387 } | |
1388 } | |
1389 | |
1390 return (jbyteArray) JNIHandles::make_local(env, fd.annotations()); | |
1391 JVM_END | |
1392 | |
1393 | |
1394 static methodOop jvm_get_method_common(jobject method, TRAPS) { | |
1395 // some of this code was adapted from from jni_FromReflectedMethod | |
1396 | |
1397 oop reflected = JNIHandles::resolve_non_null(method); | |
1398 oop mirror = NULL; | |
1399 int slot = 0; | |
1400 | |
1401 if (reflected->klass() == SystemDictionary::reflect_constructor_klass()) { | |
1402 mirror = java_lang_reflect_Constructor::clazz(reflected); | |
1403 slot = java_lang_reflect_Constructor::slot(reflected); | |
1404 } else { | |
1405 assert(reflected->klass() == SystemDictionary::reflect_method_klass(), | |
1406 "wrong type"); | |
1407 mirror = java_lang_reflect_Method::clazz(reflected); | |
1408 slot = java_lang_reflect_Method::slot(reflected); | |
1409 } | |
1410 klassOop k = java_lang_Class::as_klassOop(mirror); | |
1411 | |
1412 KlassHandle kh(THREAD, k); | |
1413 methodOop m = instanceKlass::cast(kh())->method_with_idnum(slot); | |
1414 if (m == NULL) { | |
1415 assert(false, "cannot find method"); | |
1416 return NULL; // robustness | |
1417 } | |
1418 | |
1419 return m; | |
1420 } | |
1421 | |
1422 | |
1423 JVM_ENTRY(jbyteArray, JVM_GetMethodAnnotations(JNIEnv *env, jobject method)) | |
1424 JVMWrapper("JVM_GetMethodAnnotations"); | |
1425 | |
1426 // method is a handle to a java.lang.reflect.Method object | |
1427 methodOop m = jvm_get_method_common(method, CHECK_NULL); | |
1428 return (jbyteArray) JNIHandles::make_local(env, m->annotations()); | |
1429 JVM_END | |
1430 | |
1431 | |
1432 JVM_ENTRY(jbyteArray, JVM_GetMethodDefaultAnnotationValue(JNIEnv *env, jobject method)) | |
1433 JVMWrapper("JVM_GetMethodDefaultAnnotationValue"); | |
1434 | |
1435 // method is a handle to a java.lang.reflect.Method object | |
1436 methodOop m = jvm_get_method_common(method, CHECK_NULL); | |
1437 return (jbyteArray) JNIHandles::make_local(env, m->annotation_default()); | |
1438 JVM_END | |
1439 | |
1440 | |
1441 JVM_ENTRY(jbyteArray, JVM_GetMethodParameterAnnotations(JNIEnv *env, jobject method)) | |
1442 JVMWrapper("JVM_GetMethodParameterAnnotations"); | |
1443 | |
1444 // method is a handle to a java.lang.reflect.Method object | |
1445 methodOop m = jvm_get_method_common(method, CHECK_NULL); | |
1446 return (jbyteArray) JNIHandles::make_local(env, m->parameter_annotations()); | |
1447 JVM_END | |
1448 | |
1449 | |
1450 // New (JDK 1.4) reflection implementation ///////////////////////////////////// | |
1451 | |
1452 JVM_ENTRY(jobjectArray, JVM_GetClassDeclaredFields(JNIEnv *env, jclass ofClass, jboolean publicOnly)) | |
1453 { | |
1454 JVMWrapper("JVM_GetClassDeclaredFields"); | |
1455 JvmtiVMObjectAllocEventCollector oam; | |
1456 | |
1457 // Exclude primitive types and array types | |
1458 if (java_lang_Class::is_primitive(JNIHandles::resolve_non_null(ofClass)) || | |
1459 Klass::cast(java_lang_Class::as_klassOop(JNIHandles::resolve_non_null(ofClass)))->oop_is_javaArray()) { | |
1460 // Return empty array | |
1461 oop res = oopFactory::new_objArray(SystemDictionary::reflect_field_klass(), 0, CHECK_NULL); | |
1462 return (jobjectArray) JNIHandles::make_local(env, res); | |
1463 } | |
1464 | |
1465 instanceKlassHandle k(THREAD, java_lang_Class::as_klassOop(JNIHandles::resolve_non_null(ofClass))); | |
1466 constantPoolHandle cp(THREAD, k->constants()); | |
1467 | |
1468 // Ensure class is linked | |
1469 k->link_class(CHECK_NULL); | |
1470 | |
1471 typeArrayHandle fields(THREAD, k->fields()); | |
1472 int fields_len = fields->length(); | |
1473 | |
1474 // 4496456 We need to filter out java.lang.Throwable.backtrace | |
1475 bool skip_backtrace = false; | |
1476 | |
1477 // Allocate result | |
1478 int num_fields; | |
1479 | |
1480 if (publicOnly) { | |
1481 num_fields = 0; | |
1482 for (int i = 0, j = 0; i < fields_len; i += instanceKlass::next_offset, j++) { | |
1483 int mods = fields->ushort_at(i + instanceKlass::access_flags_offset) & JVM_RECOGNIZED_FIELD_MODIFIERS; | |
1484 if (mods & JVM_ACC_PUBLIC) ++num_fields; | |
1485 } | |
1486 } else { | |
1487 num_fields = fields_len / instanceKlass::next_offset; | |
1488 | |
1489 if (k() == SystemDictionary::throwable_klass()) { | |
1490 num_fields--; | |
1491 skip_backtrace = true; | |
1492 } | |
1493 } | |
1494 | |
1495 objArrayOop r = oopFactory::new_objArray(SystemDictionary::reflect_field_klass(), num_fields, CHECK_NULL); | |
1496 objArrayHandle result (THREAD, r); | |
1497 | |
1498 int out_idx = 0; | |
1499 fieldDescriptor fd; | |
1500 for (int i = 0; i < fields_len; i += instanceKlass::next_offset) { | |
1501 if (skip_backtrace) { | |
1502 // 4496456 skip java.lang.Throwable.backtrace | |
1503 int offset = k->offset_from_fields(i); | |
1504 if (offset == java_lang_Throwable::get_backtrace_offset()) continue; | |
1505 } | |
1506 | |
1507 int mods = fields->ushort_at(i + instanceKlass::access_flags_offset) & JVM_RECOGNIZED_FIELD_MODIFIERS; | |
1508 if (!publicOnly || (mods & JVM_ACC_PUBLIC)) { | |
1509 fd.initialize(k(), i); | |
1510 oop field = Reflection::new_field(&fd, UseNewReflection, CHECK_NULL); | |
1511 result->obj_at_put(out_idx, field); | |
1512 ++out_idx; | |
1513 } | |
1514 } | |
1515 assert(out_idx == num_fields, "just checking"); | |
1516 return (jobjectArray) JNIHandles::make_local(env, result()); | |
1517 } | |
1518 JVM_END | |
1519 | |
1520 JVM_ENTRY(jobjectArray, JVM_GetClassDeclaredMethods(JNIEnv *env, jclass ofClass, jboolean publicOnly)) | |
1521 { | |
1522 JVMWrapper("JVM_GetClassDeclaredMethods"); | |
1523 JvmtiVMObjectAllocEventCollector oam; | |
1524 | |
1525 // Exclude primitive types and array types | |
1526 if (java_lang_Class::is_primitive(JNIHandles::resolve_non_null(ofClass)) | |
1527 || Klass::cast(java_lang_Class::as_klassOop(JNIHandles::resolve_non_null(ofClass)))->oop_is_javaArray()) { | |
1528 // Return empty array | |
1529 oop res = oopFactory::new_objArray(SystemDictionary::reflect_method_klass(), 0, CHECK_NULL); | |
1530 return (jobjectArray) JNIHandles::make_local(env, res); | |
1531 } | |
1532 | |
1533 instanceKlassHandle k(THREAD, java_lang_Class::as_klassOop(JNIHandles::resolve_non_null(ofClass))); | |
1534 | |
1535 // Ensure class is linked | |
1536 k->link_class(CHECK_NULL); | |
1537 | |
1538 objArrayHandle methods (THREAD, k->methods()); | |
1539 int methods_length = methods->length(); | |
1540 int num_methods = 0; | |
1541 | |
1542 int i; | |
1543 for (i = 0; i < methods_length; i++) { | |
1544 methodHandle method(THREAD, (methodOop) methods->obj_at(i)); | |
1545 if (!method->is_initializer()) { | |
1546 if (!publicOnly || method->is_public()) { | |
1547 ++num_methods; | |
1548 } | |
1549 } | |
1550 } | |
1551 | |
1552 // Allocate result | |
1553 objArrayOop r = oopFactory::new_objArray(SystemDictionary::reflect_method_klass(), num_methods, CHECK_NULL); | |
1554 objArrayHandle result (THREAD, r); | |
1555 | |
1556 int out_idx = 0; | |
1557 for (i = 0; i < methods_length; i++) { | |
1558 methodHandle method(THREAD, (methodOop) methods->obj_at(i)); | |
1559 if (!method->is_initializer()) { | |
1560 if (!publicOnly || method->is_public()) { | |
1561 oop m = Reflection::new_method(method, UseNewReflection, false, CHECK_NULL); | |
1562 result->obj_at_put(out_idx, m); | |
1563 ++out_idx; | |
1564 } | |
1565 } | |
1566 } | |
1567 assert(out_idx == num_methods, "just checking"); | |
1568 return (jobjectArray) JNIHandles::make_local(env, result()); | |
1569 } | |
1570 JVM_END | |
1571 | |
1572 JVM_ENTRY(jobjectArray, JVM_GetClassDeclaredConstructors(JNIEnv *env, jclass ofClass, jboolean publicOnly)) | |
1573 { | |
1574 JVMWrapper("JVM_GetClassDeclaredConstructors"); | |
1575 JvmtiVMObjectAllocEventCollector oam; | |
1576 | |
1577 // Exclude primitive types and array types | |
1578 if (java_lang_Class::is_primitive(JNIHandles::resolve_non_null(ofClass)) | |
1579 || Klass::cast(java_lang_Class::as_klassOop(JNIHandles::resolve_non_null(ofClass)))->oop_is_javaArray()) { | |
1580 // Return empty array | |
1581 oop res = oopFactory::new_objArray(SystemDictionary::reflect_constructor_klass(), 0 , CHECK_NULL); | |
1582 return (jobjectArray) JNIHandles::make_local(env, res); | |
1583 } | |
1584 | |
1585 instanceKlassHandle k(THREAD, java_lang_Class::as_klassOop(JNIHandles::resolve_non_null(ofClass))); | |
1586 | |
1587 // Ensure class is linked | |
1588 k->link_class(CHECK_NULL); | |
1589 | |
1590 objArrayHandle methods (THREAD, k->methods()); | |
1591 int methods_length = methods->length(); | |
1592 int num_constructors = 0; | |
1593 | |
1594 int i; | |
1595 for (i = 0; i < methods_length; i++) { | |
1596 methodHandle method(THREAD, (methodOop) methods->obj_at(i)); | |
1597 if (method->is_initializer() && !method->is_static()) { | |
1598 if (!publicOnly || method->is_public()) { | |
1599 ++num_constructors; | |
1600 } | |
1601 } | |
1602 } | |
1603 | |
1604 // Allocate result | |
1605 objArrayOop r = oopFactory::new_objArray(SystemDictionary::reflect_constructor_klass(), num_constructors, CHECK_NULL); | |
1606 objArrayHandle result(THREAD, r); | |
1607 | |
1608 int out_idx = 0; | |
1609 for (i = 0; i < methods_length; i++) { | |
1610 methodHandle method(THREAD, (methodOop) methods->obj_at(i)); | |
1611 if (method->is_initializer() && !method->is_static()) { | |
1612 if (!publicOnly || method->is_public()) { | |
1613 oop m = Reflection::new_constructor(method, CHECK_NULL); | |
1614 result->obj_at_put(out_idx, m); | |
1615 ++out_idx; | |
1616 } | |
1617 } | |
1618 } | |
1619 assert(out_idx == num_constructors, "just checking"); | |
1620 return (jobjectArray) JNIHandles::make_local(env, result()); | |
1621 } | |
1622 JVM_END | |
1623 | |
1624 JVM_ENTRY(jint, JVM_GetClassAccessFlags(JNIEnv *env, jclass cls)) | |
1625 { | |
1626 JVMWrapper("JVM_GetClassAccessFlags"); | |
1627 if (java_lang_Class::is_primitive(JNIHandles::resolve_non_null(cls))) { | |
1628 // Primitive type | |
1629 return JVM_ACC_ABSTRACT | JVM_ACC_FINAL | JVM_ACC_PUBLIC; | |
1630 } | |
1631 | |
1632 Klass* k = Klass::cast(java_lang_Class::as_klassOop(JNIHandles::resolve_non_null(cls))); | |
1633 return k->access_flags().as_int() & JVM_ACC_WRITTEN_FLAGS; | |
1634 } | |
1635 JVM_END | |
1636 | |
1637 | |
1638 // Constant pool access ////////////////////////////////////////////////////////// | |
1639 | |
1640 JVM_ENTRY(jobject, JVM_GetClassConstantPool(JNIEnv *env, jclass cls)) | |
1641 { | |
1642 JVMWrapper("JVM_GetClassConstantPool"); | |
1643 JvmtiVMObjectAllocEventCollector oam; | |
1644 | |
1645 // Return null for primitives and arrays | |
1646 if (!java_lang_Class::is_primitive(JNIHandles::resolve_non_null(cls))) { | |
1647 klassOop k = java_lang_Class::as_klassOop(JNIHandles::resolve_non_null(cls)); | |
1648 if (Klass::cast(k)->oop_is_instance()) { | |
1649 instanceKlassHandle k_h(THREAD, k); | |
1650 Handle jcp = sun_reflect_ConstantPool::create(CHECK_NULL); | |
1651 sun_reflect_ConstantPool::set_cp_oop(jcp(), k_h->constants()); | |
1652 return JNIHandles::make_local(jcp()); | |
1653 } | |
1654 } | |
1655 return NULL; | |
1656 } | |
1657 JVM_END | |
1658 | |
1659 | |
1660 JVM_ENTRY(jint, JVM_ConstantPoolGetSize(JNIEnv *env, jobject unused, jobject jcpool)) | |
1661 { | |
1662 JVMWrapper("JVM_ConstantPoolGetSize"); | |
1663 constantPoolHandle cp = constantPoolHandle(THREAD, constantPoolOop(JNIHandles::resolve_non_null(jcpool))); | |
1664 return cp->length(); | |
1665 } | |
1666 JVM_END | |
1667 | |
1668 | |
1669 static void bounds_check(constantPoolHandle cp, jint index, TRAPS) { | |
1670 if (!cp->is_within_bounds(index)) { | |
1671 THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(), "Constant pool index out of bounds"); | |
1672 } | |
1673 } | |
1674 | |
1675 | |
1676 JVM_ENTRY(jclass, JVM_ConstantPoolGetClassAt(JNIEnv *env, jobject unused, jobject jcpool, jint index)) | |
1677 { | |
1678 JVMWrapper("JVM_ConstantPoolGetClassAt"); | |
1679 constantPoolHandle cp = constantPoolHandle(THREAD, constantPoolOop(JNIHandles::resolve_non_null(jcpool))); | |
1680 bounds_check(cp, index, CHECK_NULL); | |
1681 constantTag tag = cp->tag_at(index); | |
1682 if (!tag.is_klass() && !tag.is_unresolved_klass()) { | |
1683 THROW_MSG_0(vmSymbols::java_lang_IllegalArgumentException(), "Wrong type at constant pool index"); | |
1684 } | |
1685 klassOop k = cp->klass_at(index, CHECK_NULL); | |
1686 return (jclass) JNIHandles::make_local(k->klass_part()->java_mirror()); | |
1687 } | |
1688 JVM_END | |
1689 | |
1690 | |
1691 JVM_ENTRY(jclass, JVM_ConstantPoolGetClassAtIfLoaded(JNIEnv *env, jobject unused, jobject jcpool, jint index)) | |
1692 { | |
1693 JVMWrapper("JVM_ConstantPoolGetClassAtIfLoaded"); | |
1694 constantPoolHandle cp = constantPoolHandle(THREAD, constantPoolOop(JNIHandles::resolve_non_null(jcpool))); | |
1695 bounds_check(cp, index, CHECK_NULL); | |
1696 constantTag tag = cp->tag_at(index); | |
1697 if (!tag.is_klass() && !tag.is_unresolved_klass()) { | |
1698 THROW_MSG_0(vmSymbols::java_lang_IllegalArgumentException(), "Wrong type at constant pool index"); | |
1699 } | |
1700 klassOop k = constantPoolOopDesc::klass_at_if_loaded(cp, index); | |
1701 if (k == NULL) return NULL; | |
1702 return (jclass) JNIHandles::make_local(k->klass_part()->java_mirror()); | |
1703 } | |
1704 JVM_END | |
1705 | |
1706 static jobject get_method_at_helper(constantPoolHandle cp, jint index, bool force_resolution, TRAPS) { | |
1707 constantTag tag = cp->tag_at(index); | |
1708 if (!tag.is_method() && !tag.is_interface_method()) { | |
1709 THROW_MSG_0(vmSymbols::java_lang_IllegalArgumentException(), "Wrong type at constant pool index"); | |
1710 } | |
1711 int klass_ref = cp->uncached_klass_ref_index_at(index); | |
1712 klassOop k_o; | |
1713 if (force_resolution) { | |
1714 k_o = cp->klass_at(klass_ref, CHECK_NULL); | |
1715 } else { | |
1716 k_o = constantPoolOopDesc::klass_at_if_loaded(cp, klass_ref); | |
1717 if (k_o == NULL) return NULL; | |
1718 } | |
1719 instanceKlassHandle k(THREAD, k_o); | |
1720 symbolOop name = cp->uncached_name_ref_at(index); | |
1721 symbolOop sig = cp->uncached_signature_ref_at(index); | |
1722 methodHandle m (THREAD, k->find_method(name, sig)); | |
1723 if (m.is_null()) { | |
1724 THROW_MSG_0(vmSymbols::java_lang_RuntimeException(), "Unable to look up method in target class"); | |
1725 } | |
1726 oop method; | |
1727 if (!m->is_initializer() || m->is_static()) { | |
1728 method = Reflection::new_method(m, true, true, CHECK_NULL); | |
1729 } else { | |
1730 method = Reflection::new_constructor(m, CHECK_NULL); | |
1731 } | |
1732 return JNIHandles::make_local(method); | |
1733 } | |
1734 | |
1735 JVM_ENTRY(jobject, JVM_ConstantPoolGetMethodAt(JNIEnv *env, jobject unused, jobject jcpool, jint index)) | |
1736 { | |
1737 JVMWrapper("JVM_ConstantPoolGetMethodAt"); | |
1738 JvmtiVMObjectAllocEventCollector oam; | |
1739 constantPoolHandle cp = constantPoolHandle(THREAD, constantPoolOop(JNIHandles::resolve_non_null(jcpool))); | |
1740 bounds_check(cp, index, CHECK_NULL); | |
1741 jobject res = get_method_at_helper(cp, index, true, CHECK_NULL); | |
1742 return res; | |
1743 } | |
1744 JVM_END | |
1745 | |
1746 JVM_ENTRY(jobject, JVM_ConstantPoolGetMethodAtIfLoaded(JNIEnv *env, jobject unused, jobject jcpool, jint index)) | |
1747 { | |
1748 JVMWrapper("JVM_ConstantPoolGetMethodAtIfLoaded"); | |
1749 JvmtiVMObjectAllocEventCollector oam; | |
1750 constantPoolHandle cp = constantPoolHandle(THREAD, constantPoolOop(JNIHandles::resolve_non_null(jcpool))); | |
1751 bounds_check(cp, index, CHECK_NULL); | |
1752 jobject res = get_method_at_helper(cp, index, false, CHECK_NULL); | |
1753 return res; | |
1754 } | |
1755 JVM_END | |
1756 | |
1757 static jobject get_field_at_helper(constantPoolHandle cp, jint index, bool force_resolution, TRAPS) { | |
1758 constantTag tag = cp->tag_at(index); | |
1759 if (!tag.is_field()) { | |
1760 THROW_MSG_0(vmSymbols::java_lang_IllegalArgumentException(), "Wrong type at constant pool index"); | |
1761 } | |
1762 int klass_ref = cp->uncached_klass_ref_index_at(index); | |
1763 klassOop k_o; | |
1764 if (force_resolution) { | |
1765 k_o = cp->klass_at(klass_ref, CHECK_NULL); | |
1766 } else { | |
1767 k_o = constantPoolOopDesc::klass_at_if_loaded(cp, klass_ref); | |
1768 if (k_o == NULL) return NULL; | |
1769 } | |
1770 instanceKlassHandle k(THREAD, k_o); | |
1771 symbolOop name = cp->uncached_name_ref_at(index); | |
1772 symbolOop sig = cp->uncached_signature_ref_at(index); | |
1773 fieldDescriptor fd; | |
1774 klassOop target_klass = k->find_field(name, sig, &fd); | |
1775 if (target_klass == NULL) { | |
1776 THROW_MSG_0(vmSymbols::java_lang_RuntimeException(), "Unable to look up field in target class"); | |
1777 } | |
1778 oop field = Reflection::new_field(&fd, true, CHECK_NULL); | |
1779 return JNIHandles::make_local(field); | |
1780 } | |
1781 | |
1782 JVM_ENTRY(jobject, JVM_ConstantPoolGetFieldAt(JNIEnv *env, jobject unused, jobject jcpool, jint index)) | |
1783 { | |
1784 JVMWrapper("JVM_ConstantPoolGetFieldAt"); | |
1785 JvmtiVMObjectAllocEventCollector oam; | |
1786 constantPoolHandle cp = constantPoolHandle(THREAD, constantPoolOop(JNIHandles::resolve_non_null(jcpool))); | |
1787 bounds_check(cp, index, CHECK_NULL); | |
1788 jobject res = get_field_at_helper(cp, index, true, CHECK_NULL); | |
1789 return res; | |
1790 } | |
1791 JVM_END | |
1792 | |
1793 JVM_ENTRY(jobject, JVM_ConstantPoolGetFieldAtIfLoaded(JNIEnv *env, jobject unused, jobject jcpool, jint index)) | |
1794 { | |
1795 JVMWrapper("JVM_ConstantPoolGetFieldAtIfLoaded"); | |
1796 JvmtiVMObjectAllocEventCollector oam; | |
1797 constantPoolHandle cp = constantPoolHandle(THREAD, constantPoolOop(JNIHandles::resolve_non_null(jcpool))); | |
1798 bounds_check(cp, index, CHECK_NULL); | |
1799 jobject res = get_field_at_helper(cp, index, false, CHECK_NULL); | |
1800 return res; | |
1801 } | |
1802 JVM_END | |
1803 | |
1804 JVM_ENTRY(jobjectArray, JVM_ConstantPoolGetMemberRefInfoAt(JNIEnv *env, jobject unused, jobject jcpool, jint index)) | |
1805 { | |
1806 JVMWrapper("JVM_ConstantPoolGetMemberRefInfoAt"); | |
1807 JvmtiVMObjectAllocEventCollector oam; | |
1808 constantPoolHandle cp = constantPoolHandle(THREAD, constantPoolOop(JNIHandles::resolve_non_null(jcpool))); | |
1809 bounds_check(cp, index, CHECK_NULL); | |
1810 constantTag tag = cp->tag_at(index); | |
1811 if (!tag.is_field_or_method()) { | |
1812 THROW_MSG_0(vmSymbols::java_lang_IllegalArgumentException(), "Wrong type at constant pool index"); | |
1813 } | |
1814 int klass_ref = cp->uncached_klass_ref_index_at(index); | |
1815 symbolHandle klass_name (THREAD, cp->klass_name_at(klass_ref)); | |
1816 symbolHandle member_name(THREAD, cp->uncached_name_ref_at(index)); | |
1817 symbolHandle member_sig (THREAD, cp->uncached_signature_ref_at(index)); | |
1818 objArrayOop dest_o = oopFactory::new_objArray(SystemDictionary::string_klass(), 3, CHECK_NULL); | |
1819 objArrayHandle dest(THREAD, dest_o); | |
1820 Handle str = java_lang_String::create_from_symbol(klass_name, CHECK_NULL); | |
1821 dest->obj_at_put(0, str()); | |
1822 str = java_lang_String::create_from_symbol(member_name, CHECK_NULL); | |
1823 dest->obj_at_put(1, str()); | |
1824 str = java_lang_String::create_from_symbol(member_sig, CHECK_NULL); | |
1825 dest->obj_at_put(2, str()); | |
1826 return (jobjectArray) JNIHandles::make_local(dest()); | |
1827 } | |
1828 JVM_END | |
1829 | |
1830 JVM_ENTRY(jint, JVM_ConstantPoolGetIntAt(JNIEnv *env, jobject unused, jobject jcpool, jint index)) | |
1831 { | |
1832 JVMWrapper("JVM_ConstantPoolGetIntAt"); | |
1833 constantPoolHandle cp = constantPoolHandle(THREAD, constantPoolOop(JNIHandles::resolve_non_null(jcpool))); | |
1834 bounds_check(cp, index, CHECK_0); | |
1835 constantTag tag = cp->tag_at(index); | |
1836 if (!tag.is_int()) { | |
1837 THROW_MSG_0(vmSymbols::java_lang_IllegalArgumentException(), "Wrong type at constant pool index"); | |
1838 } | |
1839 return cp->int_at(index); | |
1840 } | |
1841 JVM_END | |
1842 | |
1843 JVM_ENTRY(jlong, JVM_ConstantPoolGetLongAt(JNIEnv *env, jobject unused, jobject jcpool, jint index)) | |
1844 { | |
1845 JVMWrapper("JVM_ConstantPoolGetLongAt"); | |
1846 constantPoolHandle cp = constantPoolHandle(THREAD, constantPoolOop(JNIHandles::resolve_non_null(jcpool))); | |
1847 bounds_check(cp, index, CHECK_(0L)); | |
1848 constantTag tag = cp->tag_at(index); | |
1849 if (!tag.is_long()) { | |
1850 THROW_MSG_0(vmSymbols::java_lang_IllegalArgumentException(), "Wrong type at constant pool index"); | |
1851 } | |
1852 return cp->long_at(index); | |
1853 } | |
1854 JVM_END | |
1855 | |
1856 JVM_ENTRY(jfloat, JVM_ConstantPoolGetFloatAt(JNIEnv *env, jobject unused, jobject jcpool, jint index)) | |
1857 { | |
1858 JVMWrapper("JVM_ConstantPoolGetFloatAt"); | |
1859 constantPoolHandle cp = constantPoolHandle(THREAD, constantPoolOop(JNIHandles::resolve_non_null(jcpool))); | |
1860 bounds_check(cp, index, CHECK_(0.0f)); | |
1861 constantTag tag = cp->tag_at(index); | |
1862 if (!tag.is_float()) { | |
1863 THROW_MSG_0(vmSymbols::java_lang_IllegalArgumentException(), "Wrong type at constant pool index"); | |
1864 } | |
1865 return cp->float_at(index); | |
1866 } | |
1867 JVM_END | |
1868 | |
1869 JVM_ENTRY(jdouble, JVM_ConstantPoolGetDoubleAt(JNIEnv *env, jobject unused, jobject jcpool, jint index)) | |
1870 { | |
1871 JVMWrapper("JVM_ConstantPoolGetDoubleAt"); | |
1872 constantPoolHandle cp = constantPoolHandle(THREAD, constantPoolOop(JNIHandles::resolve_non_null(jcpool))); | |
1873 bounds_check(cp, index, CHECK_(0.0)); | |
1874 constantTag tag = cp->tag_at(index); | |
1875 if (!tag.is_double()) { | |
1876 THROW_MSG_0(vmSymbols::java_lang_IllegalArgumentException(), "Wrong type at constant pool index"); | |
1877 } | |
1878 return cp->double_at(index); | |
1879 } | |
1880 JVM_END | |
1881 | |
1882 JVM_ENTRY(jstring, JVM_ConstantPoolGetStringAt(JNIEnv *env, jobject unused, jobject jcpool, jint index)) | |
1883 { | |
1884 JVMWrapper("JVM_ConstantPoolGetStringAt"); | |
1885 constantPoolHandle cp = constantPoolHandle(THREAD, constantPoolOop(JNIHandles::resolve_non_null(jcpool))); | |
1886 bounds_check(cp, index, CHECK_NULL); | |
1887 constantTag tag = cp->tag_at(index); | |
1888 if (!tag.is_string() && !tag.is_unresolved_string()) { | |
1889 THROW_MSG_0(vmSymbols::java_lang_IllegalArgumentException(), "Wrong type at constant pool index"); | |
1890 } | |
1891 oop str = cp->string_at(index, CHECK_NULL); | |
1892 return (jstring) JNIHandles::make_local(str); | |
1893 } | |
1894 JVM_END | |
1895 | |
1896 JVM_ENTRY(jstring, JVM_ConstantPoolGetUTF8At(JNIEnv *env, jobject unused, jobject jcpool, jint index)) | |
1897 { | |
1898 JVMWrapper("JVM_ConstantPoolGetUTF8At"); | |
1899 JvmtiVMObjectAllocEventCollector oam; | |
1900 constantPoolHandle cp = constantPoolHandle(THREAD, constantPoolOop(JNIHandles::resolve_non_null(jcpool))); | |
1901 bounds_check(cp, index, CHECK_NULL); | |
1902 constantTag tag = cp->tag_at(index); | |
1903 if (!tag.is_symbol()) { | |
1904 THROW_MSG_0(vmSymbols::java_lang_IllegalArgumentException(), "Wrong type at constant pool index"); | |
1905 } | |
1906 symbolOop sym_o = cp->symbol_at(index); | |
1907 symbolHandle sym(THREAD, sym_o); | |
1908 Handle str = java_lang_String::create_from_symbol(sym, CHECK_NULL); | |
1909 return (jstring) JNIHandles::make_local(str()); | |
1910 } | |
1911 JVM_END | |
1912 | |
1913 | |
1914 // Assertion support. ////////////////////////////////////////////////////////// | |
1915 | |
1916 JVM_ENTRY(jboolean, JVM_DesiredAssertionStatus(JNIEnv *env, jclass unused, jclass cls)) | |
1917 JVMWrapper("JVM_DesiredAssertionStatus"); | |
1918 assert(cls != NULL, "bad class"); | |
1919 | |
1920 oop r = JNIHandles::resolve(cls); | |
1921 assert(! java_lang_Class::is_primitive(r), "primitive classes not allowed"); | |
1922 if (java_lang_Class::is_primitive(r)) return false; | |
1923 | |
1924 klassOop k = java_lang_Class::as_klassOop(r); | |
1925 assert(Klass::cast(k)->oop_is_instance(), "must be an instance klass"); | |
1926 if (! Klass::cast(k)->oop_is_instance()) return false; | |
1927 | |
1928 ResourceMark rm(THREAD); | |
1929 const char* name = Klass::cast(k)->name()->as_C_string(); | |
1930 bool system_class = Klass::cast(k)->class_loader() == NULL; | |
1931 return JavaAssertions::enabled(name, system_class); | |
1932 | |
1933 JVM_END | |
1934 | |
1935 | |
1936 // Return a new AssertionStatusDirectives object with the fields filled in with | |
1937 // command-line assertion arguments (i.e., -ea, -da). | |
1938 JVM_ENTRY(jobject, JVM_AssertionStatusDirectives(JNIEnv *env, jclass unused)) | |
1939 JVMWrapper("JVM_AssertionStatusDirectives"); | |
1940 JvmtiVMObjectAllocEventCollector oam; | |
1941 oop asd = JavaAssertions::createAssertionStatusDirectives(CHECK_NULL); | |
1942 return JNIHandles::make_local(env, asd); | |
1943 JVM_END | |
1944 | |
1945 // Verification //////////////////////////////////////////////////////////////////////////////// | |
1946 | |
1947 // Reflection for the verifier ///////////////////////////////////////////////////////////////// | |
1948 | |
1949 // RedefineClasses support: bug 6214132 caused verification to fail. | |
1950 // All functions from this section should call the jvmtiThreadSate function: | |
1951 // klassOop class_to_verify_considering_redefinition(klassOop klass). | |
1952 // The function returns a klassOop of the _scratch_class if the verifier | |
1953 // was invoked in the middle of the class redefinition. | |
1954 // Otherwise it returns its argument value which is the _the_class klassOop. | |
1955 // Please, refer to the description in the jvmtiThreadSate.hpp. | |
1956 | |
1957 JVM_ENTRY(const char*, JVM_GetClassNameUTF(JNIEnv *env, jclass cls)) | |
1958 JVMWrapper("JVM_GetClassNameUTF"); | |
1959 klassOop k = java_lang_Class::as_klassOop(JNIHandles::resolve_non_null(cls)); | |
1960 k = JvmtiThreadState::class_to_verify_considering_redefinition(k, thread); | |
1961 return Klass::cast(k)->name()->as_utf8(); | |
1962 JVM_END | |
1963 | |
1964 | |
1965 JVM_QUICK_ENTRY(void, JVM_GetClassCPTypes(JNIEnv *env, jclass cls, unsigned char *types)) | |
1966 JVMWrapper("JVM_GetClassCPTypes"); | |
1967 klassOop k = java_lang_Class::as_klassOop(JNIHandles::resolve_non_null(cls)); | |
1968 k = JvmtiThreadState::class_to_verify_considering_redefinition(k, thread); | |
1969 // types will have length zero if this is not an instanceKlass | |
1970 // (length is determined by call to JVM_GetClassCPEntriesCount) | |
1971 if (Klass::cast(k)->oop_is_instance()) { | |
1972 constantPoolOop cp = instanceKlass::cast(k)->constants(); | |
1973 for (int index = cp->length() - 1; index >= 0; index--) { | |
1974 constantTag tag = cp->tag_at(index); | |
1975 types[index] = (tag.is_unresolved_klass()) ? JVM_CONSTANT_Class : | |
1976 (tag.is_unresolved_string()) ? JVM_CONSTANT_String : tag.value(); | |
1977 } | |
1978 } | |
1979 JVM_END | |
1980 | |
1981 | |
1982 JVM_QUICK_ENTRY(jint, JVM_GetClassCPEntriesCount(JNIEnv *env, jclass cls)) | |
1983 JVMWrapper("JVM_GetClassCPEntriesCount"); | |
1984 klassOop k = java_lang_Class::as_klassOop(JNIHandles::resolve_non_null(cls)); | |
1985 k = JvmtiThreadState::class_to_verify_considering_redefinition(k, thread); | |
1986 if (!Klass::cast(k)->oop_is_instance()) | |
1987 return 0; | |
1988 return instanceKlass::cast(k)->constants()->length(); | |
1989 JVM_END | |
1990 | |
1991 | |
1992 JVM_QUICK_ENTRY(jint, JVM_GetClassFieldsCount(JNIEnv *env, jclass cls)) | |
1993 JVMWrapper("JVM_GetClassFieldsCount"); | |
1994 klassOop k = java_lang_Class::as_klassOop(JNIHandles::resolve_non_null(cls)); | |
1995 k = JvmtiThreadState::class_to_verify_considering_redefinition(k, thread); | |
1996 if (!Klass::cast(k)->oop_is_instance()) | |
1997 return 0; | |
1998 return instanceKlass::cast(k)->fields()->length() / instanceKlass::next_offset; | |
1999 JVM_END | |
2000 | |
2001 | |
2002 JVM_QUICK_ENTRY(jint, JVM_GetClassMethodsCount(JNIEnv *env, jclass cls)) | |
2003 JVMWrapper("JVM_GetClassMethodsCount"); | |
2004 klassOop k = java_lang_Class::as_klassOop(JNIHandles::resolve_non_null(cls)); | |
2005 k = JvmtiThreadState::class_to_verify_considering_redefinition(k, thread); | |
2006 if (!Klass::cast(k)->oop_is_instance()) | |
2007 return 0; | |
2008 return instanceKlass::cast(k)->methods()->length(); | |
2009 JVM_END | |
2010 | |
2011 | |
2012 // The following methods, used for the verifier, are never called with | |
2013 // array klasses, so a direct cast to instanceKlass is safe. | |
2014 // Typically, these methods are called in a loop with bounds determined | |
2015 // by the results of JVM_GetClass{Fields,Methods}Count, which return | |
2016 // zero for arrays. | |
2017 JVM_QUICK_ENTRY(void, JVM_GetMethodIxExceptionIndexes(JNIEnv *env, jclass cls, jint method_index, unsigned short *exceptions)) | |
2018 JVMWrapper("JVM_GetMethodIxExceptionIndexes"); | |
2019 klassOop k = java_lang_Class::as_klassOop(JNIHandles::resolve_non_null(cls)); | |
2020 k = JvmtiThreadState::class_to_verify_considering_redefinition(k, thread); | |
2021 oop method = instanceKlass::cast(k)->methods()->obj_at(method_index); | |
2022 int length = methodOop(method)->checked_exceptions_length(); | |
2023 if (length > 0) { | |
2024 CheckedExceptionElement* table= methodOop(method)->checked_exceptions_start(); | |
2025 for (int i = 0; i < length; i++) { | |
2026 exceptions[i] = table[i].class_cp_index; | |
2027 } | |
2028 } | |
2029 JVM_END | |
2030 | |
2031 | |
2032 JVM_QUICK_ENTRY(jint, JVM_GetMethodIxExceptionsCount(JNIEnv *env, jclass cls, jint method_index)) | |
2033 JVMWrapper("JVM_GetMethodIxExceptionsCount"); | |
2034 klassOop k = java_lang_Class::as_klassOop(JNIHandles::resolve_non_null(cls)); | |
2035 k = JvmtiThreadState::class_to_verify_considering_redefinition(k, thread); | |
2036 oop method = instanceKlass::cast(k)->methods()->obj_at(method_index); | |
2037 return methodOop(method)->checked_exceptions_length(); | |
2038 JVM_END | |
2039 | |
2040 | |
2041 JVM_QUICK_ENTRY(void, JVM_GetMethodIxByteCode(JNIEnv *env, jclass cls, jint method_index, unsigned char *code)) | |
2042 JVMWrapper("JVM_GetMethodIxByteCode"); | |
2043 klassOop k = java_lang_Class::as_klassOop(JNIHandles::resolve_non_null(cls)); | |
2044 k = JvmtiThreadState::class_to_verify_considering_redefinition(k, thread); | |
2045 oop method = instanceKlass::cast(k)->methods()->obj_at(method_index); | |
2046 memcpy(code, methodOop(method)->code_base(), methodOop(method)->code_size()); | |
2047 JVM_END | |
2048 | |
2049 | |
2050 JVM_QUICK_ENTRY(jint, JVM_GetMethodIxByteCodeLength(JNIEnv *env, jclass cls, jint method_index)) | |
2051 JVMWrapper("JVM_GetMethodIxByteCodeLength"); | |
2052 klassOop k = java_lang_Class::as_klassOop(JNIHandles::resolve_non_null(cls)); | |
2053 k = JvmtiThreadState::class_to_verify_considering_redefinition(k, thread); | |
2054 oop method = instanceKlass::cast(k)->methods()->obj_at(method_index); | |
2055 return methodOop(method)->code_size(); | |
2056 JVM_END | |
2057 | |
2058 | |
2059 JVM_QUICK_ENTRY(void, JVM_GetMethodIxExceptionTableEntry(JNIEnv *env, jclass cls, jint method_index, jint entry_index, JVM_ExceptionTableEntryType *entry)) | |
2060 JVMWrapper("JVM_GetMethodIxExceptionTableEntry"); | |
2061 klassOop k = java_lang_Class::as_klassOop(JNIHandles::resolve_non_null(cls)); | |
2062 k = JvmtiThreadState::class_to_verify_considering_redefinition(k, thread); | |
2063 oop method = instanceKlass::cast(k)->methods()->obj_at(method_index); | |
2064 typeArrayOop extable = methodOop(method)->exception_table(); | |
2065 entry->start_pc = extable->int_at(entry_index * 4); | |
2066 entry->end_pc = extable->int_at(entry_index * 4 + 1); | |
2067 entry->handler_pc = extable->int_at(entry_index * 4 + 2); | |
2068 entry->catchType = extable->int_at(entry_index * 4 + 3); | |
2069 JVM_END | |
2070 | |
2071 | |
2072 JVM_QUICK_ENTRY(jint, JVM_GetMethodIxExceptionTableLength(JNIEnv *env, jclass cls, int method_index)) | |
2073 JVMWrapper("JVM_GetMethodIxExceptionTableLength"); | |
2074 klassOop k = java_lang_Class::as_klassOop(JNIHandles::resolve_non_null(cls)); | |
2075 k = JvmtiThreadState::class_to_verify_considering_redefinition(k, thread); | |
2076 oop method = instanceKlass::cast(k)->methods()->obj_at(method_index); | |
2077 return methodOop(method)->exception_table()->length() / 4; | |
2078 JVM_END | |
2079 | |
2080 | |
2081 JVM_QUICK_ENTRY(jint, JVM_GetMethodIxModifiers(JNIEnv *env, jclass cls, int method_index)) | |
2082 JVMWrapper("JVM_GetMethodIxModifiers"); | |
2083 klassOop k = java_lang_Class::as_klassOop(JNIHandles::resolve_non_null(cls)); | |
2084 k = JvmtiThreadState::class_to_verify_considering_redefinition(k, thread); | |
2085 oop method = instanceKlass::cast(k)->methods()->obj_at(method_index); | |
2086 return methodOop(method)->access_flags().as_int() & JVM_RECOGNIZED_METHOD_MODIFIERS; | |
2087 JVM_END | |
2088 | |
2089 | |
2090 JVM_QUICK_ENTRY(jint, JVM_GetFieldIxModifiers(JNIEnv *env, jclass cls, int field_index)) | |
2091 JVMWrapper("JVM_GetFieldIxModifiers"); | |
2092 klassOop k = java_lang_Class::as_klassOop(JNIHandles::resolve_non_null(cls)); | |
2093 k = JvmtiThreadState::class_to_verify_considering_redefinition(k, thread); | |
2094 typeArrayOop fields = instanceKlass::cast(k)->fields(); | |
2095 return fields->ushort_at(field_index * instanceKlass::next_offset + instanceKlass::access_flags_offset) & JVM_RECOGNIZED_FIELD_MODIFIERS; | |
2096 JVM_END | |
2097 | |
2098 | |
2099 JVM_QUICK_ENTRY(jint, JVM_GetMethodIxLocalsCount(JNIEnv *env, jclass cls, int method_index)) | |
2100 JVMWrapper("JVM_GetMethodIxLocalsCount"); | |
2101 klassOop k = java_lang_Class::as_klassOop(JNIHandles::resolve_non_null(cls)); | |
2102 k = JvmtiThreadState::class_to_verify_considering_redefinition(k, thread); | |
2103 oop method = instanceKlass::cast(k)->methods()->obj_at(method_index); | |
2104 return methodOop(method)->max_locals(); | |
2105 JVM_END | |
2106 | |
2107 | |
2108 JVM_QUICK_ENTRY(jint, JVM_GetMethodIxArgsSize(JNIEnv *env, jclass cls, int method_index)) | |
2109 JVMWrapper("JVM_GetMethodIxArgsSize"); | |
2110 klassOop k = java_lang_Class::as_klassOop(JNIHandles::resolve_non_null(cls)); | |
2111 k = JvmtiThreadState::class_to_verify_considering_redefinition(k, thread); | |
2112 oop method = instanceKlass::cast(k)->methods()->obj_at(method_index); | |
2113 return methodOop(method)->size_of_parameters(); | |
2114 JVM_END | |
2115 | |
2116 | |
2117 JVM_QUICK_ENTRY(jint, JVM_GetMethodIxMaxStack(JNIEnv *env, jclass cls, int method_index)) | |
2118 JVMWrapper("JVM_GetMethodIxMaxStack"); | |
2119 klassOop k = java_lang_Class::as_klassOop(JNIHandles::resolve_non_null(cls)); | |
2120 k = JvmtiThreadState::class_to_verify_considering_redefinition(k, thread); | |
2121 oop method = instanceKlass::cast(k)->methods()->obj_at(method_index); | |
2122 return methodOop(method)->max_stack(); | |
2123 JVM_END | |
2124 | |
2125 | |
2126 JVM_QUICK_ENTRY(jboolean, JVM_IsConstructorIx(JNIEnv *env, jclass cls, int method_index)) | |
2127 JVMWrapper("JVM_IsConstructorIx"); | |
2128 ResourceMark rm(THREAD); | |
2129 klassOop k = java_lang_Class::as_klassOop(JNIHandles::resolve_non_null(cls)); | |
2130 k = JvmtiThreadState::class_to_verify_considering_redefinition(k, thread); | |
2131 oop method = instanceKlass::cast(k)->methods()->obj_at(method_index); | |
2132 return methodOop(method)->name() == vmSymbols::object_initializer_name(); | |
2133 JVM_END | |
2134 | |
2135 | |
2136 JVM_ENTRY(const char*, JVM_GetMethodIxNameUTF(JNIEnv *env, jclass cls, jint method_index)) | |
2137 JVMWrapper("JVM_GetMethodIxIxUTF"); | |
2138 klassOop k = java_lang_Class::as_klassOop(JNIHandles::resolve_non_null(cls)); | |
2139 k = JvmtiThreadState::class_to_verify_considering_redefinition(k, thread); | |
2140 oop method = instanceKlass::cast(k)->methods()->obj_at(method_index); | |
2141 return methodOop(method)->name()->as_utf8(); | |
2142 JVM_END | |
2143 | |
2144 | |
2145 JVM_ENTRY(const char*, JVM_GetMethodIxSignatureUTF(JNIEnv *env, jclass cls, jint method_index)) | |
2146 JVMWrapper("JVM_GetMethodIxSignatureUTF"); | |
2147 klassOop k = java_lang_Class::as_klassOop(JNIHandles::resolve_non_null(cls)); | |
2148 k = JvmtiThreadState::class_to_verify_considering_redefinition(k, thread); | |
2149 oop method = instanceKlass::cast(k)->methods()->obj_at(method_index); | |
2150 return methodOop(method)->signature()->as_utf8(); | |
2151 JVM_END | |
2152 | |
2153 /** | |
2154 * All of these JVM_GetCP-xxx methods are used by the old verifier to | |
2155 * read entries in the constant pool. Since the old verifier always | |
2156 * works on a copy of the code, it will not see any rewriting that | |
2157 * may possibly occur in the middle of verification. So it is important | |
2158 * that nothing it calls tries to use the cpCache instead of the raw | |
2159 * constant pool, so we must use cp->uncached_x methods when appropriate. | |
2160 */ | |
2161 JVM_ENTRY(const char*, JVM_GetCPFieldNameUTF(JNIEnv *env, jclass cls, jint cp_index)) | |
2162 JVMWrapper("JVM_GetCPFieldNameUTF"); | |
2163 klassOop k = java_lang_Class::as_klassOop(JNIHandles::resolve_non_null(cls)); | |
2164 k = JvmtiThreadState::class_to_verify_considering_redefinition(k, thread); | |
2165 constantPoolOop cp = instanceKlass::cast(k)->constants(); | |
2166 switch (cp->tag_at(cp_index).value()) { | |
2167 case JVM_CONSTANT_Fieldref: | |
2168 return cp->uncached_name_ref_at(cp_index)->as_utf8(); | |
2169 default: | |
2170 fatal("JVM_GetCPFieldNameUTF: illegal constant"); | |
2171 } | |
2172 ShouldNotReachHere(); | |
2173 return NULL; | |
2174 JVM_END | |
2175 | |
2176 | |
2177 JVM_ENTRY(const char*, JVM_GetCPMethodNameUTF(JNIEnv *env, jclass cls, jint cp_index)) | |
2178 JVMWrapper("JVM_GetCPMethodNameUTF"); | |
2179 klassOop k = java_lang_Class::as_klassOop(JNIHandles::resolve_non_null(cls)); | |
2180 k = JvmtiThreadState::class_to_verify_considering_redefinition(k, thread); | |
2181 constantPoolOop cp = instanceKlass::cast(k)->constants(); | |
2182 switch (cp->tag_at(cp_index).value()) { | |
2183 case JVM_CONSTANT_InterfaceMethodref: | |
2184 case JVM_CONSTANT_Methodref: | |
2185 return cp->uncached_name_ref_at(cp_index)->as_utf8(); | |
2186 default: | |
2187 fatal("JVM_GetCPMethodNameUTF: illegal constant"); | |
2188 } | |
2189 ShouldNotReachHere(); | |
2190 return NULL; | |
2191 JVM_END | |
2192 | |
2193 | |
2194 JVM_ENTRY(const char*, JVM_GetCPMethodSignatureUTF(JNIEnv *env, jclass cls, jint cp_index)) | |
2195 JVMWrapper("JVM_GetCPMethodSignatureUTF"); | |
2196 klassOop k = java_lang_Class::as_klassOop(JNIHandles::resolve_non_null(cls)); | |
2197 k = JvmtiThreadState::class_to_verify_considering_redefinition(k, thread); | |
2198 constantPoolOop cp = instanceKlass::cast(k)->constants(); | |
2199 switch (cp->tag_at(cp_index).value()) { | |
2200 case JVM_CONSTANT_InterfaceMethodref: | |
2201 case JVM_CONSTANT_Methodref: | |
2202 return cp->uncached_signature_ref_at(cp_index)->as_utf8(); | |
2203 default: | |
2204 fatal("JVM_GetCPMethodSignatureUTF: illegal constant"); | |
2205 } | |
2206 ShouldNotReachHere(); | |
2207 return NULL; | |
2208 JVM_END | |
2209 | |
2210 | |
2211 JVM_ENTRY(const char*, JVM_GetCPFieldSignatureUTF(JNIEnv *env, jclass cls, jint cp_index)) | |
2212 JVMWrapper("JVM_GetCPFieldSignatureUTF"); | |
2213 klassOop k = java_lang_Class::as_klassOop(JNIHandles::resolve_non_null(cls)); | |
2214 k = JvmtiThreadState::class_to_verify_considering_redefinition(k, thread); | |
2215 constantPoolOop cp = instanceKlass::cast(k)->constants(); | |
2216 switch (cp->tag_at(cp_index).value()) { | |
2217 case JVM_CONSTANT_Fieldref: | |
2218 return cp->uncached_signature_ref_at(cp_index)->as_utf8(); | |
2219 default: | |
2220 fatal("JVM_GetCPFieldSignatureUTF: illegal constant"); | |
2221 } | |
2222 ShouldNotReachHere(); | |
2223 return NULL; | |
2224 JVM_END | |
2225 | |
2226 | |
2227 JVM_ENTRY(const char*, JVM_GetCPClassNameUTF(JNIEnv *env, jclass cls, jint cp_index)) | |
2228 JVMWrapper("JVM_GetCPClassNameUTF"); | |
2229 klassOop k = java_lang_Class::as_klassOop(JNIHandles::resolve_non_null(cls)); | |
2230 k = JvmtiThreadState::class_to_verify_considering_redefinition(k, thread); | |
2231 constantPoolOop cp = instanceKlass::cast(k)->constants(); | |
2232 symbolOop classname = cp->klass_name_at(cp_index); | |
2233 return classname->as_utf8(); | |
2234 JVM_END | |
2235 | |
2236 | |
2237 JVM_ENTRY(const char*, JVM_GetCPFieldClassNameUTF(JNIEnv *env, jclass cls, jint cp_index)) | |
2238 JVMWrapper("JVM_GetCPFieldClassNameUTF"); | |
2239 klassOop k = java_lang_Class::as_klassOop(JNIHandles::resolve_non_null(cls)); | |
2240 k = JvmtiThreadState::class_to_verify_considering_redefinition(k, thread); | |
2241 constantPoolOop cp = instanceKlass::cast(k)->constants(); | |
2242 switch (cp->tag_at(cp_index).value()) { | |
2243 case JVM_CONSTANT_Fieldref: { | |
2244 int class_index = cp->uncached_klass_ref_index_at(cp_index); | |
2245 symbolOop classname = cp->klass_name_at(class_index); | |
2246 return classname->as_utf8(); | |
2247 } | |
2248 default: | |
2249 fatal("JVM_GetCPFieldClassNameUTF: illegal constant"); | |
2250 } | |
2251 ShouldNotReachHere(); | |
2252 return NULL; | |
2253 JVM_END | |
2254 | |
2255 | |
2256 JVM_ENTRY(const char*, JVM_GetCPMethodClassNameUTF(JNIEnv *env, jclass cls, jint cp_index)) | |
2257 JVMWrapper("JVM_GetCPMethodClassNameUTF"); | |
2258 klassOop k = java_lang_Class::as_klassOop(JNIHandles::resolve_non_null(cls)); | |
2259 k = JvmtiThreadState::class_to_verify_considering_redefinition(k, thread); | |
2260 constantPoolOop cp = instanceKlass::cast(k)->constants(); | |
2261 switch (cp->tag_at(cp_index).value()) { | |
2262 case JVM_CONSTANT_Methodref: | |
2263 case JVM_CONSTANT_InterfaceMethodref: { | |
2264 int class_index = cp->uncached_klass_ref_index_at(cp_index); | |
2265 symbolOop classname = cp->klass_name_at(class_index); | |
2266 return classname->as_utf8(); | |
2267 } | |
2268 default: | |
2269 fatal("JVM_GetCPMethodClassNameUTF: illegal constant"); | |
2270 } | |
2271 ShouldNotReachHere(); | |
2272 return NULL; | |
2273 JVM_END | |
2274 | |
2275 | |
2276 JVM_QUICK_ENTRY(jint, JVM_GetCPFieldModifiers(JNIEnv *env, jclass cls, int cp_index, jclass called_cls)) | |
2277 JVMWrapper("JVM_GetCPFieldModifiers"); | |
2278 klassOop k = java_lang_Class::as_klassOop(JNIHandles::resolve_non_null(cls)); | |
2279 klassOop k_called = java_lang_Class::as_klassOop(JNIHandles::resolve_non_null(called_cls)); | |
2280 k = JvmtiThreadState::class_to_verify_considering_redefinition(k, thread); | |
2281 k_called = JvmtiThreadState::class_to_verify_considering_redefinition(k_called, thread); | |
2282 constantPoolOop cp = instanceKlass::cast(k)->constants(); | |
2283 constantPoolOop cp_called = instanceKlass::cast(k_called)->constants(); | |
2284 switch (cp->tag_at(cp_index).value()) { | |
2285 case JVM_CONSTANT_Fieldref: { | |
2286 symbolOop name = cp->uncached_name_ref_at(cp_index); | |
2287 symbolOop signature = cp->uncached_signature_ref_at(cp_index); | |
2288 typeArrayOop fields = instanceKlass::cast(k_called)->fields(); | |
2289 int fields_count = fields->length(); | |
2290 for (int i = 0; i < fields_count; i += instanceKlass::next_offset) { | |
2291 if (cp_called->symbol_at(fields->ushort_at(i + instanceKlass::name_index_offset)) == name && | |
2292 cp_called->symbol_at(fields->ushort_at(i + instanceKlass::signature_index_offset)) == signature) { | |
2293 return fields->ushort_at(i + instanceKlass::access_flags_offset) & JVM_RECOGNIZED_FIELD_MODIFIERS; | |
2294 } | |
2295 } | |
2296 return -1; | |
2297 } | |
2298 default: | |
2299 fatal("JVM_GetCPFieldModifiers: illegal constant"); | |
2300 } | |
2301 ShouldNotReachHere(); | |
2302 return 0; | |
2303 JVM_END | |
2304 | |
2305 | |
2306 JVM_QUICK_ENTRY(jint, JVM_GetCPMethodModifiers(JNIEnv *env, jclass cls, int cp_index, jclass called_cls)) | |
2307 JVMWrapper("JVM_GetCPMethodModifiers"); | |
2308 klassOop k = java_lang_Class::as_klassOop(JNIHandles::resolve_non_null(cls)); | |
2309 klassOop k_called = java_lang_Class::as_klassOop(JNIHandles::resolve_non_null(called_cls)); | |
2310 k = JvmtiThreadState::class_to_verify_considering_redefinition(k, thread); | |
2311 k_called = JvmtiThreadState::class_to_verify_considering_redefinition(k_called, thread); | |
2312 constantPoolOop cp = instanceKlass::cast(k)->constants(); | |
2313 switch (cp->tag_at(cp_index).value()) { | |
2314 case JVM_CONSTANT_Methodref: | |
2315 case JVM_CONSTANT_InterfaceMethodref: { | |
2316 symbolOop name = cp->uncached_name_ref_at(cp_index); | |
2317 symbolOop signature = cp->uncached_signature_ref_at(cp_index); | |
2318 objArrayOop methods = instanceKlass::cast(k_called)->methods(); | |
2319 int methods_count = methods->length(); | |
2320 for (int i = 0; i < methods_count; i++) { | |
2321 methodOop method = methodOop(methods->obj_at(i)); | |
2322 if (method->name() == name && method->signature() == signature) { | |
2323 return method->access_flags().as_int() & JVM_RECOGNIZED_METHOD_MODIFIERS; | |
2324 } | |
2325 } | |
2326 return -1; | |
2327 } | |
2328 default: | |
2329 fatal("JVM_GetCPMethodModifiers: illegal constant"); | |
2330 } | |
2331 ShouldNotReachHere(); | |
2332 return 0; | |
2333 JVM_END | |
2334 | |
2335 | |
2336 // Misc ////////////////////////////////////////////////////////////////////////////////////////////// | |
2337 | |
2338 JVM_LEAF(void, JVM_ReleaseUTF(const char *utf)) | |
2339 // So long as UTF8::convert_to_utf8 returns resource strings, we don't have to do anything | |
2340 JVM_END | |
2341 | |
2342 | |
2343 JVM_ENTRY(jboolean, JVM_IsSameClassPackage(JNIEnv *env, jclass class1, jclass class2)) | |
2344 JVMWrapper("JVM_IsSameClassPackage"); | |
2345 oop class1_mirror = JNIHandles::resolve_non_null(class1); | |
2346 oop class2_mirror = JNIHandles::resolve_non_null(class2); | |
2347 klassOop klass1 = java_lang_Class::as_klassOop(class1_mirror); | |
2348 klassOop klass2 = java_lang_Class::as_klassOop(class2_mirror); | |
2349 return (jboolean) Reflection::is_same_class_package(klass1, klass2); | |
2350 JVM_END | |
2351 | |
2352 | |
2353 // IO functions //////////////////////////////////////////////////////////////////////////////////////// | |
2354 | |
2355 JVM_LEAF(jint, JVM_Open(const char *fname, jint flags, jint mode)) | |
2356 JVMWrapper2("JVM_Open (%s)", fname); | |
2357 | |
2358 //%note jvm_r6 | |
2359 int result = hpi::open(fname, flags, mode); | |
2360 if (result >= 0) { | |
2361 return result; | |
2362 } else { | |
2363 switch(errno) { | |
2364 case EEXIST: | |
2365 return JVM_EEXIST; | |
2366 default: | |
2367 return -1; | |
2368 } | |
2369 } | |
2370 JVM_END | |
2371 | |
2372 | |
2373 JVM_LEAF(jint, JVM_Close(jint fd)) | |
2374 JVMWrapper2("JVM_Close (0x%x)", fd); | |
2375 //%note jvm_r6 | |
2376 return hpi::close(fd); | |
2377 JVM_END | |
2378 | |
2379 | |
2380 JVM_LEAF(jint, JVM_Read(jint fd, char *buf, jint nbytes)) | |
2381 JVMWrapper2("JVM_Read (0x%x)", fd); | |
2382 | |
2383 //%note jvm_r6 | |
2384 return (jint)hpi::read(fd, buf, nbytes); | |
2385 JVM_END | |
2386 | |
2387 | |
2388 JVM_LEAF(jint, JVM_Write(jint fd, char *buf, jint nbytes)) | |
2389 JVMWrapper2("JVM_Write (0x%x)", fd); | |
2390 | |
2391 //%note jvm_r6 | |
2392 return (jint)hpi::write(fd, buf, nbytes); | |
2393 JVM_END | |
2394 | |
2395 | |
2396 JVM_LEAF(jint, JVM_Available(jint fd, jlong *pbytes)) | |
2397 JVMWrapper2("JVM_Available (0x%x)", fd); | |
2398 //%note jvm_r6 | |
2399 return hpi::available(fd, pbytes); | |
2400 JVM_END | |
2401 | |
2402 | |
2403 JVM_LEAF(jlong, JVM_Lseek(jint fd, jlong offset, jint whence)) | |
2404 JVMWrapper4("JVM_Lseek (0x%x, %Ld, %d)", fd, offset, whence); | |
2405 //%note jvm_r6 | |
2406 return hpi::lseek(fd, offset, whence); | |
2407 JVM_END | |
2408 | |
2409 | |
2410 JVM_LEAF(jint, JVM_SetLength(jint fd, jlong length)) | |
2411 JVMWrapper3("JVM_SetLength (0x%x, %Ld)", fd, length); | |
2412 return hpi::ftruncate(fd, length); | |
2413 JVM_END | |
2414 | |
2415 | |
2416 JVM_LEAF(jint, JVM_Sync(jint fd)) | |
2417 JVMWrapper2("JVM_Sync (0x%x)", fd); | |
2418 //%note jvm_r6 | |
2419 return hpi::fsync(fd); | |
2420 JVM_END | |
2421 | |
2422 | |
2423 // Printing support ////////////////////////////////////////////////// | |
2424 extern "C" { | |
2425 | |
2426 int jio_vsnprintf(char *str, size_t count, const char *fmt, va_list args) { | |
2427 // see bug 4399518, 4417214 | |
2428 if ((intptr_t)count <= 0) return -1; | |
2429 return vsnprintf(str, count, fmt, args); | |
2430 } | |
2431 | |
2432 | |
2433 int jio_snprintf(char *str, size_t count, const char *fmt, ...) { | |
2434 va_list args; | |
2435 int len; | |
2436 va_start(args, fmt); | |
2437 len = jio_vsnprintf(str, count, fmt, args); | |
2438 va_end(args); | |
2439 return len; | |
2440 } | |
2441 | |
2442 | |
2443 int jio_fprintf(FILE* f, const char *fmt, ...) { | |
2444 int len; | |
2445 va_list args; | |
2446 va_start(args, fmt); | |
2447 len = jio_vfprintf(f, fmt, args); | |
2448 va_end(args); | |
2449 return len; | |
2450 } | |
2451 | |
2452 | |
2453 int jio_vfprintf(FILE* f, const char *fmt, va_list args) { | |
2454 if (Arguments::vfprintf_hook() != NULL) { | |
2455 return Arguments::vfprintf_hook()(f, fmt, args); | |
2456 } else { | |
2457 return vfprintf(f, fmt, args); | |
2458 } | |
2459 } | |
2460 | |
2461 | |
2462 int jio_printf(const char *fmt, ...) { | |
2463 int len; | |
2464 va_list args; | |
2465 va_start(args, fmt); | |
2466 len = jio_vfprintf(defaultStream::output_stream(), fmt, args); | |
2467 va_end(args); | |
2468 return len; | |
2469 } | |
2470 | |
2471 | |
2472 // HotSpot specific jio method | |
2473 void jio_print(const char* s) { | |
2474 // Try to make this function as atomic as possible. | |
2475 if (Arguments::vfprintf_hook() != NULL) { | |
2476 jio_fprintf(defaultStream::output_stream(), "%s", s); | |
2477 } else { | |
2478 ::write(defaultStream::output_fd(), s, (int)strlen(s)); | |
2479 } | |
2480 } | |
2481 | |
2482 } // Extern C | |
2483 | |
2484 // java.lang.Thread ////////////////////////////////////////////////////////////////////////////// | |
2485 | |
2486 // In most of the JVM Thread support functions we need to be sure to lock the Threads_lock | |
2487 // to prevent the target thread from exiting after we have a pointer to the C++ Thread or | |
2488 // OSThread objects. The exception to this rule is when the target object is the thread | |
2489 // doing the operation, in which case we know that the thread won't exit until the | |
2490 // operation is done (all exits being voluntary). There are a few cases where it is | |
2491 // rather silly to do operations on yourself, like resuming yourself or asking whether | |
2492 // you are alive. While these can still happen, they are not subject to deadlocks if | |
2493 // the lock is held while the operation occurs (this is not the case for suspend, for | |
2494 // instance), and are very unlikely. Because IsAlive needs to be fast and its | |
2495 // implementation is local to this file, we always lock Threads_lock for that one. | |
2496 | |
2497 static void thread_entry(JavaThread* thread, TRAPS) { | |
2498 HandleMark hm(THREAD); | |
2499 Handle obj(THREAD, thread->threadObj()); | |
2500 JavaValue result(T_VOID); | |
2501 JavaCalls::call_virtual(&result, | |
2502 obj, | |
2503 KlassHandle(THREAD, SystemDictionary::thread_klass()), | |
2504 vmSymbolHandles::run_method_name(), | |
2505 vmSymbolHandles::void_method_signature(), | |
2506 THREAD); | |
2507 } | |
2508 | |
2509 | |
2510 JVM_ENTRY(void, JVM_StartThread(JNIEnv* env, jobject jthread)) | |
2511 JVMWrapper("JVM_StartThread"); | |
2512 JavaThread *native_thread = NULL; | |
2513 | |
2514 // We cannot hold the Threads_lock when we throw an exception, | |
2515 // due to rank ordering issues. Example: we might need to grab the | |
2516 // Heap_lock while we construct the exception. | |
2517 bool throw_illegal_thread_state = false; | |
2518 | |
2519 // We must release the Threads_lock before we can post a jvmti event | |
2520 // in Thread::start. | |
2521 { | |
2522 // Ensure that the C++ Thread and OSThread structures aren't freed before | |
2523 // we operate. | |
2524 MutexLocker mu(Threads_lock); | |
2525 | |
2526 // Check to see if we're running a thread that's already exited or was | |
2527 // stopped (is_stillborn) or is still active (thread is not NULL). | |
2528 if (java_lang_Thread::is_stillborn(JNIHandles::resolve_non_null(jthread)) || | |
2529 java_lang_Thread::thread(JNIHandles::resolve_non_null(jthread)) != NULL) { | |
2530 throw_illegal_thread_state = true; | |
2531 } else { | |
2532 jlong size = | |
2533 java_lang_Thread::stackSize(JNIHandles::resolve_non_null(jthread)); | |
2534 // Allocate the C++ Thread structure and create the native thread. The | |
2535 // stack size retrieved from java is signed, but the constructor takes | |
2536 // size_t (an unsigned type), so avoid passing negative values which would | |
2537 // result in really large stacks. | |
2538 size_t sz = size > 0 ? (size_t) size : 0; | |
2539 native_thread = new JavaThread(&thread_entry, sz); | |
2540 | |
2541 // At this point it may be possible that no osthread was created for the | |
2542 // JavaThread due to lack of memory. Check for this situation and throw | |
2543 // an exception if necessary. Eventually we may want to change this so | |
2544 // that we only grab the lock if the thread was created successfully - | |
2545 // then we can also do this check and throw the exception in the | |
2546 // JavaThread constructor. | |
2547 if (native_thread->osthread() != NULL) { | |
2548 // Note: the current thread is not being used within "prepare". | |
2549 native_thread->prepare(jthread); | |
2550 } | |
2551 } | |
2552 } | |
2553 | |
2554 if (throw_illegal_thread_state) { | |
2555 THROW(vmSymbols::java_lang_IllegalThreadStateException()); | |
2556 } | |
2557 | |
2558 assert(native_thread != NULL, "Starting null thread?"); | |
2559 | |
2560 if (native_thread->osthread() == NULL) { | |
2561 // No one should hold a reference to the 'native_thread'. | |
2562 delete native_thread; | |
2563 if (JvmtiExport::should_post_resource_exhausted()) { | |
2564 JvmtiExport::post_resource_exhausted( | |
2565 JVMTI_RESOURCE_EXHAUSTED_OOM_ERROR | JVMTI_RESOURCE_EXHAUSTED_THREADS, | |
2566 "unable to create new native thread"); | |
2567 } | |
2568 THROW_MSG(vmSymbols::java_lang_OutOfMemoryError(), | |
2569 "unable to create new native thread"); | |
2570 } | |
2571 | |
2572 Thread::start(native_thread); | |
2573 | |
2574 JVM_END | |
2575 | |
2576 // JVM_Stop is implemented using a VM_Operation, so threads are forced to safepoints | |
2577 // before the quasi-asynchronous exception is delivered. This is a little obtrusive, | |
2578 // but is thought to be reliable and simple. In the case, where the receiver is the | |
2579 // save thread as the sender, no safepoint is needed. | |
2580 JVM_ENTRY(void, JVM_StopThread(JNIEnv* env, jobject jthread, jobject throwable)) | |
2581 JVMWrapper("JVM_StopThread"); | |
2582 | |
2583 oop java_throwable = JNIHandles::resolve(throwable); | |
2584 if (java_throwable == NULL) { | |
2585 THROW(vmSymbols::java_lang_NullPointerException()); | |
2586 } | |
2587 oop java_thread = JNIHandles::resolve_non_null(jthread); | |
2588 JavaThread* receiver = java_lang_Thread::thread(java_thread); | |
2589 Events::log("JVM_StopThread thread JavaThread " INTPTR_FORMAT " as oop " INTPTR_FORMAT " [exception " INTPTR_FORMAT "]", receiver, (address)java_thread, throwable); | |
2590 // First check if thread already exited | |
2591 if (receiver != NULL) { | |
2592 // Check if exception is getting thrown at self (use oop equality, since the | |
2593 // target object might exit) | |
2594 if (java_thread == thread->threadObj()) { | |
2595 // This is a change from JDK 1.1, but JDK 1.2 will also do it: | |
2596 // NOTE (from JDK 1.2): this is done solely to prevent stopped | |
2597 // threads from being restarted. | |
2598 // Fix for 4314342, 4145910, perhaps others: it now doesn't have | |
2599 // any effect on the "liveness" of a thread; see | |
2600 // JVM_IsThreadAlive, below. | |
2601 if (java_throwable->is_a(SystemDictionary::threaddeath_klass())) { | |
2602 java_lang_Thread::set_stillborn(java_thread); | |
2603 } | |
2604 THROW_OOP(java_throwable); | |
2605 } else { | |
2606 // Enques a VM_Operation to stop all threads and then deliver the exception... | |
2607 Thread::send_async_exception(java_thread, JNIHandles::resolve(throwable)); | |
2608 } | |
2609 } | |
2610 JVM_END | |
2611 | |
2612 | |
2613 JVM_ENTRY(jboolean, JVM_IsThreadAlive(JNIEnv* env, jobject jthread)) | |
2614 JVMWrapper("JVM_IsThreadAlive"); | |
2615 | |
2616 oop thread_oop = JNIHandles::resolve_non_null(jthread); | |
2617 return java_lang_Thread::is_alive(thread_oop); | |
2618 JVM_END | |
2619 | |
2620 | |
2621 JVM_ENTRY(void, JVM_SuspendThread(JNIEnv* env, jobject jthread)) | |
2622 JVMWrapper("JVM_SuspendThread"); | |
2623 oop java_thread = JNIHandles::resolve_non_null(jthread); | |
2624 JavaThread* receiver = java_lang_Thread::thread(java_thread); | |
2625 | |
2626 if (receiver != NULL) { | |
2627 // thread has run and has not exited (still on threads list) | |
2628 | |
2629 { | |
2630 MutexLockerEx ml(receiver->SR_lock(), Mutex::_no_safepoint_check_flag); | |
2631 if (receiver->is_external_suspend()) { | |
2632 // Don't allow nested external suspend requests. We can't return | |
2633 // an error from this interface so just ignore the problem. | |
2634 return; | |
2635 } | |
2636 if (receiver->is_exiting()) { // thread is in the process of exiting | |
2637 return; | |
2638 } | |
2639 receiver->set_external_suspend(); | |
2640 } | |
2641 | |
2642 // java_suspend() will catch threads in the process of exiting | |
2643 // and will ignore them. | |
2644 receiver->java_suspend(); | |
2645 | |
2646 // It would be nice to have the following assertion in all the | |
2647 // time, but it is possible for a racing resume request to have | |
2648 // resumed this thread right after we suspended it. Temporarily | |
2649 // enable this assertion if you are chasing a different kind of | |
2650 // bug. | |
2651 // | |
2652 // assert(java_lang_Thread::thread(receiver->threadObj()) == NULL || | |
2653 // receiver->is_being_ext_suspended(), "thread is not suspended"); | |
2654 } | |
2655 JVM_END | |
2656 | |
2657 | |
2658 JVM_ENTRY(void, JVM_ResumeThread(JNIEnv* env, jobject jthread)) | |
2659 JVMWrapper("JVM_ResumeThread"); | |
2660 // Ensure that the C++ Thread and OSThread structures aren't freed before we operate. | |
2661 // We need to *always* get the threads lock here, since this operation cannot be allowed during | |
2662 // a safepoint. The safepoint code relies on suspending a thread to examine its state. If other | |
2663 // threads randomly resumes threads, then a thread might not be suspended when the safepoint code | |
2664 // looks at it. | |
2665 MutexLocker ml(Threads_lock); | |
2666 JavaThread* thr = java_lang_Thread::thread(JNIHandles::resolve_non_null(jthread)); | |
2667 if (thr != NULL) { | |
2668 // the thread has run and is not in the process of exiting | |
2669 thr->java_resume(); | |
2670 } | |
2671 JVM_END | |
2672 | |
2673 | |
2674 JVM_ENTRY(void, JVM_SetThreadPriority(JNIEnv* env, jobject jthread, jint prio)) | |
2675 JVMWrapper("JVM_SetThreadPriority"); | |
2676 // Ensure that the C++ Thread and OSThread structures aren't freed before we operate | |
2677 MutexLocker ml(Threads_lock); | |
2678 oop java_thread = JNIHandles::resolve_non_null(jthread); | |
2679 java_lang_Thread::set_priority(java_thread, (ThreadPriority)prio); | |
2680 JavaThread* thr = java_lang_Thread::thread(java_thread); | |
2681 if (thr != NULL) { // Thread not yet started; priority pushed down when it is | |
2682 Thread::set_priority(thr, (ThreadPriority)prio); | |
2683 } | |
2684 JVM_END | |
2685 | |
2686 | |
2687 JVM_ENTRY(void, JVM_Yield(JNIEnv *env, jclass threadClass)) | |
2688 JVMWrapper("JVM_Yield"); | |
2689 if (os::dont_yield()) return; | |
2690 // When ConvertYieldToSleep is off (default), this matches the classic VM use of yield. | |
2691 // Critical for similar threading behaviour | |
2692 if (ConvertYieldToSleep) { | |
2693 os::sleep(thread, MinSleepInterval, false); | |
2694 } else { | |
2695 os::yield(); | |
2696 } | |
2697 JVM_END | |
2698 | |
2699 | |
2700 JVM_ENTRY(void, JVM_Sleep(JNIEnv* env, jclass threadClass, jlong millis)) | |
2701 JVMWrapper("JVM_Sleep"); | |
2702 | |
2703 if (millis < 0) { | |
2704 THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(), "timeout value is negative"); | |
2705 } | |
2706 | |
2707 if (Thread::is_interrupted (THREAD, true) && !HAS_PENDING_EXCEPTION) { | |
2708 THROW_MSG(vmSymbols::java_lang_InterruptedException(), "sleep interrupted"); | |
2709 } | |
2710 | |
2711 // Save current thread state and restore it at the end of this block. | |
2712 // And set new thread state to SLEEPING. | |
2713 JavaThreadSleepState jtss(thread); | |
2714 | |
2715 if (millis == 0) { | |
2716 // When ConvertSleepToYield is on, this matches the classic VM implementation of | |
2717 // JVM_Sleep. Critical for similar threading behaviour (Win32) | |
2718 // It appears that in certain GUI contexts, it may be beneficial to do a short sleep | |
2719 // for SOLARIS | |
2720 if (ConvertSleepToYield) { | |
2721 os::yield(); | |
2722 } else { | |
2723 ThreadState old_state = thread->osthread()->get_state(); | |
2724 thread->osthread()->set_state(SLEEPING); | |
2725 os::sleep(thread, MinSleepInterval, false); | |
2726 thread->osthread()->set_state(old_state); | |
2727 } | |
2728 } else { | |
2729 ThreadState old_state = thread->osthread()->get_state(); | |
2730 thread->osthread()->set_state(SLEEPING); | |
2731 if (os::sleep(thread, millis, true) == OS_INTRPT) { | |
2732 // An asynchronous exception (e.g., ThreadDeathException) could have been thrown on | |
2733 // us while we were sleeping. We do not overwrite those. | |
2734 if (!HAS_PENDING_EXCEPTION) { | |
2735 // TODO-FIXME: THROW_MSG returns which means we will not call set_state() | |
2736 // to properly restore the thread state. That's likely wrong. | |
2737 THROW_MSG(vmSymbols::java_lang_InterruptedException(), "sleep interrupted"); | |
2738 } | |
2739 } | |
2740 thread->osthread()->set_state(old_state); | |
2741 } | |
2742 JVM_END | |
2743 | |
2744 JVM_ENTRY(jobject, JVM_CurrentThread(JNIEnv* env, jclass threadClass)) | |
2745 JVMWrapper("JVM_CurrentThread"); | |
2746 oop jthread = thread->threadObj(); | |
2747 assert (thread != NULL, "no current thread!"); | |
2748 return JNIHandles::make_local(env, jthread); | |
2749 JVM_END | |
2750 | |
2751 | |
2752 JVM_ENTRY(jint, JVM_CountStackFrames(JNIEnv* env, jobject jthread)) | |
2753 JVMWrapper("JVM_CountStackFrames"); | |
2754 | |
2755 // Ensure that the C++ Thread and OSThread structures aren't freed before we operate | |
2756 oop java_thread = JNIHandles::resolve_non_null(jthread); | |
2757 bool throw_illegal_thread_state = false; | |
2758 int count = 0; | |
2759 | |
2760 { | |
2761 MutexLockerEx ml(thread->threadObj() == java_thread ? NULL : Threads_lock); | |
2762 // We need to re-resolve the java_thread, since a GC might have happened during the | |
2763 // acquire of the lock | |
2764 JavaThread* thr = java_lang_Thread::thread(JNIHandles::resolve_non_null(jthread)); | |
2765 | |
2766 if (thr == NULL) { | |
2767 // do nothing | |
2768 } else if(! thr->is_external_suspend() || ! thr->frame_anchor()->walkable()) { | |
2769 // Check whether this java thread has been suspended already. If not, throws | |
2770 // IllegalThreadStateException. We defer to throw that exception until | |
2771 // Threads_lock is released since loading exception class has to leave VM. | |
2772 // The correct way to test a thread is actually suspended is | |
2773 // wait_for_ext_suspend_completion(), but we can't call that while holding | |
2774 // the Threads_lock. The above tests are sufficient for our purposes | |
2775 // provided the walkability of the stack is stable - which it isn't | |
2776 // 100% but close enough for most practical purposes. | |
2777 throw_illegal_thread_state = true; | |
2778 } else { | |
2779 // Count all java activation, i.e., number of vframes | |
2780 for(vframeStream vfst(thr); !vfst.at_end(); vfst.next()) { | |
2781 // Native frames are not counted | |
2782 if (!vfst.method()->is_native()) count++; | |
2783 } | |
2784 } | |
2785 } | |
2786 | |
2787 if (throw_illegal_thread_state) { | |
2788 THROW_MSG_0(vmSymbols::java_lang_IllegalThreadStateException(), | |
2789 "this thread is not suspended"); | |
2790 } | |
2791 return count; | |
2792 JVM_END | |
2793 | |
2794 // Consider: A better way to implement JVM_Interrupt() is to acquire | |
2795 // Threads_lock to resolve the jthread into a Thread pointer, fetch | |
2796 // Thread->platformevent, Thread->native_thr, Thread->parker, etc., | |
2797 // drop Threads_lock, and the perform the unpark() and thr_kill() operations | |
2798 // outside the critical section. Threads_lock is hot so we want to minimize | |
2799 // the hold-time. A cleaner interface would be to decompose interrupt into | |
2800 // two steps. The 1st phase, performed under Threads_lock, would return | |
2801 // a closure that'd be invoked after Threads_lock was dropped. | |
2802 // This tactic is safe as PlatformEvent and Parkers are type-stable (TSM) and | |
2803 // admit spurious wakeups. | |
2804 | |
2805 JVM_ENTRY(void, JVM_Interrupt(JNIEnv* env, jobject jthread)) | |
2806 JVMWrapper("JVM_Interrupt"); | |
2807 | |
2808 // Ensure that the C++ Thread and OSThread structures aren't freed before we operate | |
2809 oop java_thread = JNIHandles::resolve_non_null(jthread); | |
2810 MutexLockerEx ml(thread->threadObj() == java_thread ? NULL : Threads_lock); | |
2811 // We need to re-resolve the java_thread, since a GC might have happened during the | |
2812 // acquire of the lock | |
2813 JavaThread* thr = java_lang_Thread::thread(JNIHandles::resolve_non_null(jthread)); | |
2814 if (thr != NULL) { | |
2815 Thread::interrupt(thr); | |
2816 } | |
2817 JVM_END | |
2818 | |
2819 | |
2820 JVM_QUICK_ENTRY(jboolean, JVM_IsInterrupted(JNIEnv* env, jobject jthread, jboolean clear_interrupted)) | |
2821 JVMWrapper("JVM_IsInterrupted"); | |
2822 | |
2823 // Ensure that the C++ Thread and OSThread structures aren't freed before we operate | |
2824 oop java_thread = JNIHandles::resolve_non_null(jthread); | |
2825 MutexLockerEx ml(thread->threadObj() == java_thread ? NULL : Threads_lock); | |
2826 // We need to re-resolve the java_thread, since a GC might have happened during the | |
2827 // acquire of the lock | |
2828 JavaThread* thr = java_lang_Thread::thread(JNIHandles::resolve_non_null(jthread)); | |
2829 if (thr == NULL) { | |
2830 return JNI_FALSE; | |
2831 } else { | |
2832 return (jboolean) Thread::is_interrupted(thr, clear_interrupted != 0); | |
2833 } | |
2834 JVM_END | |
2835 | |
2836 | |
2837 // Return true iff the current thread has locked the object passed in | |
2838 | |
2839 JVM_ENTRY(jboolean, JVM_HoldsLock(JNIEnv* env, jclass threadClass, jobject obj)) | |
2840 JVMWrapper("JVM_HoldsLock"); | |
2841 assert(THREAD->is_Java_thread(), "sanity check"); | |
2842 if (obj == NULL) { | |
2843 THROW_(vmSymbols::java_lang_NullPointerException(), JNI_FALSE); | |
2844 } | |
2845 Handle h_obj(THREAD, JNIHandles::resolve(obj)); | |
2846 return ObjectSynchronizer::current_thread_holds_lock((JavaThread*)THREAD, h_obj); | |
2847 JVM_END | |
2848 | |
2849 | |
2850 JVM_ENTRY(void, JVM_DumpAllStacks(JNIEnv* env, jclass)) | |
2851 JVMWrapper("JVM_DumpAllStacks"); | |
2852 VM_PrintThreads op; | |
2853 VMThread::execute(&op); | |
2854 if (JvmtiExport::should_post_data_dump()) { | |
2855 JvmtiExport::post_data_dump(); | |
2856 } | |
2857 JVM_END | |
2858 | |
2859 | |
2860 // java.lang.SecurityManager /////////////////////////////////////////////////////////////////////// | |
2861 | |
2862 static bool is_trusted_frame(JavaThread* jthread, vframeStream* vfst) { | |
2863 assert(jthread->is_Java_thread(), "must be a Java thread"); | |
2864 if (jthread->privileged_stack_top() == NULL) return false; | |
2865 if (jthread->privileged_stack_top()->frame_id() == vfst->frame_id()) { | |
2866 oop loader = jthread->privileged_stack_top()->class_loader(); | |
2867 if (loader == NULL) return true; | |
2868 bool trusted = java_lang_ClassLoader::is_trusted_loader(loader); | |
2869 if (trusted) return true; | |
2870 } | |
2871 return false; | |
2872 } | |
2873 | |
2874 JVM_ENTRY(jclass, JVM_CurrentLoadedClass(JNIEnv *env)) | |
2875 JVMWrapper("JVM_CurrentLoadedClass"); | |
2876 ResourceMark rm(THREAD); | |
2877 | |
2878 for (vframeStream vfst(thread); !vfst.at_end(); vfst.next()) { | |
2879 // if a method in a class in a trusted loader is in a doPrivileged, return NULL | |
2880 bool trusted = is_trusted_frame(thread, &vfst); | |
2881 if (trusted) return NULL; | |
2882 | |
2883 methodOop m = vfst.method(); | |
2884 if (!m->is_native()) { | |
2885 klassOop holder = m->method_holder(); | |
2886 oop loader = instanceKlass::cast(holder)->class_loader(); | |
2887 if (loader != NULL && !java_lang_ClassLoader::is_trusted_loader(loader)) { | |
2888 return (jclass) JNIHandles::make_local(env, Klass::cast(holder)->java_mirror()); | |
2889 } | |
2890 } | |
2891 } | |
2892 return NULL; | |
2893 JVM_END | |
2894 | |
2895 | |
2896 JVM_ENTRY(jobject, JVM_CurrentClassLoader(JNIEnv *env)) | |
2897 JVMWrapper("JVM_CurrentClassLoader"); | |
2898 ResourceMark rm(THREAD); | |
2899 | |
2900 for (vframeStream vfst(thread); !vfst.at_end(); vfst.next()) { | |
2901 | |
2902 // if a method in a class in a trusted loader is in a doPrivileged, return NULL | |
2903 bool trusted = is_trusted_frame(thread, &vfst); | |
2904 if (trusted) return NULL; | |
2905 | |
2906 methodOop m = vfst.method(); | |
2907 if (!m->is_native()) { | |
2908 klassOop holder = m->method_holder(); | |
2909 assert(holder->is_klass(), "just checking"); | |
2910 oop loader = instanceKlass::cast(holder)->class_loader(); | |
2911 if (loader != NULL && !java_lang_ClassLoader::is_trusted_loader(loader)) { | |
2912 return JNIHandles::make_local(env, loader); | |
2913 } | |
2914 } | |
2915 } | |
2916 return NULL; | |
2917 JVM_END | |
2918 | |
2919 | |
2920 // Utility object for collecting method holders walking down the stack | |
2921 class KlassLink: public ResourceObj { | |
2922 public: | |
2923 KlassHandle klass; | |
2924 KlassLink* next; | |
2925 | |
2926 KlassLink(KlassHandle k) { klass = k; next = NULL; } | |
2927 }; | |
2928 | |
2929 | |
2930 JVM_ENTRY(jobjectArray, JVM_GetClassContext(JNIEnv *env)) | |
2931 JVMWrapper("JVM_GetClassContext"); | |
2932 ResourceMark rm(THREAD); | |
2933 JvmtiVMObjectAllocEventCollector oam; | |
2934 // Collect linked list of (handles to) method holders | |
2935 KlassLink* first = NULL; | |
2936 KlassLink* last = NULL; | |
2937 int depth = 0; | |
2938 | |
2939 for(vframeStream vfst(thread); !vfst.at_end(); vfst.security_get_caller_frame(1)) { | |
2940 // Native frames are not returned | |
2941 if (!vfst.method()->is_native()) { | |
2942 klassOop holder = vfst.method()->method_holder(); | |
2943 assert(holder->is_klass(), "just checking"); | |
2944 depth++; | |
2945 KlassLink* l = new KlassLink(KlassHandle(thread, holder)); | |
2946 if (first == NULL) { | |
2947 first = last = l; | |
2948 } else { | |
2949 last->next = l; | |
2950 last = l; | |
2951 } | |
2952 } | |
2953 } | |
2954 | |
2955 // Create result array of type [Ljava/lang/Class; | |
2956 objArrayOop result = oopFactory::new_objArray(SystemDictionary::class_klass(), depth, CHECK_NULL); | |
2957 // Fill in mirrors corresponding to method holders | |
2958 int index = 0; | |
2959 while (first != NULL) { | |
2960 result->obj_at_put(index++, Klass::cast(first->klass())->java_mirror()); | |
2961 first = first->next; | |
2962 } | |
2963 assert(index == depth, "just checking"); | |
2964 | |
2965 return (jobjectArray) JNIHandles::make_local(env, result); | |
2966 JVM_END | |
2967 | |
2968 | |
2969 JVM_ENTRY(jint, JVM_ClassDepth(JNIEnv *env, jstring name)) | |
2970 JVMWrapper("JVM_ClassDepth"); | |
2971 ResourceMark rm(THREAD); | |
2972 Handle h_name (THREAD, JNIHandles::resolve_non_null(name)); | |
2973 Handle class_name_str = java_lang_String::internalize_classname(h_name, CHECK_0); | |
2974 | |
2975 const char* str = java_lang_String::as_utf8_string(class_name_str()); | |
2976 symbolHandle class_name_sym = | |
2977 symbolHandle(THREAD, SymbolTable::probe(str, (int)strlen(str))); | |
2978 if (class_name_sym.is_null()) { | |
2979 return -1; | |
2980 } | |
2981 | |
2982 int depth = 0; | |
2983 | |
2984 for(vframeStream vfst(thread); !vfst.at_end(); vfst.next()) { | |
2985 if (!vfst.method()->is_native()) { | |
2986 klassOop holder = vfst.method()->method_holder(); | |
2987 assert(holder->is_klass(), "just checking"); | |
2988 if (instanceKlass::cast(holder)->name() == class_name_sym()) { | |
2989 return depth; | |
2990 } | |
2991 depth++; | |
2992 } | |
2993 } | |
2994 return -1; | |
2995 JVM_END | |
2996 | |
2997 | |
2998 JVM_ENTRY(jint, JVM_ClassLoaderDepth(JNIEnv *env)) | |
2999 JVMWrapper("JVM_ClassLoaderDepth"); | |
3000 ResourceMark rm(THREAD); | |
3001 int depth = 0; | |
3002 for (vframeStream vfst(thread); !vfst.at_end(); vfst.next()) { | |
3003 // if a method in a class in a trusted loader is in a doPrivileged, return -1 | |
3004 bool trusted = is_trusted_frame(thread, &vfst); | |
3005 if (trusted) return -1; | |
3006 | |
3007 methodOop m = vfst.method(); | |
3008 if (!m->is_native()) { | |
3009 klassOop holder = m->method_holder(); | |
3010 assert(holder->is_klass(), "just checking"); | |
3011 oop loader = instanceKlass::cast(holder)->class_loader(); | |
3012 if (loader != NULL && !java_lang_ClassLoader::is_trusted_loader(loader)) { | |
3013 return depth; | |
3014 } | |
3015 depth++; | |
3016 } | |
3017 } | |
3018 return -1; | |
3019 JVM_END | |
3020 | |
3021 | |
3022 // java.lang.Package //////////////////////////////////////////////////////////////// | |
3023 | |
3024 | |
3025 JVM_ENTRY(jstring, JVM_GetSystemPackage(JNIEnv *env, jstring name)) | |
3026 JVMWrapper("JVM_GetSystemPackage"); | |
3027 ResourceMark rm(THREAD); | |
3028 JvmtiVMObjectAllocEventCollector oam; | |
3029 char* str = java_lang_String::as_utf8_string(JNIHandles::resolve_non_null(name)); | |
3030 oop result = ClassLoader::get_system_package(str, CHECK_NULL); | |
3031 return (jstring) JNIHandles::make_local(result); | |
3032 JVM_END | |
3033 | |
3034 | |
3035 JVM_ENTRY(jobjectArray, JVM_GetSystemPackages(JNIEnv *env)) | |
3036 JVMWrapper("JVM_GetSystemPackages"); | |
3037 JvmtiVMObjectAllocEventCollector oam; | |
3038 objArrayOop result = ClassLoader::get_system_packages(CHECK_NULL); | |
3039 return (jobjectArray) JNIHandles::make_local(result); | |
3040 JVM_END | |
3041 | |
3042 | |
3043 // ObjectInputStream /////////////////////////////////////////////////////////////// | |
3044 | |
3045 bool force_verify_field_access(klassOop current_class, klassOop field_class, AccessFlags access, bool classloader_only) { | |
3046 if (current_class == NULL) { | |
3047 return true; | |
3048 } | |
3049 if ((current_class == field_class) || access.is_public()) { | |
3050 return true; | |
3051 } | |
3052 | |
3053 if (access.is_protected()) { | |
3054 // See if current_class is a subclass of field_class | |
3055 if (Klass::cast(current_class)->is_subclass_of(field_class)) { | |
3056 return true; | |
3057 } | |
3058 } | |
3059 | |
3060 return (!access.is_private() && instanceKlass::cast(current_class)->is_same_class_package(field_class)); | |
3061 } | |
3062 | |
3063 | |
3064 // JVM_AllocateNewObject and JVM_AllocateNewArray are unused as of 1.4 | |
3065 JVM_ENTRY(jobject, JVM_AllocateNewObject(JNIEnv *env, jobject receiver, jclass currClass, jclass initClass)) | |
3066 JVMWrapper("JVM_AllocateNewObject"); | |
3067 JvmtiVMObjectAllocEventCollector oam; | |
3068 // Receiver is not used | |
3069 oop curr_mirror = JNIHandles::resolve_non_null(currClass); | |
3070 oop init_mirror = JNIHandles::resolve_non_null(initClass); | |
3071 | |
3072 // Cannot instantiate primitive types | |
3073 if (java_lang_Class::is_primitive(curr_mirror) || java_lang_Class::is_primitive(init_mirror)) { | |
3074 ResourceMark rm(THREAD); | |
3075 THROW_0(vmSymbols::java_lang_InvalidClassException()); | |
3076 } | |
3077 | |
3078 // Arrays not allowed here, must use JVM_AllocateNewArray | |
3079 if (Klass::cast(java_lang_Class::as_klassOop(curr_mirror))->oop_is_javaArray() || | |
3080 Klass::cast(java_lang_Class::as_klassOop(init_mirror))->oop_is_javaArray()) { | |
3081 ResourceMark rm(THREAD); | |
3082 THROW_0(vmSymbols::java_lang_InvalidClassException()); | |
3083 } | |
3084 | |
3085 instanceKlassHandle curr_klass (THREAD, java_lang_Class::as_klassOop(curr_mirror)); | |
3086 instanceKlassHandle init_klass (THREAD, java_lang_Class::as_klassOop(init_mirror)); | |
3087 | |
3088 assert(curr_klass->is_subclass_of(init_klass()), "just checking"); | |
3089 | |
3090 // Interfaces, abstract classes, and java.lang.Class classes cannot be instantiated directly. | |
3091 curr_klass->check_valid_for_instantiation(false, CHECK_NULL); | |
3092 | |
3093 // Make sure klass is initialized, since we are about to instantiate one of them. | |
3094 curr_klass->initialize(CHECK_NULL); | |
3095 | |
3096 methodHandle m (THREAD, | |
3097 init_klass->find_method(vmSymbols::object_initializer_name(), | |
3098 vmSymbols::void_method_signature())); | |
3099 if (m.is_null()) { | |
3100 ResourceMark rm(THREAD); | |
3101 THROW_MSG_0(vmSymbols::java_lang_NoSuchMethodError(), | |
3102 methodOopDesc::name_and_sig_as_C_string(Klass::cast(init_klass()), | |
3103 vmSymbols::object_initializer_name(), | |
3104 vmSymbols::void_method_signature())); | |
3105 } | |
3106 | |
3107 if (curr_klass == init_klass && !m->is_public()) { | |
3108 // Calling the constructor for class 'curr_klass'. | |
3109 // Only allow calls to a public no-arg constructor. | |
3110 // This path corresponds to creating an Externalizable object. | |
3111 THROW_0(vmSymbols::java_lang_IllegalAccessException()); | |
3112 } | |
3113 | |
3114 if (!force_verify_field_access(curr_klass(), init_klass(), m->access_flags(), false)) { | |
3115 // subclass 'curr_klass' does not have access to no-arg constructor of 'initcb' | |
3116 THROW_0(vmSymbols::java_lang_IllegalAccessException()); | |
3117 } | |
3118 | |
3119 Handle obj = curr_klass->allocate_instance_handle(CHECK_NULL); | |
3120 // Call constructor m. This might call a constructor higher up in the hierachy | |
3121 JavaCalls::call_default_constructor(thread, m, obj, CHECK_NULL); | |
3122 | |
3123 return JNIHandles::make_local(obj()); | |
3124 JVM_END | |
3125 | |
3126 | |
3127 JVM_ENTRY(jobject, JVM_AllocateNewArray(JNIEnv *env, jobject obj, jclass currClass, jint length)) | |
3128 JVMWrapper("JVM_AllocateNewArray"); | |
3129 JvmtiVMObjectAllocEventCollector oam; | |
3130 oop mirror = JNIHandles::resolve_non_null(currClass); | |
3131 | |
3132 if (java_lang_Class::is_primitive(mirror)) { | |
3133 THROW_0(vmSymbols::java_lang_InvalidClassException()); | |
3134 } | |
3135 klassOop k = java_lang_Class::as_klassOop(mirror); | |
3136 oop result; | |
3137 | |
3138 if (k->klass_part()->oop_is_typeArray()) { | |
3139 // typeArray | |
3140 result = typeArrayKlass::cast(k)->allocate(length, CHECK_NULL); | |
3141 } else if (k->klass_part()->oop_is_objArray()) { | |
3142 // objArray | |
3143 objArrayKlassHandle oak(THREAD, k); | |
3144 oak->initialize(CHECK_NULL); // make sure class is initialized (matches Classic VM behavior) | |
3145 result = oak->allocate(length, CHECK_NULL); | |
3146 } else { | |
3147 THROW_0(vmSymbols::java_lang_InvalidClassException()); | |
3148 } | |
3149 return JNIHandles::make_local(env, result); | |
3150 JVM_END | |
3151 | |
3152 | |
3153 // Return the first non-null class loader up the execution stack, or null | |
3154 // if only code from the null class loader is on the stack. | |
3155 | |
3156 JVM_ENTRY(jobject, JVM_LatestUserDefinedLoader(JNIEnv *env)) | |
3157 for (vframeStream vfst(thread); !vfst.at_end(); vfst.next()) { | |
3158 // UseNewReflection | |
3159 vfst.skip_reflection_related_frames(); // Only needed for 1.4 reflection | |
3160 klassOop holder = vfst.method()->method_holder(); | |
3161 oop loader = instanceKlass::cast(holder)->class_loader(); | |
3162 if (loader != NULL) { | |
3163 return JNIHandles::make_local(env, loader); | |
3164 } | |
3165 } | |
3166 return NULL; | |
3167 JVM_END | |
3168 | |
3169 | |
3170 // Load a class relative to the most recent class on the stack with a non-null | |
3171 // classloader. | |
3172 // This function has been deprecated and should not be considered part of the | |
3173 // specified JVM interface. | |
3174 | |
3175 JVM_ENTRY(jclass, JVM_LoadClass0(JNIEnv *env, jobject receiver, | |
3176 jclass currClass, jstring currClassName)) | |
3177 JVMWrapper("JVM_LoadClass0"); | |
3178 // Receiver is not used | |
3179 ResourceMark rm(THREAD); | |
3180 | |
3181 // Class name argument is not guaranteed to be in internal format | |
3182 Handle classname (THREAD, JNIHandles::resolve_non_null(currClassName)); | |
3183 Handle string = java_lang_String::internalize_classname(classname, CHECK_NULL); | |
3184 | |
3185 const char* str = java_lang_String::as_utf8_string(string()); | |
3186 | |
3187 if (str == NULL || (int)strlen(str) > symbolOopDesc::max_length()) { | |
3188 // It's impossible to create this class; the name cannot fit | |
3189 // into the constant pool. | |
3190 THROW_MSG_0(vmSymbols::java_lang_NoClassDefFoundError(), str); | |
3191 } | |
3192 | |
3193 symbolHandle name = oopFactory::new_symbol_handle(str, CHECK_NULL); | |
3194 Handle curr_klass (THREAD, JNIHandles::resolve(currClass)); | |
3195 // Find the most recent class on the stack with a non-null classloader | |
3196 oop loader = NULL; | |
3197 oop protection_domain = NULL; | |
3198 if (curr_klass.is_null()) { | |
3199 for (vframeStream vfst(thread); | |
3200 !vfst.at_end() && loader == NULL; | |
3201 vfst.next()) { | |
3202 if (!vfst.method()->is_native()) { | |
3203 klassOop holder = vfst.method()->method_holder(); | |
3204 loader = instanceKlass::cast(holder)->class_loader(); | |
3205 protection_domain = instanceKlass::cast(holder)->protection_domain(); | |
3206 } | |
3207 } | |
3208 } else { | |
3209 klassOop curr_klass_oop = java_lang_Class::as_klassOop(curr_klass()); | |
3210 loader = instanceKlass::cast(curr_klass_oop)->class_loader(); | |
3211 protection_domain = instanceKlass::cast(curr_klass_oop)->protection_domain(); | |
3212 } | |
3213 Handle h_loader(THREAD, loader); | |
3214 Handle h_prot (THREAD, protection_domain); | |
3215 return find_class_from_class_loader(env, name, true, h_loader, h_prot, | |
3216 false, thread); | |
3217 JVM_END | |
3218 | |
3219 | |
3220 // Array /////////////////////////////////////////////////////////////////////////////////////////// | |
3221 | |
3222 | |
3223 // resolve array handle and check arguments | |
3224 static inline arrayOop check_array(JNIEnv *env, jobject arr, bool type_array_only, TRAPS) { | |
3225 if (arr == NULL) { | |
3226 THROW_0(vmSymbols::java_lang_NullPointerException()); | |
3227 } | |
3228 oop a = JNIHandles::resolve_non_null(arr); | |
3229 if (!a->is_javaArray() || (type_array_only && !a->is_typeArray())) { | |
3230 THROW_MSG_0(vmSymbols::java_lang_IllegalArgumentException(), "Argument is not an array"); | |
3231 } | |
3232 return arrayOop(a); | |
3233 } | |
3234 | |
3235 | |
3236 JVM_ENTRY(jint, JVM_GetArrayLength(JNIEnv *env, jobject arr)) | |
3237 JVMWrapper("JVM_GetArrayLength"); | |
3238 arrayOop a = check_array(env, arr, false, CHECK_0); | |
3239 return a->length(); | |
3240 JVM_END | |
3241 | |
3242 | |
3243 JVM_ENTRY(jobject, JVM_GetArrayElement(JNIEnv *env, jobject arr, jint index)) | |
3244 JVMWrapper("JVM_Array_Get"); | |
3245 JvmtiVMObjectAllocEventCollector oam; | |
3246 arrayOop a = check_array(env, arr, false, CHECK_NULL); | |
3247 jvalue value; | |
3248 BasicType type = Reflection::array_get(&value, a, index, CHECK_NULL); | |
3249 oop box = Reflection::box(&value, type, CHECK_NULL); | |
3250 return JNIHandles::make_local(env, box); | |
3251 JVM_END | |
3252 | |
3253 | |
3254 JVM_ENTRY(jvalue, JVM_GetPrimitiveArrayElement(JNIEnv *env, jobject arr, jint index, jint wCode)) | |
3255 JVMWrapper("JVM_GetPrimitiveArrayElement"); | |
3256 jvalue value; | |
3257 value.i = 0; // to initialize value before getting used in CHECK | |
3258 arrayOop a = check_array(env, arr, true, CHECK_(value)); | |
3259 assert(a->is_typeArray(), "just checking"); | |
3260 BasicType type = Reflection::array_get(&value, a, index, CHECK_(value)); | |
3261 BasicType wide_type = (BasicType) wCode; | |
3262 if (type != wide_type) { | |
3263 Reflection::widen(&value, type, wide_type, CHECK_(value)); | |
3264 } | |
3265 return value; | |
3266 JVM_END | |
3267 | |
3268 | |
3269 JVM_ENTRY(void, JVM_SetArrayElement(JNIEnv *env, jobject arr, jint index, jobject val)) | |
3270 JVMWrapper("JVM_SetArrayElement"); | |
3271 arrayOop a = check_array(env, arr, false, CHECK); | |
3272 oop box = JNIHandles::resolve(val); | |
3273 jvalue value; | |
3274 value.i = 0; // to initialize value before getting used in CHECK | |
3275 BasicType value_type; | |
3276 if (a->is_objArray()) { | |
3277 // Make sure we do no unbox e.g. java/lang/Integer instances when storing into an object array | |
3278 value_type = Reflection::unbox_for_regular_object(box, &value); | |
3279 } else { | |
3280 value_type = Reflection::unbox_for_primitive(box, &value, CHECK); | |
3281 } | |
3282 Reflection::array_set(&value, a, index, value_type, CHECK); | |
3283 JVM_END | |
3284 | |
3285 | |
3286 JVM_ENTRY(void, JVM_SetPrimitiveArrayElement(JNIEnv *env, jobject arr, jint index, jvalue v, unsigned char vCode)) | |
3287 JVMWrapper("JVM_SetPrimitiveArrayElement"); | |
3288 arrayOop a = check_array(env, arr, true, CHECK); | |
3289 assert(a->is_typeArray(), "just checking"); | |
3290 BasicType value_type = (BasicType) vCode; | |
3291 Reflection::array_set(&v, a, index, value_type, CHECK); | |
3292 JVM_END | |
3293 | |
3294 | |
3295 JVM_ENTRY(jobject, JVM_NewArray(JNIEnv *env, jclass eltClass, jint length)) | |
3296 JVMWrapper("JVM_NewArray"); | |
3297 JvmtiVMObjectAllocEventCollector oam; | |
3298 oop element_mirror = JNIHandles::resolve(eltClass); | |
3299 oop result = Reflection::reflect_new_array(element_mirror, length, CHECK_NULL); | |
3300 return JNIHandles::make_local(env, result); | |
3301 JVM_END | |
3302 | |
3303 | |
3304 JVM_ENTRY(jobject, JVM_NewMultiArray(JNIEnv *env, jclass eltClass, jintArray dim)) | |
3305 JVMWrapper("JVM_NewMultiArray"); | |
3306 JvmtiVMObjectAllocEventCollector oam; | |
3307 arrayOop dim_array = check_array(env, dim, true, CHECK_NULL); | |
3308 oop element_mirror = JNIHandles::resolve(eltClass); | |
3309 assert(dim_array->is_typeArray(), "just checking"); | |
3310 oop result = Reflection::reflect_new_multi_array(element_mirror, typeArrayOop(dim_array), CHECK_NULL); | |
3311 return JNIHandles::make_local(env, result); | |
3312 JVM_END | |
3313 | |
3314 | |
3315 // Networking library support //////////////////////////////////////////////////////////////////// | |
3316 | |
3317 JVM_LEAF(jint, JVM_InitializeSocketLibrary()) | |
3318 JVMWrapper("JVM_InitializeSocketLibrary"); | |
3319 return hpi::initialize_socket_library(); | |
3320 JVM_END | |
3321 | |
3322 | |
3323 JVM_LEAF(jint, JVM_Socket(jint domain, jint type, jint protocol)) | |
3324 JVMWrapper("JVM_Socket"); | |
3325 return hpi::socket(domain, type, protocol); | |
3326 JVM_END | |
3327 | |
3328 | |
3329 JVM_LEAF(jint, JVM_SocketClose(jint fd)) | |
3330 JVMWrapper2("JVM_SocketClose (0x%x)", fd); | |
3331 //%note jvm_r6 | |
3332 return hpi::socket_close(fd); | |
3333 JVM_END | |
3334 | |
3335 | |
3336 JVM_LEAF(jint, JVM_SocketShutdown(jint fd, jint howto)) | |
3337 JVMWrapper2("JVM_SocketShutdown (0x%x)", fd); | |
3338 //%note jvm_r6 | |
3339 return hpi::socket_shutdown(fd, howto); | |
3340 JVM_END | |
3341 | |
3342 | |
3343 JVM_LEAF(jint, JVM_Recv(jint fd, char *buf, jint nBytes, jint flags)) | |
3344 JVMWrapper2("JVM_Recv (0x%x)", fd); | |
3345 //%note jvm_r6 | |
3346 return hpi::recv(fd, buf, nBytes, flags); | |
3347 JVM_END | |
3348 | |
3349 | |
3350 JVM_LEAF(jint, JVM_Send(jint fd, char *buf, jint nBytes, jint flags)) | |
3351 JVMWrapper2("JVM_Send (0x%x)", fd); | |
3352 //%note jvm_r6 | |
3353 return hpi::send(fd, buf, nBytes, flags); | |
3354 JVM_END | |
3355 | |
3356 | |
3357 JVM_LEAF(jint, JVM_Timeout(int fd, long timeout)) | |
3358 JVMWrapper2("JVM_Timeout (0x%x)", fd); | |
3359 //%note jvm_r6 | |
3360 return hpi::timeout(fd, timeout); | |
3361 JVM_END | |
3362 | |
3363 | |
3364 JVM_LEAF(jint, JVM_Listen(jint fd, jint count)) | |
3365 JVMWrapper2("JVM_Listen (0x%x)", fd); | |
3366 //%note jvm_r6 | |
3367 return hpi::listen(fd, count); | |
3368 JVM_END | |
3369 | |
3370 | |
3371 JVM_LEAF(jint, JVM_Connect(jint fd, struct sockaddr *him, jint len)) | |
3372 JVMWrapper2("JVM_Connect (0x%x)", fd); | |
3373 //%note jvm_r6 | |
3374 return hpi::connect(fd, him, len); | |
3375 JVM_END | |
3376 | |
3377 | |
3378 JVM_LEAF(jint, JVM_Bind(jint fd, struct sockaddr *him, jint len)) | |
3379 JVMWrapper2("JVM_Bind (0x%x)", fd); | |
3380 //%note jvm_r6 | |
3381 return hpi::bind(fd, him, len); | |
3382 JVM_END | |
3383 | |
3384 | |
3385 JVM_LEAF(jint, JVM_Accept(jint fd, struct sockaddr *him, jint *len)) | |
3386 JVMWrapper2("JVM_Accept (0x%x)", fd); | |
3387 //%note jvm_r6 | |
3388 return hpi::accept(fd, him, (int *)len); | |
3389 JVM_END | |
3390 | |
3391 | |
3392 JVM_LEAF(jint, JVM_RecvFrom(jint fd, char *buf, int nBytes, int flags, struct sockaddr *from, int *fromlen)) | |
3393 JVMWrapper2("JVM_RecvFrom (0x%x)", fd); | |
3394 //%note jvm_r6 | |
3395 return hpi::recvfrom(fd, buf, nBytes, flags, from, fromlen); | |
3396 JVM_END | |
3397 | |
3398 | |
3399 JVM_LEAF(jint, JVM_GetSockName(jint fd, struct sockaddr *him, int *len)) | |
3400 JVMWrapper2("JVM_GetSockName (0x%x)", fd); | |
3401 //%note jvm_r6 | |
3402 return hpi::get_sock_name(fd, him, len); | |
3403 JVM_END | |
3404 | |
3405 | |
3406 JVM_LEAF(jint, JVM_SendTo(jint fd, char *buf, int len, int flags, struct sockaddr *to, int tolen)) | |
3407 JVMWrapper2("JVM_SendTo (0x%x)", fd); | |
3408 //%note jvm_r6 | |
3409 return hpi::sendto(fd, buf, len, flags, to, tolen); | |
3410 JVM_END | |
3411 | |
3412 | |
3413 JVM_LEAF(jint, JVM_SocketAvailable(jint fd, jint *pbytes)) | |
3414 JVMWrapper2("JVM_SocketAvailable (0x%x)", fd); | |
3415 //%note jvm_r6 | |
3416 return hpi::socket_available(fd, pbytes); | |
3417 JVM_END | |
3418 | |
3419 | |
3420 JVM_LEAF(jint, JVM_GetSockOpt(jint fd, int level, int optname, char *optval, int *optlen)) | |
3421 JVMWrapper2("JVM_GetSockOpt (0x%x)", fd); | |
3422 //%note jvm_r6 | |
3423 return hpi::get_sock_opt(fd, level, optname, optval, optlen); | |
3424 JVM_END | |
3425 | |
3426 | |
3427 JVM_LEAF(jint, JVM_SetSockOpt(jint fd, int level, int optname, const char *optval, int optlen)) | |
3428 JVMWrapper2("JVM_GetSockOpt (0x%x)", fd); | |
3429 //%note jvm_r6 | |
3430 return hpi::set_sock_opt(fd, level, optname, optval, optlen); | |
3431 JVM_END | |
3432 | |
3433 JVM_LEAF(int, JVM_GetHostName(char* name, int namelen)) | |
3434 JVMWrapper("JVM_GetHostName"); | |
3435 return hpi::get_host_name(name, namelen); | |
3436 JVM_END | |
3437 | |
3438 #ifdef _WINDOWS | |
3439 | |
3440 JVM_LEAF(struct hostent*, JVM_GetHostByAddr(const char* name, int len, int type)) | |
3441 JVMWrapper("JVM_GetHostByAddr"); | |
3442 return hpi::get_host_by_addr(name, len, type); | |
3443 JVM_END | |
3444 | |
3445 | |
3446 JVM_LEAF(struct hostent*, JVM_GetHostByName(char* name)) | |
3447 JVMWrapper("JVM_GetHostByName"); | |
3448 return hpi::get_host_by_name(name); | |
3449 JVM_END | |
3450 | |
3451 | |
3452 JVM_LEAF(struct protoent*, JVM_GetProtoByName(char* name)) | |
3453 JVMWrapper("JVM_GetProtoByName"); | |
3454 return hpi::get_proto_by_name(name); | |
3455 JVM_END | |
3456 | |
3457 #endif | |
3458 | |
3459 // Library support /////////////////////////////////////////////////////////////////////////// | |
3460 | |
3461 JVM_ENTRY_NO_ENV(void*, JVM_LoadLibrary(const char* name)) | |
3462 //%note jvm_ct | |
3463 JVMWrapper2("JVM_LoadLibrary (%s)", name); | |
3464 char ebuf[1024]; | |
3465 void *load_result; | |
3466 { | |
3467 ThreadToNativeFromVM ttnfvm(thread); | |
3468 load_result = hpi::dll_load(name, ebuf, sizeof ebuf); | |
3469 } | |
3470 if (load_result == NULL) { | |
3471 char msg[1024]; | |
3472 jio_snprintf(msg, sizeof msg, "%s: %s", name, ebuf); | |
3473 // Since 'ebuf' may contain a string encoded using | |
3474 // platform encoding scheme, we need to pass | |
3475 // Exceptions::unsafe_to_utf8 to the new_exception method | |
3476 // as the last argument. See bug 6367357. | |
3477 Handle h_exception = | |
3478 Exceptions::new_exception(thread, | |
3479 vmSymbols::java_lang_UnsatisfiedLinkError(), | |
3480 msg, Exceptions::unsafe_to_utf8); | |
3481 | |
3482 THROW_HANDLE_0(h_exception); | |
3483 } | |
3484 return load_result; | |
3485 JVM_END | |
3486 | |
3487 | |
3488 JVM_LEAF(void, JVM_UnloadLibrary(void* handle)) | |
3489 JVMWrapper("JVM_UnloadLibrary"); | |
3490 hpi::dll_unload(handle); | |
3491 JVM_END | |
3492 | |
3493 | |
3494 JVM_LEAF(void*, JVM_FindLibraryEntry(void* handle, const char* name)) | |
3495 JVMWrapper2("JVM_FindLibraryEntry (%s)", name); | |
3496 return hpi::dll_lookup(handle, name); | |
3497 JVM_END | |
3498 | |
3499 // Floating point support //////////////////////////////////////////////////////////////////// | |
3500 | |
3501 JVM_LEAF(jboolean, JVM_IsNaN(jdouble a)) | |
3502 JVMWrapper("JVM_IsNaN"); | |
3503 return g_isnan(a); | |
3504 JVM_END | |
3505 | |
3506 | |
3507 | |
3508 // JNI version /////////////////////////////////////////////////////////////////////////////// | |
3509 | |
3510 JVM_LEAF(jboolean, JVM_IsSupportedJNIVersion(jint version)) | |
3511 JVMWrapper2("JVM_IsSupportedJNIVersion (%d)", version); | |
3512 return Threads::is_supported_jni_version_including_1_1(version); | |
3513 JVM_END | |
3514 | |
3515 | |
3516 // String support /////////////////////////////////////////////////////////////////////////// | |
3517 | |
3518 JVM_ENTRY(jstring, JVM_InternString(JNIEnv *env, jstring str)) | |
3519 JVMWrapper("JVM_InternString"); | |
3520 JvmtiVMObjectAllocEventCollector oam; | |
3521 if (str == NULL) return NULL; | |
3522 oop string = JNIHandles::resolve_non_null(str); | |
3523 oop result = StringTable::intern(string, CHECK_NULL); | |
3524 return (jstring) JNIHandles::make_local(env, result); | |
3525 JVM_END | |
3526 | |
3527 | |
3528 // Raw monitor support ////////////////////////////////////////////////////////////////////// | |
3529 | |
3530 // The lock routine below calls lock_without_safepoint_check in order to get a raw lock | |
3531 // without interfering with the safepoint mechanism. The routines are not JVM_LEAF because | |
3532 // they might be called by non-java threads. The JVM_LEAF installs a NoHandleMark check | |
3533 // that only works with java threads. | |
3534 | |
3535 | |
3536 JNIEXPORT void* JNICALL JVM_RawMonitorCreate(void) { | |
3537 VM_Exit::block_if_vm_exited(); | |
3538 JVMWrapper("JVM_RawMonitorCreate"); | |
3539 return new Mutex(Mutex::native, "JVM_RawMonitorCreate"); | |
3540 } | |
3541 | |
3542 | |
3543 JNIEXPORT void JNICALL JVM_RawMonitorDestroy(void *mon) { | |
3544 VM_Exit::block_if_vm_exited(); | |
3545 JVMWrapper("JVM_RawMonitorDestroy"); | |
3546 delete ((Mutex*) mon); | |
3547 } | |
3548 | |
3549 | |
3550 JNIEXPORT jint JNICALL JVM_RawMonitorEnter(void *mon) { | |
3551 VM_Exit::block_if_vm_exited(); | |
3552 JVMWrapper("JVM_RawMonitorEnter"); | |
3553 ((Mutex*) mon)->jvm_raw_lock(); | |
3554 return 0; | |
3555 } | |
3556 | |
3557 | |
3558 JNIEXPORT void JNICALL JVM_RawMonitorExit(void *mon) { | |
3559 VM_Exit::block_if_vm_exited(); | |
3560 JVMWrapper("JVM_RawMonitorExit"); | |
3561 ((Mutex*) mon)->jvm_raw_unlock(); | |
3562 } | |
3563 | |
3564 | |
3565 // Support for Serialization | |
3566 | |
3567 typedef jfloat (JNICALL *IntBitsToFloatFn )(JNIEnv* env, jclass cb, jint value); | |
3568 typedef jdouble (JNICALL *LongBitsToDoubleFn)(JNIEnv* env, jclass cb, jlong value); | |
3569 typedef jint (JNICALL *FloatToIntBitsFn )(JNIEnv* env, jclass cb, jfloat value); | |
3570 typedef jlong (JNICALL *DoubleToLongBitsFn)(JNIEnv* env, jclass cb, jdouble value); | |
3571 | |
3572 static IntBitsToFloatFn int_bits_to_float_fn = NULL; | |
3573 static LongBitsToDoubleFn long_bits_to_double_fn = NULL; | |
3574 static FloatToIntBitsFn float_to_int_bits_fn = NULL; | |
3575 static DoubleToLongBitsFn double_to_long_bits_fn = NULL; | |
3576 | |
3577 | |
3578 void initialize_converter_functions() { | |
3579 if (JDK_Version::is_gte_jdk14x_version()) { | |
3580 // These functions only exist for compatibility with 1.3.1 and earlier | |
3581 return; | |
3582 } | |
3583 | |
3584 // called from universe_post_init() | |
3585 assert( | |
3586 int_bits_to_float_fn == NULL && | |
3587 long_bits_to_double_fn == NULL && | |
3588 float_to_int_bits_fn == NULL && | |
3589 double_to_long_bits_fn == NULL , | |
3590 "initialization done twice" | |
3591 ); | |
3592 // initialize | |
3593 int_bits_to_float_fn = CAST_TO_FN_PTR(IntBitsToFloatFn , NativeLookup::base_library_lookup("java/lang/Float" , "intBitsToFloat" , "(I)F")); | |
3594 long_bits_to_double_fn = CAST_TO_FN_PTR(LongBitsToDoubleFn, NativeLookup::base_library_lookup("java/lang/Double", "longBitsToDouble", "(J)D")); | |
3595 float_to_int_bits_fn = CAST_TO_FN_PTR(FloatToIntBitsFn , NativeLookup::base_library_lookup("java/lang/Float" , "floatToIntBits" , "(F)I")); | |
3596 double_to_long_bits_fn = CAST_TO_FN_PTR(DoubleToLongBitsFn, NativeLookup::base_library_lookup("java/lang/Double", "doubleToLongBits", "(D)J")); | |
3597 // verify | |
3598 assert( | |
3599 int_bits_to_float_fn != NULL && | |
3600 long_bits_to_double_fn != NULL && | |
3601 float_to_int_bits_fn != NULL && | |
3602 double_to_long_bits_fn != NULL , | |
3603 "initialization failed" | |
3604 ); | |
3605 } | |
3606 | |
3607 | |
3608 // Serialization | |
3609 JVM_ENTRY(void, JVM_SetPrimitiveFieldValues(JNIEnv *env, jclass cb, jobject obj, | |
3610 jlongArray fieldIDs, jcharArray typecodes, jbyteArray data)) | |
3611 assert(!JDK_Version::is_gte_jdk14x_version(), "should only be used in 1.3.1 and earlier"); | |
3612 | |
3613 typeArrayOop tcodes = typeArrayOop(JNIHandles::resolve(typecodes)); | |
3614 typeArrayOop dbuf = typeArrayOop(JNIHandles::resolve(data)); | |
3615 typeArrayOop fids = typeArrayOop(JNIHandles::resolve(fieldIDs)); | |
3616 oop o = JNIHandles::resolve(obj); | |
3617 | |
3618 if (o == NULL || fids == NULL || dbuf == NULL || tcodes == NULL) { | |
3619 THROW(vmSymbols::java_lang_NullPointerException()); | |
3620 } | |
3621 | |
3622 jsize nfids = fids->length(); | |
3623 if (nfids == 0) return; | |
3624 | |
3625 if (tcodes->length() < nfids) { | |
3626 THROW(vmSymbols::java_lang_ArrayIndexOutOfBoundsException()); | |
3627 } | |
3628 | |
3629 jsize off = 0; | |
3630 /* loop through fields, setting values */ | |
3631 for (jsize i = 0; i < nfids; i++) { | |
3632 jfieldID fid = (jfieldID)(intptr_t) fids->long_at(i); | |
3633 int field_offset; | |
3634 if (fid != NULL) { | |
3635 // NULL is a legal value for fid, but retrieving the field offset | |
3636 // trigger assertion in that case | |
3637 field_offset = jfieldIDWorkaround::from_instance_jfieldID(o->klass(), fid); | |
3638 } | |
3639 | |
3640 switch (tcodes->char_at(i)) { | |
3641 case 'Z': | |
3642 if (fid != NULL) { | |
3643 jboolean val = (dbuf->byte_at(off) != 0) ? JNI_TRUE : JNI_FALSE; | |
3644 o->bool_field_put(field_offset, val); | |
3645 } | |
3646 off++; | |
3647 break; | |
3648 | |
3649 case 'B': | |
3650 if (fid != NULL) { | |
3651 o->byte_field_put(field_offset, dbuf->byte_at(off)); | |
3652 } | |
3653 off++; | |
3654 break; | |
3655 | |
3656 case 'C': | |
3657 if (fid != NULL) { | |
3658 jchar val = ((dbuf->byte_at(off + 0) & 0xFF) << 8) | |
3659 + ((dbuf->byte_at(off + 1) & 0xFF) << 0); | |
3660 o->char_field_put(field_offset, val); | |
3661 } | |
3662 off += 2; | |
3663 break; | |
3664 | |
3665 case 'S': | |
3666 if (fid != NULL) { | |
3667 jshort val = ((dbuf->byte_at(off + 0) & 0xFF) << 8) | |
3668 + ((dbuf->byte_at(off + 1) & 0xFF) << 0); | |
3669 o->short_field_put(field_offset, val); | |
3670 } | |
3671 off += 2; | |
3672 break; | |
3673 | |
3674 case 'I': | |
3675 if (fid != NULL) { | |
3676 jint ival = ((dbuf->byte_at(off + 0) & 0xFF) << 24) | |
3677 + ((dbuf->byte_at(off + 1) & 0xFF) << 16) | |
3678 + ((dbuf->byte_at(off + 2) & 0xFF) << 8) | |
3679 + ((dbuf->byte_at(off + 3) & 0xFF) << 0); | |
3680 o->int_field_put(field_offset, ival); | |
3681 } | |
3682 off += 4; | |
3683 break; | |
3684 | |
3685 case 'F': | |
3686 if (fid != NULL) { | |
3687 jint ival = ((dbuf->byte_at(off + 0) & 0xFF) << 24) | |
3688 + ((dbuf->byte_at(off + 1) & 0xFF) << 16) | |
3689 + ((dbuf->byte_at(off + 2) & 0xFF) << 8) | |
3690 + ((dbuf->byte_at(off + 3) & 0xFF) << 0); | |
3691 jfloat fval = (*int_bits_to_float_fn)(env, NULL, ival); | |
3692 o->float_field_put(field_offset, fval); | |
3693 } | |
3694 off += 4; | |
3695 break; | |
3696 | |
3697 case 'J': | |
3698 if (fid != NULL) { | |
3699 jlong lval = (((jlong) dbuf->byte_at(off + 0) & 0xFF) << 56) | |
3700 + (((jlong) dbuf->byte_at(off + 1) & 0xFF) << 48) | |
3701 + (((jlong) dbuf->byte_at(off + 2) & 0xFF) << 40) | |
3702 + (((jlong) dbuf->byte_at(off + 3) & 0xFF) << 32) | |
3703 + (((jlong) dbuf->byte_at(off + 4) & 0xFF) << 24) | |
3704 + (((jlong) dbuf->byte_at(off + 5) & 0xFF) << 16) | |
3705 + (((jlong) dbuf->byte_at(off + 6) & 0xFF) << 8) | |
3706 + (((jlong) dbuf->byte_at(off + 7) & 0xFF) << 0); | |
3707 o->long_field_put(field_offset, lval); | |
3708 } | |
3709 off += 8; | |
3710 break; | |
3711 | |
3712 case 'D': | |
3713 if (fid != NULL) { | |
3714 jlong lval = (((jlong) dbuf->byte_at(off + 0) & 0xFF) << 56) | |
3715 + (((jlong) dbuf->byte_at(off + 1) & 0xFF) << 48) | |
3716 + (((jlong) dbuf->byte_at(off + 2) & 0xFF) << 40) | |
3717 + (((jlong) dbuf->byte_at(off + 3) & 0xFF) << 32) | |
3718 + (((jlong) dbuf->byte_at(off + 4) & 0xFF) << 24) | |
3719 + (((jlong) dbuf->byte_at(off + 5) & 0xFF) << 16) | |
3720 + (((jlong) dbuf->byte_at(off + 6) & 0xFF) << 8) | |
3721 + (((jlong) dbuf->byte_at(off + 7) & 0xFF) << 0); | |
3722 jdouble dval = (*long_bits_to_double_fn)(env, NULL, lval); | |
3723 o->double_field_put(field_offset, dval); | |
3724 } | |
3725 off += 8; | |
3726 break; | |
3727 | |
3728 default: | |
3729 // Illegal typecode | |
3730 THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(), "illegal typecode"); | |
3731 } | |
3732 } | |
3733 JVM_END | |
3734 | |
3735 | |
3736 JVM_ENTRY(void, JVM_GetPrimitiveFieldValues(JNIEnv *env, jclass cb, jobject obj, | |
3737 jlongArray fieldIDs, jcharArray typecodes, jbyteArray data)) | |
3738 assert(!JDK_Version::is_gte_jdk14x_version(), "should only be used in 1.3.1 and earlier"); | |
3739 | |
3740 typeArrayOop tcodes = typeArrayOop(JNIHandles::resolve(typecodes)); | |
3741 typeArrayOop dbuf = typeArrayOop(JNIHandles::resolve(data)); | |
3742 typeArrayOop fids = typeArrayOop(JNIHandles::resolve(fieldIDs)); | |
3743 oop o = JNIHandles::resolve(obj); | |
3744 | |
3745 if (o == NULL || fids == NULL || dbuf == NULL || tcodes == NULL) { | |
3746 THROW(vmSymbols::java_lang_NullPointerException()); | |
3747 } | |
3748 | |
3749 jsize nfids = fids->length(); | |
3750 if (nfids == 0) return; | |
3751 | |
3752 if (tcodes->length() < nfids) { | |
3753 THROW(vmSymbols::java_lang_ArrayIndexOutOfBoundsException()); | |
3754 } | |
3755 | |
3756 /* loop through fields, fetching values */ | |
3757 jsize off = 0; | |
3758 for (jsize i = 0; i < nfids; i++) { | |
3759 jfieldID fid = (jfieldID)(intptr_t) fids->long_at(i); | |
3760 if (fid == NULL) { | |
3761 THROW(vmSymbols::java_lang_NullPointerException()); | |
3762 } | |
3763 int field_offset = jfieldIDWorkaround::from_instance_jfieldID(o->klass(), fid); | |
3764 | |
3765 switch (tcodes->char_at(i)) { | |
3766 case 'Z': | |
3767 { | |
3768 jboolean val = o->bool_field(field_offset); | |
3769 dbuf->byte_at_put(off++, (val != 0) ? 1 : 0); | |
3770 } | |
3771 break; | |
3772 | |
3773 case 'B': | |
3774 dbuf->byte_at_put(off++, o->byte_field(field_offset)); | |
3775 break; | |
3776 | |
3777 case 'C': | |
3778 { | |
3779 jchar val = o->char_field(field_offset); | |
3780 dbuf->byte_at_put(off++, (val >> 8) & 0xFF); | |
3781 dbuf->byte_at_put(off++, (val >> 0) & 0xFF); | |
3782 } | |
3783 break; | |
3784 | |
3785 case 'S': | |
3786 { | |
3787 jshort val = o->short_field(field_offset); | |
3788 dbuf->byte_at_put(off++, (val >> 8) & 0xFF); | |
3789 dbuf->byte_at_put(off++, (val >> 0) & 0xFF); | |
3790 } | |
3791 break; | |
3792 | |
3793 case 'I': | |
3794 { | |
3795 jint val = o->int_field(field_offset); | |
3796 dbuf->byte_at_put(off++, (val >> 24) & 0xFF); | |
3797 dbuf->byte_at_put(off++, (val >> 16) & 0xFF); | |
3798 dbuf->byte_at_put(off++, (val >> 8) & 0xFF); | |
3799 dbuf->byte_at_put(off++, (val >> 0) & 0xFF); | |
3800 } | |
3801 break; | |
3802 | |
3803 case 'F': | |
3804 { | |
3805 jfloat fval = o->float_field(field_offset); | |
3806 jint ival = (*float_to_int_bits_fn)(env, NULL, fval); | |
3807 dbuf->byte_at_put(off++, (ival >> 24) & 0xFF); | |
3808 dbuf->byte_at_put(off++, (ival >> 16) & 0xFF); | |
3809 dbuf->byte_at_put(off++, (ival >> 8) & 0xFF); | |
3810 dbuf->byte_at_put(off++, (ival >> 0) & 0xFF); | |
3811 } | |
3812 break; | |
3813 | |
3814 case 'J': | |
3815 { | |
3816 jlong val = o->long_field(field_offset); | |
3817 dbuf->byte_at_put(off++, (val >> 56) & 0xFF); | |
3818 dbuf->byte_at_put(off++, (val >> 48) & 0xFF); | |
3819 dbuf->byte_at_put(off++, (val >> 40) & 0xFF); | |
3820 dbuf->byte_at_put(off++, (val >> 32) & 0xFF); | |
3821 dbuf->byte_at_put(off++, (val >> 24) & 0xFF); | |
3822 dbuf->byte_at_put(off++, (val >> 16) & 0xFF); | |
3823 dbuf->byte_at_put(off++, (val >> 8) & 0xFF); | |
3824 dbuf->byte_at_put(off++, (val >> 0) & 0xFF); | |
3825 } | |
3826 break; | |
3827 | |
3828 case 'D': | |
3829 { | |
3830 jdouble dval = o->double_field(field_offset); | |
3831 jlong lval = (*double_to_long_bits_fn)(env, NULL, dval); | |
3832 dbuf->byte_at_put(off++, (lval >> 56) & 0xFF); | |
3833 dbuf->byte_at_put(off++, (lval >> 48) & 0xFF); | |
3834 dbuf->byte_at_put(off++, (lval >> 40) & 0xFF); | |
3835 dbuf->byte_at_put(off++, (lval >> 32) & 0xFF); | |
3836 dbuf->byte_at_put(off++, (lval >> 24) & 0xFF); | |
3837 dbuf->byte_at_put(off++, (lval >> 16) & 0xFF); | |
3838 dbuf->byte_at_put(off++, (lval >> 8) & 0xFF); | |
3839 dbuf->byte_at_put(off++, (lval >> 0) & 0xFF); | |
3840 } | |
3841 break; | |
3842 | |
3843 default: | |
3844 // Illegal typecode | |
3845 THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(), "illegal typecode"); | |
3846 } | |
3847 } | |
3848 JVM_END | |
3849 | |
3850 | |
3851 // Shared JNI/JVM entry points ////////////////////////////////////////////////////////////// | |
3852 | |
3853 jclass find_class_from_class_loader(JNIEnv* env, symbolHandle name, jboolean init, Handle loader, Handle protection_domain, jboolean throwError, TRAPS) { | |
3854 // Security Note: | |
3855 // The Java level wrapper will perform the necessary security check allowing | |
3856 // us to pass the NULL as the initiating class loader. | |
3857 klassOop klass = SystemDictionary::resolve_or_fail(name, loader, protection_domain, throwError != 0, CHECK_NULL); | |
3858 KlassHandle klass_handle(THREAD, klass); | |
3859 // Check if we should initialize the class | |
3860 if (init && klass_handle->oop_is_instance()) { | |
3861 klass_handle->initialize(CHECK_NULL); | |
3862 } | |
3863 return (jclass) JNIHandles::make_local(env, klass_handle->java_mirror()); | |
3864 } | |
3865 | |
3866 | |
3867 // Internal SQE debugging support /////////////////////////////////////////////////////////// | |
3868 | |
3869 #ifndef PRODUCT | |
3870 | |
3871 extern "C" { | |
3872 JNIEXPORT jboolean JNICALL JVM_AccessVMBooleanFlag(const char* name, jboolean* value, jboolean is_get); | |
3873 JNIEXPORT jboolean JNICALL JVM_AccessVMIntFlag(const char* name, jint* value, jboolean is_get); | |
3874 JNIEXPORT void JNICALL JVM_VMBreakPoint(JNIEnv *env, jobject obj); | |
3875 } | |
3876 | |
3877 JVM_LEAF(jboolean, JVM_AccessVMBooleanFlag(const char* name, jboolean* value, jboolean is_get)) | |
3878 JVMWrapper("JVM_AccessBoolVMFlag"); | |
3879 return is_get ? CommandLineFlags::boolAt((char*) name, (bool*) value) : CommandLineFlags::boolAtPut((char*) name, (bool*) value, INTERNAL); | |
3880 JVM_END | |
3881 | |
3882 JVM_LEAF(jboolean, JVM_AccessVMIntFlag(const char* name, jint* value, jboolean is_get)) | |
3883 JVMWrapper("JVM_AccessVMIntFlag"); | |
3884 intx v; | |
3885 jboolean result = is_get ? CommandLineFlags::intxAt((char*) name, &v) : CommandLineFlags::intxAtPut((char*) name, &v, INTERNAL); | |
3886 *value = (jint)v; | |
3887 return result; | |
3888 JVM_END | |
3889 | |
3890 | |
3891 JVM_ENTRY(void, JVM_VMBreakPoint(JNIEnv *env, jobject obj)) | |
3892 JVMWrapper("JVM_VMBreakPoint"); | |
3893 oop the_obj = JNIHandles::resolve(obj); | |
3894 BREAKPOINT; | |
3895 JVM_END | |
3896 | |
3897 | |
3898 #endif | |
3899 | |
3900 | |
3901 //--------------------------------------------------------------------------- | |
3902 // | |
3903 // Support for old native code-based reflection (pre-JDK 1.4) | |
3904 // Disabled by default in the product build. | |
3905 // | |
3906 // See reflection.hpp for information on SUPPORT_OLD_REFLECTION | |
3907 // | |
3908 //--------------------------------------------------------------------------- | |
3909 | |
3910 #ifdef SUPPORT_OLD_REFLECTION | |
3911 | |
3912 JVM_ENTRY(jobjectArray, JVM_GetClassFields(JNIEnv *env, jclass cls, jint which)) | |
3913 JVMWrapper("JVM_GetClassFields"); | |
3914 JvmtiVMObjectAllocEventCollector oam; | |
3915 oop mirror = JNIHandles::resolve_non_null(cls); | |
3916 objArrayOop result = Reflection::reflect_fields(mirror, which, CHECK_NULL); | |
3917 return (jobjectArray) JNIHandles::make_local(env, result); | |
3918 JVM_END | |
3919 | |
3920 | |
3921 JVM_ENTRY(jobjectArray, JVM_GetClassMethods(JNIEnv *env, jclass cls, jint which)) | |
3922 JVMWrapper("JVM_GetClassMethods"); | |
3923 JvmtiVMObjectAllocEventCollector oam; | |
3924 oop mirror = JNIHandles::resolve_non_null(cls); | |
3925 objArrayOop result = Reflection::reflect_methods(mirror, which, CHECK_NULL); | |
3926 //%note jvm_r4 | |
3927 return (jobjectArray) JNIHandles::make_local(env, result); | |
3928 JVM_END | |
3929 | |
3930 | |
3931 JVM_ENTRY(jobjectArray, JVM_GetClassConstructors(JNIEnv *env, jclass cls, jint which)) | |
3932 JVMWrapper("JVM_GetClassConstructors"); | |
3933 JvmtiVMObjectAllocEventCollector oam; | |
3934 oop mirror = JNIHandles::resolve_non_null(cls); | |
3935 objArrayOop result = Reflection::reflect_constructors(mirror, which, CHECK_NULL); | |
3936 //%note jvm_r4 | |
3937 return (jobjectArray) JNIHandles::make_local(env, result); | |
3938 JVM_END | |
3939 | |
3940 | |
3941 JVM_ENTRY(jobject, JVM_GetClassField(JNIEnv *env, jclass cls, jstring name, jint which)) | |
3942 JVMWrapper("JVM_GetClassField"); | |
3943 JvmtiVMObjectAllocEventCollector oam; | |
3944 if (name == NULL) return NULL; | |
3945 Handle str (THREAD, JNIHandles::resolve_non_null(name)); | |
3946 | |
3947 const char* cstr = java_lang_String::as_utf8_string(str()); | |
3948 symbolHandle field_name = | |
3949 symbolHandle(THREAD, SymbolTable::probe(cstr, (int)strlen(cstr))); | |
3950 if (field_name.is_null()) { | |
3951 THROW_0(vmSymbols::java_lang_NoSuchFieldException()); | |
3952 } | |
3953 | |
3954 oop mirror = JNIHandles::resolve_non_null(cls); | |
3955 oop result = Reflection::reflect_field(mirror, field_name(), which, CHECK_NULL); | |
3956 if (result == NULL) { | |
3957 THROW_0(vmSymbols::java_lang_NoSuchFieldException()); | |
3958 } | |
3959 return JNIHandles::make_local(env, result); | |
3960 JVM_END | |
3961 | |
3962 | |
3963 JVM_ENTRY(jobject, JVM_GetClassMethod(JNIEnv *env, jclass cls, jstring name, jobjectArray types, jint which)) | |
3964 JVMWrapper("JVM_GetClassMethod"); | |
3965 JvmtiVMObjectAllocEventCollector oam; | |
3966 if (name == NULL) { | |
3967 THROW_0(vmSymbols::java_lang_NullPointerException()); | |
3968 } | |
3969 Handle str (THREAD, JNIHandles::resolve_non_null(name)); | |
3970 | |
3971 const char* cstr = java_lang_String::as_utf8_string(str()); | |
3972 symbolHandle method_name = | |
3973 symbolHandle(THREAD, SymbolTable::probe(cstr, (int)strlen(cstr))); | |
3974 if (method_name.is_null()) { | |
3975 THROW_0(vmSymbols::java_lang_NoSuchMethodException()); | |
3976 } | |
3977 | |
3978 oop mirror = JNIHandles::resolve_non_null(cls); | |
3979 objArrayHandle tarray (THREAD, objArrayOop(JNIHandles::resolve(types))); | |
3980 oop result = Reflection::reflect_method(mirror, method_name, tarray, | |
3981 which, CHECK_NULL); | |
3982 if (result == NULL) { | |
3983 THROW_0(vmSymbols::java_lang_NoSuchMethodException()); | |
3984 } | |
3985 return JNIHandles::make_local(env, result); | |
3986 JVM_END | |
3987 | |
3988 | |
3989 JVM_ENTRY(jobject, JVM_GetClassConstructor(JNIEnv *env, jclass cls, jobjectArray types, jint which)) | |
3990 JVMWrapper("JVM_GetClassConstructor"); | |
3991 JvmtiVMObjectAllocEventCollector oam; | |
3992 oop mirror = JNIHandles::resolve_non_null(cls); | |
3993 objArrayHandle tarray (THREAD, objArrayOop(JNIHandles::resolve(types))); | |
3994 oop result = Reflection::reflect_constructor(mirror, tarray, which, CHECK_NULL); | |
3995 if (result == NULL) { | |
3996 THROW_0(vmSymbols::java_lang_NoSuchMethodException()); | |
3997 } | |
3998 return (jobject) JNIHandles::make_local(env, result); | |
3999 JVM_END | |
4000 | |
4001 | |
4002 // Instantiation /////////////////////////////////////////////////////////////////////////////// | |
4003 | |
4004 JVM_ENTRY(jobject, JVM_NewInstance(JNIEnv *env, jclass cls)) | |
4005 JVMWrapper("JVM_NewInstance"); | |
4006 Handle mirror(THREAD, JNIHandles::resolve_non_null(cls)); | |
4007 | |
4008 methodOop resolved_constructor = java_lang_Class::resolved_constructor(mirror()); | |
4009 if (resolved_constructor == NULL) { | |
4010 klassOop k = java_lang_Class::as_klassOop(mirror()); | |
4011 // The java.lang.Class object caches a resolved constructor if all the checks | |
4012 // below were done successfully and a constructor was found. | |
4013 | |
4014 // Do class based checks | |
4015 if (java_lang_Class::is_primitive(mirror())) { | |
4016 const char* msg = ""; | |
4017 if (mirror == Universe::bool_mirror()) msg = "java/lang/Boolean"; | |
4018 else if (mirror == Universe::char_mirror()) msg = "java/lang/Character"; | |
4019 else if (mirror == Universe::float_mirror()) msg = "java/lang/Float"; | |
4020 else if (mirror == Universe::double_mirror()) msg = "java/lang/Double"; | |
4021 else if (mirror == Universe::byte_mirror()) msg = "java/lang/Byte"; | |
4022 else if (mirror == Universe::short_mirror()) msg = "java/lang/Short"; | |
4023 else if (mirror == Universe::int_mirror()) msg = "java/lang/Integer"; | |
4024 else if (mirror == Universe::long_mirror()) msg = "java/lang/Long"; | |
4025 THROW_MSG_0(vmSymbols::java_lang_NullPointerException(), msg); | |
4026 } | |
4027 | |
4028 // Check whether we are allowed to instantiate this class | |
4029 Klass::cast(k)->check_valid_for_instantiation(false, CHECK_NULL); // Array classes get caught here | |
4030 instanceKlassHandle klass(THREAD, k); | |
4031 // Make sure class is initialized (also so all methods are rewritten) | |
4032 klass->initialize(CHECK_NULL); | |
4033 | |
4034 // Lookup default constructor | |
4035 resolved_constructor = klass->find_method(vmSymbols::object_initializer_name(), vmSymbols::void_method_signature()); | |
4036 if (resolved_constructor == NULL) { | |
4037 ResourceMark rm(THREAD); | |
4038 THROW_MSG_0(vmSymbols::java_lang_InstantiationException(), klass->external_name()); | |
4039 } | |
4040 | |
4041 // Cache result in java.lang.Class object. Does not have to be MT safe. | |
4042 java_lang_Class::set_resolved_constructor(mirror(), resolved_constructor); | |
4043 } | |
4044 | |
4045 assert(resolved_constructor != NULL, "sanity check"); | |
4046 methodHandle constructor = methodHandle(THREAD, resolved_constructor); | |
4047 | |
4048 // We have an initialized instanceKlass with a default constructor | |
4049 instanceKlassHandle klass(THREAD, java_lang_Class::as_klassOop(JNIHandles::resolve_non_null(cls))); | |
4050 assert(klass->is_initialized() || klass->is_being_initialized(), "sanity check"); | |
4051 | |
4052 // Do security check | |
4053 klassOop caller_klass = NULL; | |
4054 if (UsePrivilegedStack) { | |
4055 caller_klass = thread->security_get_caller_class(2); | |
4056 | |
4057 if (!Reflection::verify_class_access(caller_klass, klass(), false) || | |
4058 !Reflection::verify_field_access(caller_klass, | |
4059 klass(), | |
4060 klass(), | |
4061 constructor->access_flags(), | |
4062 false, | |
4063 true)) { | |
4064 ResourceMark rm(THREAD); | |
4065 THROW_MSG_0(vmSymbols::java_lang_IllegalAccessException(), klass->external_name()); | |
4066 } | |
4067 } | |
4068 | |
4069 // Allocate object and call constructor | |
4070 Handle receiver = klass->allocate_instance_handle(CHECK_NULL); | |
4071 JavaCalls::call_default_constructor(thread, constructor, receiver, CHECK_NULL); | |
4072 | |
4073 jobject res = JNIHandles::make_local(env, receiver()); | |
4074 if (JvmtiExport::should_post_vm_object_alloc()) { | |
4075 JvmtiExport::post_vm_object_alloc(JavaThread::current(), receiver()); | |
4076 } | |
4077 return res; | |
4078 JVM_END | |
4079 | |
4080 | |
4081 // Field //////////////////////////////////////////////////////////////////////////////////////////// | |
4082 | |
4083 JVM_ENTRY(jobject, JVM_GetField(JNIEnv *env, jobject field, jobject obj)) | |
4084 JVMWrapper("JVM_GetField"); | |
4085 JvmtiVMObjectAllocEventCollector oam; | |
4086 Handle field_mirror(thread, JNIHandles::resolve(field)); | |
4087 Handle receiver (thread, JNIHandles::resolve(obj)); | |
4088 fieldDescriptor fd; | |
4089 Reflection::resolve_field(field_mirror, receiver, &fd, false, CHECK_NULL); | |
4090 jvalue value; | |
4091 BasicType type = Reflection::field_get(&value, &fd, receiver); | |
4092 oop box = Reflection::box(&value, type, CHECK_NULL); | |
4093 return JNIHandles::make_local(env, box); | |
4094 JVM_END | |
4095 | |
4096 | |
4097 JVM_ENTRY(jvalue, JVM_GetPrimitiveField(JNIEnv *env, jobject field, jobject obj, unsigned char wCode)) | |
4098 JVMWrapper("JVM_GetPrimitiveField"); | |
4099 Handle field_mirror(thread, JNIHandles::resolve(field)); | |
4100 Handle receiver (thread, JNIHandles::resolve(obj)); | |
4101 fieldDescriptor fd; | |
4102 jvalue value; | |
4103 value.j = 0; | |
4104 Reflection::resolve_field(field_mirror, receiver, &fd, false, CHECK_(value)); | |
4105 BasicType type = Reflection::field_get(&value, &fd, receiver); | |
4106 BasicType wide_type = (BasicType) wCode; | |
4107 if (type != wide_type) { | |
4108 Reflection::widen(&value, type, wide_type, CHECK_(value)); | |
4109 } | |
4110 return value; | |
4111 JVM_END // should really be JVM_END, but that doesn't work for union types! | |
4112 | |
4113 | |
4114 JVM_ENTRY(void, JVM_SetField(JNIEnv *env, jobject field, jobject obj, jobject val)) | |
4115 JVMWrapper("JVM_SetField"); | |
4116 Handle field_mirror(thread, JNIHandles::resolve(field)); | |
4117 Handle receiver (thread, JNIHandles::resolve(obj)); | |
4118 oop box = JNIHandles::resolve(val); | |
4119 fieldDescriptor fd; | |
4120 Reflection::resolve_field(field_mirror, receiver, &fd, true, CHECK); | |
4121 BasicType field_type = fd.field_type(); | |
4122 jvalue value; | |
4123 BasicType value_type; | |
4124 if (field_type == T_OBJECT || field_type == T_ARRAY) { | |
4125 // Make sure we do no unbox e.g. java/lang/Integer instances when storing into an object array | |
4126 value_type = Reflection::unbox_for_regular_object(box, &value); | |
4127 Reflection::field_set(&value, &fd, receiver, field_type, CHECK); | |
4128 } else { | |
4129 value_type = Reflection::unbox_for_primitive(box, &value, CHECK); | |
4130 Reflection::field_set(&value, &fd, receiver, value_type, CHECK); | |
4131 } | |
4132 JVM_END | |
4133 | |
4134 | |
4135 JVM_ENTRY(void, JVM_SetPrimitiveField(JNIEnv *env, jobject field, jobject obj, jvalue v, unsigned char vCode)) | |
4136 JVMWrapper("JVM_SetPrimitiveField"); | |
4137 Handle field_mirror(thread, JNIHandles::resolve(field)); | |
4138 Handle receiver (thread, JNIHandles::resolve(obj)); | |
4139 fieldDescriptor fd; | |
4140 Reflection::resolve_field(field_mirror, receiver, &fd, true, CHECK); | |
4141 BasicType value_type = (BasicType) vCode; | |
4142 Reflection::field_set(&v, &fd, receiver, value_type, CHECK); | |
4143 JVM_END | |
4144 | |
4145 | |
4146 // Method /////////////////////////////////////////////////////////////////////////////////////////// | |
4147 | |
4148 JVM_ENTRY(jobject, JVM_InvokeMethod(JNIEnv *env, jobject method, jobject obj, jobjectArray args0)) | |
4149 JVMWrapper("JVM_InvokeMethod"); | |
4150 Handle method_handle; | |
4151 if (thread->stack_available((address) &method_handle) >= JVMInvokeMethodSlack) { | |
4152 method_handle = Handle(THREAD, JNIHandles::resolve(method)); | |
4153 Handle receiver(THREAD, JNIHandles::resolve(obj)); | |
4154 objArrayHandle args(THREAD, objArrayOop(JNIHandles::resolve(args0))); | |
4155 oop result = Reflection::invoke_method(method_handle(), receiver, args, CHECK_NULL); | |
4156 jobject res = JNIHandles::make_local(env, result); | |
4157 if (JvmtiExport::should_post_vm_object_alloc()) { | |
4158 oop ret_type = java_lang_reflect_Method::return_type(method_handle()); | |
4159 assert(ret_type != NULL, "sanity check: ret_type oop must not be NULL!"); | |
4160 if (java_lang_Class::is_primitive(ret_type)) { | |
4161 // Only for primitive type vm allocates memory for java object. | |
4162 // See box() method. | |
4163 JvmtiExport::post_vm_object_alloc(JavaThread::current(), result); | |
4164 } | |
4165 } | |
4166 return res; | |
4167 } else { | |
4168 THROW_0(vmSymbols::java_lang_StackOverflowError()); | |
4169 } | |
4170 JVM_END | |
4171 | |
4172 | |
4173 JVM_ENTRY(jobject, JVM_NewInstanceFromConstructor(JNIEnv *env, jobject c, jobjectArray args0)) | |
4174 JVMWrapper("JVM_NewInstanceFromConstructor"); | |
4175 oop constructor_mirror = JNIHandles::resolve(c); | |
4176 objArrayHandle args(THREAD, objArrayOop(JNIHandles::resolve(args0))); | |
4177 oop result = Reflection::invoke_constructor(constructor_mirror, args, CHECK_NULL); | |
4178 jobject res = JNIHandles::make_local(env, result); | |
4179 if (JvmtiExport::should_post_vm_object_alloc()) { | |
4180 JvmtiExport::post_vm_object_alloc(JavaThread::current(), result); | |
4181 } | |
4182 return res; | |
4183 JVM_END | |
4184 | |
4185 #endif /* SUPPORT_OLD_REFLECTION */ | |
4186 | |
4187 // Atomic /////////////////////////////////////////////////////////////////////////////////////////// | |
4188 | |
4189 JVM_LEAF(jboolean, JVM_SupportsCX8()) | |
4190 JVMWrapper("JVM_SupportsCX8"); | |
4191 return VM_Version::supports_cx8(); | |
4192 JVM_END | |
4193 | |
4194 | |
4195 JVM_ENTRY(jboolean, JVM_CX8Field(JNIEnv *env, jobject obj, jfieldID fid, jlong oldVal, jlong newVal)) | |
4196 JVMWrapper("JVM_CX8Field"); | |
4197 jlong res; | |
4198 oop o = JNIHandles::resolve(obj); | |
4199 intptr_t fldOffs = jfieldIDWorkaround::from_instance_jfieldID(o->klass(), fid); | |
4200 volatile jlong* addr = (volatile jlong*)((address)o + fldOffs); | |
4201 | |
4202 assert(VM_Version::supports_cx8(), "cx8 not supported"); | |
4203 res = Atomic::cmpxchg(newVal, addr, oldVal); | |
4204 | |
4205 return res == oldVal; | |
4206 JVM_END | |
4207 | |
116
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
0
diff
changeset
|
4208 // DTrace /////////////////////////////////////////////////////////////////// |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
0
diff
changeset
|
4209 |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
0
diff
changeset
|
4210 JVM_ENTRY(jint, JVM_DTraceGetVersion(JNIEnv* env)) |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
0
diff
changeset
|
4211 JVMWrapper("JVM_DTraceGetVersion"); |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
0
diff
changeset
|
4212 return (jint)JVM_TRACING_DTRACE_VERSION; |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
0
diff
changeset
|
4213 JVM_END |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
0
diff
changeset
|
4214 |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
0
diff
changeset
|
4215 JVM_ENTRY(jlong,JVM_DTraceActivate( |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
0
diff
changeset
|
4216 JNIEnv* env, jint version, jstring module_name, jint providers_count, |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
0
diff
changeset
|
4217 JVM_DTraceProvider* providers)) |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
0
diff
changeset
|
4218 JVMWrapper("JVM_DTraceActivate"); |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
0
diff
changeset
|
4219 return DTraceJSDT::activate( |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
0
diff
changeset
|
4220 version, module_name, providers_count, providers, CHECK_0); |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
0
diff
changeset
|
4221 JVM_END |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
0
diff
changeset
|
4222 |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
0
diff
changeset
|
4223 JVM_ENTRY(jboolean,JVM_DTraceIsProbeEnabled(JNIEnv* env, jmethodID method)) |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
0
diff
changeset
|
4224 JVMWrapper("JVM_DTraceIsProbeEnabled"); |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
0
diff
changeset
|
4225 return DTraceJSDT::is_probe_enabled(method); |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
0
diff
changeset
|
4226 JVM_END |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
0
diff
changeset
|
4227 |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
0
diff
changeset
|
4228 JVM_ENTRY(void,JVM_DTraceDispose(JNIEnv* env, jlong handle)) |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
0
diff
changeset
|
4229 JVMWrapper("JVM_DTraceDispose"); |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
0
diff
changeset
|
4230 DTraceJSDT::dispose(handle); |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
0
diff
changeset
|
4231 JVM_END |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
0
diff
changeset
|
4232 |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
0
diff
changeset
|
4233 JVM_ENTRY(jboolean,JVM_DTraceIsSupported(JNIEnv* env)) |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
0
diff
changeset
|
4234 JVMWrapper("JVM_DTraceIsSupported"); |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
0
diff
changeset
|
4235 return DTraceJSDT::is_supported(); |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
0
diff
changeset
|
4236 JVM_END |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
0
diff
changeset
|
4237 |
0 | 4238 // Returns an array of all live Thread objects (VM internal JavaThreads, |
4239 // jvmti agent threads, and JNI attaching threads are skipped) | |
4240 // See CR 6404306 regarding JNI attaching threads | |
4241 JVM_ENTRY(jobjectArray, JVM_GetAllThreads(JNIEnv *env, jclass dummy)) | |
4242 ResourceMark rm(THREAD); | |
4243 ThreadsListEnumerator tle(THREAD, false, false); | |
4244 JvmtiVMObjectAllocEventCollector oam; | |
4245 | |
4246 int num_threads = tle.num_threads(); | |
4247 objArrayOop r = oopFactory::new_objArray(SystemDictionary::thread_klass(), num_threads, CHECK_NULL); | |
4248 objArrayHandle threads_ah(THREAD, r); | |
4249 | |
4250 for (int i = 0; i < num_threads; i++) { | |
4251 Handle h = tle.get_threadObj(i); | |
4252 threads_ah->obj_at_put(i, h()); | |
4253 } | |
4254 | |
4255 return (jobjectArray) JNIHandles::make_local(env, threads_ah()); | |
4256 JVM_END | |
4257 | |
4258 | |
4259 // Support for java.lang.Thread.getStackTrace() and getAllStackTraces() methods | |
4260 // Return StackTraceElement[][], each element is the stack trace of a thread in | |
4261 // the corresponding entry in the given threads array | |
4262 JVM_ENTRY(jobjectArray, JVM_DumpThreads(JNIEnv *env, jclass threadClass, jobjectArray threads)) | |
4263 JVMWrapper("JVM_DumpThreads"); | |
4264 JvmtiVMObjectAllocEventCollector oam; | |
4265 | |
4266 // Check if threads is null | |
4267 if (threads == NULL) { | |
4268 THROW_(vmSymbols::java_lang_NullPointerException(), 0); | |
4269 } | |
4270 | |
4271 objArrayOop a = objArrayOop(JNIHandles::resolve_non_null(threads)); | |
4272 objArrayHandle ah(THREAD, a); | |
4273 int num_threads = ah->length(); | |
4274 // check if threads is non-empty array | |
4275 if (num_threads == 0) { | |
4276 THROW_(vmSymbols::java_lang_IllegalArgumentException(), 0); | |
4277 } | |
4278 | |
4279 // check if threads is not an array of objects of Thread class | |
4280 klassOop k = objArrayKlass::cast(ah->klass())->element_klass(); | |
4281 if (k != SystemDictionary::thread_klass()) { | |
4282 THROW_(vmSymbols::java_lang_IllegalArgumentException(), 0); | |
4283 } | |
4284 | |
4285 ResourceMark rm(THREAD); | |
4286 | |
4287 GrowableArray<instanceHandle>* thread_handle_array = new GrowableArray<instanceHandle>(num_threads); | |
4288 for (int i = 0; i < num_threads; i++) { | |
4289 oop thread_obj = ah->obj_at(i); | |
4290 instanceHandle h(THREAD, (instanceOop) thread_obj); | |
4291 thread_handle_array->append(h); | |
4292 } | |
4293 | |
4294 Handle stacktraces = ThreadService::dump_stack_traces(thread_handle_array, num_threads, CHECK_NULL); | |
4295 return (jobjectArray)JNIHandles::make_local(env, stacktraces()); | |
4296 | |
4297 JVM_END | |
4298 | |
4299 // JVM monitoring and management support | |
4300 JVM_ENTRY_NO_ENV(void*, JVM_GetManagement(jint version)) | |
4301 return Management::get_jmm_interface(version); | |
4302 JVM_END | |
4303 | |
4304 // com.sun.tools.attach.VirtualMachine agent properties support | |
4305 // | |
4306 // Initialize the agent properties with the properties maintained in the VM | |
4307 JVM_ENTRY(jobject, JVM_InitAgentProperties(JNIEnv *env, jobject properties)) | |
4308 JVMWrapper("JVM_InitAgentProperties"); | |
4309 ResourceMark rm; | |
4310 | |
4311 Handle props(THREAD, JNIHandles::resolve_non_null(properties)); | |
4312 | |
4313 PUTPROP(props, "sun.java.command", Arguments::java_command()); | |
4314 PUTPROP(props, "sun.jvm.flags", Arguments::jvm_flags()); | |
4315 PUTPROP(props, "sun.jvm.args", Arguments::jvm_args()); | |
4316 return properties; | |
4317 JVM_END | |
4318 | |
4319 JVM_ENTRY(jobjectArray, JVM_GetEnclosingMethodInfo(JNIEnv *env, jclass ofClass)) | |
4320 { | |
4321 JVMWrapper("JVM_GetEnclosingMethodInfo"); | |
4322 JvmtiVMObjectAllocEventCollector oam; | |
4323 | |
4324 if (ofClass == NULL) { | |
4325 return NULL; | |
4326 } | |
4327 Handle mirror(THREAD, JNIHandles::resolve_non_null(ofClass)); | |
4328 // Special handling for primitive objects | |
4329 if (java_lang_Class::is_primitive(mirror())) { | |
4330 return NULL; | |
4331 } | |
4332 klassOop k = java_lang_Class::as_klassOop(mirror()); | |
4333 if (!Klass::cast(k)->oop_is_instance()) { | |
4334 return NULL; | |
4335 } | |
4336 instanceKlassHandle ik_h(THREAD, k); | |
4337 int encl_method_class_idx = ik_h->enclosing_method_class_index(); | |
4338 if (encl_method_class_idx == 0) { | |
4339 return NULL; | |
4340 } | |
4341 objArrayOop dest_o = oopFactory::new_objArray(SystemDictionary::object_klass(), 3, CHECK_NULL); | |
4342 objArrayHandle dest(THREAD, dest_o); | |
4343 klassOop enc_k = ik_h->constants()->klass_at(encl_method_class_idx, CHECK_NULL); | |
4344 dest->obj_at_put(0, Klass::cast(enc_k)->java_mirror()); | |
4345 int encl_method_method_idx = ik_h->enclosing_method_method_index(); | |
4346 if (encl_method_method_idx != 0) { | |
4347 symbolOop sym_o = ik_h->constants()->symbol_at( | |
4348 extract_low_short_from_int( | |
4349 ik_h->constants()->name_and_type_at(encl_method_method_idx))); | |
4350 symbolHandle sym(THREAD, sym_o); | |
4351 Handle str = java_lang_String::create_from_symbol(sym, CHECK_NULL); | |
4352 dest->obj_at_put(1, str()); | |
4353 sym_o = ik_h->constants()->symbol_at( | |
4354 extract_high_short_from_int( | |
4355 ik_h->constants()->name_and_type_at(encl_method_method_idx))); | |
4356 sym = symbolHandle(THREAD, sym_o); | |
4357 str = java_lang_String::create_from_symbol(sym, CHECK_NULL); | |
4358 dest->obj_at_put(2, str()); | |
4359 } | |
4360 return (jobjectArray) JNIHandles::make_local(dest()); | |
4361 } | |
4362 JVM_END | |
4363 | |
4364 JVM_ENTRY(jintArray, JVM_GetThreadStateValues(JNIEnv* env, | |
4365 jint javaThreadState)) | |
4366 { | |
4367 // If new thread states are added in future JDK and VM versions, | |
4368 // this should check if the JDK version is compatible with thread | |
4369 // states supported by the VM. Return NULL if not compatible. | |
4370 // | |
4371 // This function must map the VM java_lang_Thread::ThreadStatus | |
4372 // to the Java thread state that the JDK supports. | |
4373 // | |
4374 | |
4375 typeArrayHandle values_h; | |
4376 switch (javaThreadState) { | |
4377 case JAVA_THREAD_STATE_NEW : { | |
4378 typeArrayOop r = oopFactory::new_typeArray(T_INT, 1, CHECK_NULL); | |
4379 values_h = typeArrayHandle(THREAD, r); | |
4380 values_h->int_at_put(0, java_lang_Thread::NEW); | |
4381 break; | |
4382 } | |
4383 case JAVA_THREAD_STATE_RUNNABLE : { | |
4384 typeArrayOop r = oopFactory::new_typeArray(T_INT, 1, CHECK_NULL); | |
4385 values_h = typeArrayHandle(THREAD, r); | |
4386 values_h->int_at_put(0, java_lang_Thread::RUNNABLE); | |
4387 break; | |
4388 } | |
4389 case JAVA_THREAD_STATE_BLOCKED : { | |
4390 typeArrayOop r = oopFactory::new_typeArray(T_INT, 1, CHECK_NULL); | |
4391 values_h = typeArrayHandle(THREAD, r); | |
4392 values_h->int_at_put(0, java_lang_Thread::BLOCKED_ON_MONITOR_ENTER); | |
4393 break; | |
4394 } | |
4395 case JAVA_THREAD_STATE_WAITING : { | |
4396 typeArrayOop r = oopFactory::new_typeArray(T_INT, 2, CHECK_NULL); | |
4397 values_h = typeArrayHandle(THREAD, r); | |
4398 values_h->int_at_put(0, java_lang_Thread::IN_OBJECT_WAIT); | |
4399 values_h->int_at_put(1, java_lang_Thread::PARKED); | |
4400 break; | |
4401 } | |
4402 case JAVA_THREAD_STATE_TIMED_WAITING : { | |
4403 typeArrayOop r = oopFactory::new_typeArray(T_INT, 3, CHECK_NULL); | |
4404 values_h = typeArrayHandle(THREAD, r); | |
4405 values_h->int_at_put(0, java_lang_Thread::SLEEPING); | |
4406 values_h->int_at_put(1, java_lang_Thread::IN_OBJECT_WAIT_TIMED); | |
4407 values_h->int_at_put(2, java_lang_Thread::PARKED_TIMED); | |
4408 break; | |
4409 } | |
4410 case JAVA_THREAD_STATE_TERMINATED : { | |
4411 typeArrayOop r = oopFactory::new_typeArray(T_INT, 1, CHECK_NULL); | |
4412 values_h = typeArrayHandle(THREAD, r); | |
4413 values_h->int_at_put(0, java_lang_Thread::TERMINATED); | |
4414 break; | |
4415 } | |
4416 default: | |
4417 // Unknown state - probably incompatible JDK version | |
4418 return NULL; | |
4419 } | |
4420 | |
4421 return (jintArray) JNIHandles::make_local(env, values_h()); | |
4422 } | |
4423 JVM_END | |
4424 | |
4425 | |
4426 JVM_ENTRY(jobjectArray, JVM_GetThreadStateNames(JNIEnv* env, | |
4427 jint javaThreadState, | |
4428 jintArray values)) | |
4429 { | |
4430 // If new thread states are added in future JDK and VM versions, | |
4431 // this should check if the JDK version is compatible with thread | |
4432 // states supported by the VM. Return NULL if not compatible. | |
4433 // | |
4434 // This function must map the VM java_lang_Thread::ThreadStatus | |
4435 // to the Java thread state that the JDK supports. | |
4436 // | |
4437 | |
4438 ResourceMark rm; | |
4439 | |
4440 // Check if threads is null | |
4441 if (values == NULL) { | |
4442 THROW_(vmSymbols::java_lang_NullPointerException(), 0); | |
4443 } | |
4444 | |
4445 typeArrayOop v = typeArrayOop(JNIHandles::resolve_non_null(values)); | |
4446 typeArrayHandle values_h(THREAD, v); | |
4447 | |
4448 objArrayHandle names_h; | |
4449 switch (javaThreadState) { | |
4450 case JAVA_THREAD_STATE_NEW : { | |
4451 assert(values_h->length() == 1 && | |
4452 values_h->int_at(0) == java_lang_Thread::NEW, | |
4453 "Invalid threadStatus value"); | |
4454 | |
4455 objArrayOop r = oopFactory::new_objArray(SystemDictionary::string_klass(), | |
4456 1, /* only 1 substate */ | |
4457 CHECK_NULL); | |
4458 names_h = objArrayHandle(THREAD, r); | |
4459 Handle name = java_lang_String::create_from_str("NEW", CHECK_NULL); | |
4460 names_h->obj_at_put(0, name()); | |
4461 break; | |
4462 } | |
4463 case JAVA_THREAD_STATE_RUNNABLE : { | |
4464 assert(values_h->length() == 1 && | |
4465 values_h->int_at(0) == java_lang_Thread::RUNNABLE, | |
4466 "Invalid threadStatus value"); | |
4467 | |
4468 objArrayOop r = oopFactory::new_objArray(SystemDictionary::string_klass(), | |
4469 1, /* only 1 substate */ | |
4470 CHECK_NULL); | |
4471 names_h = objArrayHandle(THREAD, r); | |
4472 Handle name = java_lang_String::create_from_str("RUNNABLE", CHECK_NULL); | |
4473 names_h->obj_at_put(0, name()); | |
4474 break; | |
4475 } | |
4476 case JAVA_THREAD_STATE_BLOCKED : { | |
4477 assert(values_h->length() == 1 && | |
4478 values_h->int_at(0) == java_lang_Thread::BLOCKED_ON_MONITOR_ENTER, | |
4479 "Invalid threadStatus value"); | |
4480 | |
4481 objArrayOop r = oopFactory::new_objArray(SystemDictionary::string_klass(), | |
4482 1, /* only 1 substate */ | |
4483 CHECK_NULL); | |
4484 names_h = objArrayHandle(THREAD, r); | |
4485 Handle name = java_lang_String::create_from_str("BLOCKED", CHECK_NULL); | |
4486 names_h->obj_at_put(0, name()); | |
4487 break; | |
4488 } | |
4489 case JAVA_THREAD_STATE_WAITING : { | |
4490 assert(values_h->length() == 2 && | |
4491 values_h->int_at(0) == java_lang_Thread::IN_OBJECT_WAIT && | |
4492 values_h->int_at(1) == java_lang_Thread::PARKED, | |
4493 "Invalid threadStatus value"); | |
4494 objArrayOop r = oopFactory::new_objArray(SystemDictionary::string_klass(), | |
4495 2, /* number of substates */ | |
4496 CHECK_NULL); | |
4497 names_h = objArrayHandle(THREAD, r); | |
4498 Handle name0 = java_lang_String::create_from_str("WAITING.OBJECT_WAIT", | |
4499 CHECK_NULL); | |
4500 Handle name1 = java_lang_String::create_from_str("WAITING.PARKED", | |
4501 CHECK_NULL); | |
4502 names_h->obj_at_put(0, name0()); | |
4503 names_h->obj_at_put(1, name1()); | |
4504 break; | |
4505 } | |
4506 case JAVA_THREAD_STATE_TIMED_WAITING : { | |
4507 assert(values_h->length() == 3 && | |
4508 values_h->int_at(0) == java_lang_Thread::SLEEPING && | |
4509 values_h->int_at(1) == java_lang_Thread::IN_OBJECT_WAIT_TIMED && | |
4510 values_h->int_at(2) == java_lang_Thread::PARKED_TIMED, | |
4511 "Invalid threadStatus value"); | |
4512 objArrayOop r = oopFactory::new_objArray(SystemDictionary::string_klass(), | |
4513 3, /* number of substates */ | |
4514 CHECK_NULL); | |
4515 names_h = objArrayHandle(THREAD, r); | |
4516 Handle name0 = java_lang_String::create_from_str("TIMED_WAITING.SLEEPING", | |
4517 CHECK_NULL); | |
4518 Handle name1 = java_lang_String::create_from_str("TIMED_WAITING.OBJECT_WAIT", | |
4519 CHECK_NULL); | |
4520 Handle name2 = java_lang_String::create_from_str("TIMED_WAITING.PARKED", | |
4521 CHECK_NULL); | |
4522 names_h->obj_at_put(0, name0()); | |
4523 names_h->obj_at_put(1, name1()); | |
4524 names_h->obj_at_put(2, name2()); | |
4525 break; | |
4526 } | |
4527 case JAVA_THREAD_STATE_TERMINATED : { | |
4528 assert(values_h->length() == 1 && | |
4529 values_h->int_at(0) == java_lang_Thread::TERMINATED, | |
4530 "Invalid threadStatus value"); | |
4531 objArrayOop r = oopFactory::new_objArray(SystemDictionary::string_klass(), | |
4532 1, /* only 1 substate */ | |
4533 CHECK_NULL); | |
4534 names_h = objArrayHandle(THREAD, r); | |
4535 Handle name = java_lang_String::create_from_str("TERMINATED", CHECK_NULL); | |
4536 names_h->obj_at_put(0, name()); | |
4537 break; | |
4538 } | |
4539 default: | |
4540 // Unknown state - probably incompatible JDK version | |
4541 return NULL; | |
4542 } | |
4543 return (jobjectArray) JNIHandles::make_local(env, names_h()); | |
4544 } | |
4545 JVM_END | |
4546 | |
4547 JVM_ENTRY(void, JVM_GetVersionInfo(JNIEnv* env, jvm_version_info* info, size_t info_size)) | |
4548 { | |
4549 memset(info, 0, sizeof(info_size)); | |
4550 | |
4551 info->jvm_version = Abstract_VM_Version::jvm_version(); | |
4552 info->update_version = 0; /* 0 in HotSpot Express VM */ | |
4553 info->special_update_version = 0; /* 0 in HotSpot Express VM */ | |
4554 | |
4555 // when we add a new capability in the jvm_version_info struct, we should also | |
4556 // consider to expose this new capability in the sun.rt.jvmCapabilities jvmstat | |
4557 // counter defined in runtimeService.cpp. | |
4558 info->is_attachable = AttachListener::is_attach_supported(); | |
4559 #ifdef KERNEL | |
4560 info->is_kernel_jvm = 1; // true; | |
4561 #else // KERNEL | |
4562 info->is_kernel_jvm = 0; // false; | |
4563 #endif // KERNEL | |
4564 } | |
4565 JVM_END | |
116
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
0
diff
changeset
|
4566 |