Tue, 23 Mar 2010 14:37:18 -0700
6915365: 3/4 assert(false,"Unsupported VMGlobal Type") at management.cpp:1540
Summary: Remove assert to decouple JDK and HotSpot additions of known types.
Reviewed-by: mchung
1 /*
2 * Copyright 2003-2009 Sun Microsystems, Inc. All Rights Reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation.
8 *
9 * This code is distributed in the hope that it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
12 * version 2 for more details (a copy is included in the LICENSE file that
13 * accompanied this code).
14 *
15 * You should have received a copy of the GNU General Public License version
16 * 2 along with this work; if not, write to the Free Software Foundation,
17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
18 *
19 * Please contact 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 */
25 # include "incls/_precompiled.incl"
26 # include "incls/_management.cpp.incl"
28 PerfVariable* Management::_begin_vm_creation_time = NULL;
29 PerfVariable* Management::_end_vm_creation_time = NULL;
30 PerfVariable* Management::_vm_init_done_time = NULL;
32 klassOop Management::_sensor_klass = NULL;
33 klassOop Management::_threadInfo_klass = NULL;
34 klassOop Management::_memoryUsage_klass = NULL;
35 klassOop Management::_memoryPoolMXBean_klass = NULL;
36 klassOop Management::_memoryManagerMXBean_klass = NULL;
37 klassOop Management::_garbageCollectorMXBean_klass = NULL;
38 klassOop Management::_managementFactory_klass = NULL;
40 jmmOptionalSupport Management::_optional_support = {0};
41 TimeStamp Management::_stamp;
43 void management_init() {
44 Management::init();
45 ThreadService::init();
46 RuntimeService::init();
47 ClassLoadingService::init();
48 }
50 void Management::init() {
51 EXCEPTION_MARK;
53 // These counters are for java.lang.management API support.
54 // They are created even if -XX:-UsePerfData is set and in
55 // that case, they will be allocated on C heap.
57 _begin_vm_creation_time =
58 PerfDataManager::create_variable(SUN_RT, "createVmBeginTime",
59 PerfData::U_None, CHECK);
61 _end_vm_creation_time =
62 PerfDataManager::create_variable(SUN_RT, "createVmEndTime",
63 PerfData::U_None, CHECK);
65 _vm_init_done_time =
66 PerfDataManager::create_variable(SUN_RT, "vmInitDoneTime",
67 PerfData::U_None, CHECK);
69 // Initialize optional support
70 _optional_support.isLowMemoryDetectionSupported = 1;
71 _optional_support.isCompilationTimeMonitoringSupported = 1;
72 _optional_support.isThreadContentionMonitoringSupported = 1;
74 if (os::is_thread_cpu_time_supported()) {
75 _optional_support.isCurrentThreadCpuTimeSupported = 1;
76 _optional_support.isOtherThreadCpuTimeSupported = 1;
77 } else {
78 _optional_support.isCurrentThreadCpuTimeSupported = 0;
79 _optional_support.isOtherThreadCpuTimeSupported = 0;
80 }
81 _optional_support.isBootClassPathSupported = 1;
82 _optional_support.isObjectMonitorUsageSupported = 1;
83 #ifndef SERVICES_KERNEL
84 // This depends on the heap inspector
85 _optional_support.isSynchronizerUsageSupported = 1;
86 #endif // SERVICES_KERNEL
87 }
89 void Management::initialize(TRAPS) {
90 // Start the low memory detector thread
91 LowMemoryDetector::initialize();
93 if (ManagementServer) {
94 ResourceMark rm(THREAD);
95 HandleMark hm(THREAD);
97 // Load and initialize the sun.management.Agent class
98 // invoke startAgent method to start the management server
99 Handle loader = Handle(THREAD, SystemDictionary::java_system_loader());
100 klassOop k = SystemDictionary::resolve_or_fail(vmSymbolHandles::sun_management_Agent(),
101 loader,
102 Handle(),
103 true,
104 CHECK);
105 instanceKlassHandle ik (THREAD, k);
107 JavaValue result(T_VOID);
108 JavaCalls::call_static(&result,
109 ik,
110 vmSymbolHandles::startAgent_name(),
111 vmSymbolHandles::void_method_signature(),
112 CHECK);
113 }
114 }
116 void Management::get_optional_support(jmmOptionalSupport* support) {
117 memcpy(support, &_optional_support, sizeof(jmmOptionalSupport));
118 }
120 klassOop Management::load_and_initialize_klass(symbolHandle sh, TRAPS) {
121 klassOop k = SystemDictionary::resolve_or_fail(sh, true, CHECK_NULL);
122 instanceKlassHandle ik (THREAD, k);
123 if (ik->should_be_initialized()) {
124 ik->initialize(CHECK_NULL);
125 }
126 return ik();
127 }
129 void Management::record_vm_startup_time(jlong begin, jlong duration) {
130 // if the performance counter is not initialized,
131 // then vm initialization failed; simply return.
132 if (_begin_vm_creation_time == NULL) return;
134 _begin_vm_creation_time->set_value(begin);
135 _end_vm_creation_time->set_value(begin + duration);
136 PerfMemory::set_accessible(true);
137 }
139 jlong Management::timestamp() {
140 TimeStamp t;
141 t.update();
142 return t.ticks() - _stamp.ticks();
143 }
145 void Management::oops_do(OopClosure* f) {
146 MemoryService::oops_do(f);
147 ThreadService::oops_do(f);
149 f->do_oop((oop*) &_sensor_klass);
150 f->do_oop((oop*) &_threadInfo_klass);
151 f->do_oop((oop*) &_memoryUsage_klass);
152 f->do_oop((oop*) &_memoryPoolMXBean_klass);
153 f->do_oop((oop*) &_memoryManagerMXBean_klass);
154 f->do_oop((oop*) &_garbageCollectorMXBean_klass);
155 f->do_oop((oop*) &_managementFactory_klass);
156 }
158 klassOop Management::java_lang_management_ThreadInfo_klass(TRAPS) {
159 if (_threadInfo_klass == NULL) {
160 _threadInfo_klass = load_and_initialize_klass(vmSymbolHandles::java_lang_management_ThreadInfo(), CHECK_NULL);
161 }
162 return _threadInfo_klass;
163 }
165 klassOop Management::java_lang_management_MemoryUsage_klass(TRAPS) {
166 if (_memoryUsage_klass == NULL) {
167 _memoryUsage_klass = load_and_initialize_klass(vmSymbolHandles::java_lang_management_MemoryUsage(), CHECK_NULL);
168 }
169 return _memoryUsage_klass;
170 }
172 klassOop Management::java_lang_management_MemoryPoolMXBean_klass(TRAPS) {
173 if (_memoryPoolMXBean_klass == NULL) {
174 _memoryPoolMXBean_klass = load_and_initialize_klass(vmSymbolHandles::java_lang_management_MemoryPoolMXBean(), CHECK_NULL);
175 }
176 return _memoryPoolMXBean_klass;
177 }
179 klassOop Management::java_lang_management_MemoryManagerMXBean_klass(TRAPS) {
180 if (_memoryManagerMXBean_klass == NULL) {
181 _memoryManagerMXBean_klass = load_and_initialize_klass(vmSymbolHandles::java_lang_management_MemoryManagerMXBean(), CHECK_NULL);
182 }
183 return _memoryManagerMXBean_klass;
184 }
186 klassOop Management::java_lang_management_GarbageCollectorMXBean_klass(TRAPS) {
187 if (_garbageCollectorMXBean_klass == NULL) {
188 _garbageCollectorMXBean_klass = load_and_initialize_klass(vmSymbolHandles::java_lang_management_GarbageCollectorMXBean(), CHECK_NULL);
189 }
190 return _garbageCollectorMXBean_klass;
191 }
193 klassOop Management::sun_management_Sensor_klass(TRAPS) {
194 if (_sensor_klass == NULL) {
195 _sensor_klass = load_and_initialize_klass(vmSymbolHandles::sun_management_Sensor(), CHECK_NULL);
196 }
197 return _sensor_klass;
198 }
200 klassOop Management::sun_management_ManagementFactory_klass(TRAPS) {
201 if (_managementFactory_klass == NULL) {
202 _managementFactory_klass = load_and_initialize_klass(vmSymbolHandles::sun_management_ManagementFactory(), CHECK_NULL);
203 }
204 return _managementFactory_klass;
205 }
207 static void initialize_ThreadInfo_constructor_arguments(JavaCallArguments* args, ThreadSnapshot* snapshot, TRAPS) {
208 Handle snapshot_thread(THREAD, snapshot->threadObj());
210 jlong contended_time;
211 jlong waited_time;
212 if (ThreadService::is_thread_monitoring_contention()) {
213 contended_time = Management::ticks_to_ms(snapshot->contended_enter_ticks());
214 waited_time = Management::ticks_to_ms(snapshot->monitor_wait_ticks() + snapshot->sleep_ticks());
215 } else {
216 // set them to -1 if thread contention monitoring is disabled.
217 contended_time = max_julong;
218 waited_time = max_julong;
219 }
221 int thread_status = snapshot->thread_status();
222 assert((thread_status & JMM_THREAD_STATE_FLAG_MASK) == 0, "Flags already set in thread_status in Thread object");
223 if (snapshot->is_ext_suspended()) {
224 thread_status |= JMM_THREAD_STATE_FLAG_SUSPENDED;
225 }
226 if (snapshot->is_in_native()) {
227 thread_status |= JMM_THREAD_STATE_FLAG_NATIVE;
228 }
230 ThreadStackTrace* st = snapshot->get_stack_trace();
231 Handle stacktrace_h;
232 if (st != NULL) {
233 stacktrace_h = st->allocate_fill_stack_trace_element_array(CHECK);
234 } else {
235 stacktrace_h = Handle();
236 }
238 args->push_oop(snapshot_thread);
239 args->push_int(thread_status);
240 args->push_oop(Handle(THREAD, snapshot->blocker_object()));
241 args->push_oop(Handle(THREAD, snapshot->blocker_object_owner()));
242 args->push_long(snapshot->contended_enter_count());
243 args->push_long(contended_time);
244 args->push_long(snapshot->monitor_wait_count() + snapshot->sleep_count());
245 args->push_long(waited_time);
246 args->push_oop(stacktrace_h);
247 }
249 // Helper function to construct a ThreadInfo object
250 instanceOop Management::create_thread_info_instance(ThreadSnapshot* snapshot, TRAPS) {
251 klassOop k = Management::java_lang_management_ThreadInfo_klass(CHECK_NULL);
252 instanceKlassHandle ik (THREAD, k);
254 JavaValue result(T_VOID);
255 JavaCallArguments args(14);
257 // First allocate a ThreadObj object and
258 // push the receiver as the first argument
259 Handle element = ik->allocate_instance_handle(CHECK_NULL);
260 args.push_oop(element);
262 // initialize the arguments for the ThreadInfo constructor
263 initialize_ThreadInfo_constructor_arguments(&args, snapshot, CHECK_NULL);
265 // Call ThreadInfo constructor with no locked monitors and synchronizers
266 JavaCalls::call_special(&result,
267 ik,
268 vmSymbolHandles::object_initializer_name(),
269 vmSymbolHandles::java_lang_management_ThreadInfo_constructor_signature(),
270 &args,
271 CHECK_NULL);
273 return (instanceOop) element();
274 }
276 instanceOop Management::create_thread_info_instance(ThreadSnapshot* snapshot,
277 objArrayHandle monitors_array,
278 typeArrayHandle depths_array,
279 objArrayHandle synchronizers_array,
280 TRAPS) {
281 klassOop k = Management::java_lang_management_ThreadInfo_klass(CHECK_NULL);
282 instanceKlassHandle ik (THREAD, k);
284 JavaValue result(T_VOID);
285 JavaCallArguments args(17);
287 // First allocate a ThreadObj object and
288 // push the receiver as the first argument
289 Handle element = ik->allocate_instance_handle(CHECK_NULL);
290 args.push_oop(element);
292 // initialize the arguments for the ThreadInfo constructor
293 initialize_ThreadInfo_constructor_arguments(&args, snapshot, CHECK_NULL);
295 // push the locked monitors and synchronizers in the arguments
296 args.push_oop(monitors_array);
297 args.push_oop(depths_array);
298 args.push_oop(synchronizers_array);
300 // Call ThreadInfo constructor with locked monitors and synchronizers
301 JavaCalls::call_special(&result,
302 ik,
303 vmSymbolHandles::object_initializer_name(),
304 vmSymbolHandles::java_lang_management_ThreadInfo_with_locks_constructor_signature(),
305 &args,
306 CHECK_NULL);
308 return (instanceOop) element();
309 }
311 // Helper functions
312 static JavaThread* find_java_thread_from_id(jlong thread_id) {
313 assert(Threads_lock->owned_by_self(), "Must hold Threads_lock");
315 JavaThread* java_thread = NULL;
316 // Sequential search for now. Need to do better optimization later.
317 for (JavaThread* thread = Threads::first(); thread != NULL; thread = thread->next()) {
318 oop tobj = thread->threadObj();
319 if (!thread->is_exiting() &&
320 tobj != NULL &&
321 thread_id == java_lang_Thread::thread_id(tobj)) {
322 java_thread = thread;
323 break;
324 }
325 }
326 return java_thread;
327 }
329 static GCMemoryManager* get_gc_memory_manager_from_jobject(jobject mgr, TRAPS) {
330 if (mgr == NULL) {
331 THROW_(vmSymbols::java_lang_NullPointerException(), NULL);
332 }
333 oop mgr_obj = JNIHandles::resolve(mgr);
334 instanceHandle h(THREAD, (instanceOop) mgr_obj);
336 klassOop k = Management::java_lang_management_GarbageCollectorMXBean_klass(CHECK_NULL);
337 if (!h->is_a(k)) {
338 THROW_MSG_(vmSymbols::java_lang_IllegalArgumentException(),
339 "the object is not an instance of java.lang.management.GarbageCollectorMXBean class",
340 NULL);
341 }
343 MemoryManager* gc = MemoryService::get_memory_manager(h);
344 if (gc == NULL || !gc->is_gc_memory_manager()) {
345 THROW_MSG_(vmSymbols::java_lang_IllegalArgumentException(),
346 "Invalid GC memory manager",
347 NULL);
348 }
349 return (GCMemoryManager*) gc;
350 }
352 static MemoryPool* get_memory_pool_from_jobject(jobject obj, TRAPS) {
353 if (obj == NULL) {
354 THROW_(vmSymbols::java_lang_NullPointerException(), NULL);
355 }
357 oop pool_obj = JNIHandles::resolve(obj);
358 assert(pool_obj->is_instance(), "Should be an instanceOop");
359 instanceHandle ph(THREAD, (instanceOop) pool_obj);
361 return MemoryService::get_memory_pool(ph);
362 }
364 static void validate_thread_id_array(typeArrayHandle ids_ah, TRAPS) {
365 int num_threads = ids_ah->length();
366 // should be non-empty array
367 if (num_threads == 0) {
368 THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(),
369 "Empty array of thread IDs");
370 }
372 // Validate input thread IDs
373 int i = 0;
374 for (i = 0; i < num_threads; i++) {
375 jlong tid = ids_ah->long_at(i);
376 if (tid <= 0) {
377 // throw exception if invalid thread id.
378 THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(),
379 "Invalid thread ID entry");
380 }
381 }
383 }
385 static void validate_thread_info_array(objArrayHandle infoArray_h, TRAPS) {
387 // check if the element of infoArray is of type ThreadInfo class
388 klassOop threadinfo_klass = Management::java_lang_management_ThreadInfo_klass(CHECK);
389 klassOop element_klass = objArrayKlass::cast(infoArray_h->klass())->element_klass();
390 if (element_klass != threadinfo_klass) {
391 THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(),
392 "infoArray element type is not ThreadInfo class");
393 }
395 }
398 static MemoryManager* get_memory_manager_from_jobject(jobject obj, TRAPS) {
399 if (obj == NULL) {
400 THROW_(vmSymbols::java_lang_NullPointerException(), NULL);
401 }
403 oop mgr_obj = JNIHandles::resolve(obj);
404 assert(mgr_obj->is_instance(), "Should be an instanceOop");
405 instanceHandle mh(THREAD, (instanceOop) mgr_obj);
407 return MemoryService::get_memory_manager(mh);
408 }
410 // Returns a version string and sets major and minor version if
411 // the input parameters are non-null.
412 JVM_LEAF(jint, jmm_GetVersion(JNIEnv *env))
413 return JMM_VERSION;
414 JVM_END
416 // Gets the list of VM monitoring and management optional supports
417 // Returns 0 if succeeded; otherwise returns non-zero.
418 JVM_LEAF(jint, jmm_GetOptionalSupport(JNIEnv *env, jmmOptionalSupport* support))
419 if (support == NULL) {
420 return -1;
421 }
422 Management::get_optional_support(support);
423 return 0;
424 JVM_END
426 // Returns a java.lang.String object containing the input arguments to the VM.
427 JVM_ENTRY(jobject, jmm_GetInputArguments(JNIEnv *env))
428 ResourceMark rm(THREAD);
430 if (Arguments::num_jvm_args() == 0 && Arguments::num_jvm_flags() == 0) {
431 return NULL;
432 }
434 char** vm_flags = Arguments::jvm_flags_array();
435 char** vm_args = Arguments::jvm_args_array();
436 int num_flags = Arguments::num_jvm_flags();
437 int num_args = Arguments::num_jvm_args();
439 size_t length = 1; // null terminator
440 int i;
441 for (i = 0; i < num_flags; i++) {
442 length += strlen(vm_flags[i]);
443 }
444 for (i = 0; i < num_args; i++) {
445 length += strlen(vm_args[i]);
446 }
447 // add a space between each argument
448 length += num_flags + num_args - 1;
450 // Return the list of input arguments passed to the VM
451 // and preserve the order that the VM processes.
452 char* args = NEW_RESOURCE_ARRAY(char, length);
453 args[0] = '\0';
454 // concatenate all jvm_flags
455 if (num_flags > 0) {
456 strcat(args, vm_flags[0]);
457 for (i = 1; i < num_flags; i++) {
458 strcat(args, " ");
459 strcat(args, vm_flags[i]);
460 }
461 }
463 if (num_args > 0 && num_flags > 0) {
464 // append a space if args already contains one or more jvm_flags
465 strcat(args, " ");
466 }
468 // concatenate all jvm_args
469 if (num_args > 0) {
470 strcat(args, vm_args[0]);
471 for (i = 1; i < num_args; i++) {
472 strcat(args, " ");
473 strcat(args, vm_args[i]);
474 }
475 }
477 Handle hargs = java_lang_String::create_from_platform_dependent_str(args, CHECK_NULL);
478 return JNIHandles::make_local(env, hargs());
479 JVM_END
481 // Returns an array of java.lang.String object containing the input arguments to the VM.
482 JVM_ENTRY(jobjectArray, jmm_GetInputArgumentArray(JNIEnv *env))
483 ResourceMark rm(THREAD);
485 if (Arguments::num_jvm_args() == 0 && Arguments::num_jvm_flags() == 0) {
486 return NULL;
487 }
489 char** vm_flags = Arguments::jvm_flags_array();
490 char** vm_args = Arguments::jvm_args_array();
491 int num_flags = Arguments::num_jvm_flags();
492 int num_args = Arguments::num_jvm_args();
494 instanceKlassHandle ik (THREAD, SystemDictionary::String_klass());
495 objArrayOop r = oopFactory::new_objArray(ik(), num_args + num_flags, CHECK_NULL);
496 objArrayHandle result_h(THREAD, r);
498 int index = 0;
499 for (int j = 0; j < num_flags; j++, index++) {
500 Handle h = java_lang_String::create_from_platform_dependent_str(vm_flags[j], CHECK_NULL);
501 result_h->obj_at_put(index, h());
502 }
503 for (int i = 0; i < num_args; i++, index++) {
504 Handle h = java_lang_String::create_from_platform_dependent_str(vm_args[i], CHECK_NULL);
505 result_h->obj_at_put(index, h());
506 }
507 return (jobjectArray) JNIHandles::make_local(env, result_h());
508 JVM_END
510 // Returns an array of java/lang/management/MemoryPoolMXBean object
511 // one for each memory pool if obj == null; otherwise returns
512 // an array of memory pools for a given memory manager if
513 // it is a valid memory manager.
514 JVM_ENTRY(jobjectArray, jmm_GetMemoryPools(JNIEnv* env, jobject obj))
515 ResourceMark rm(THREAD);
517 int num_memory_pools;
518 MemoryManager* mgr = NULL;
519 if (obj == NULL) {
520 num_memory_pools = MemoryService::num_memory_pools();
521 } else {
522 mgr = get_memory_manager_from_jobject(obj, CHECK_NULL);
523 if (mgr == NULL) {
524 return NULL;
525 }
526 num_memory_pools = mgr->num_memory_pools();
527 }
529 // Allocate the resulting MemoryPoolMXBean[] object
530 klassOop k = Management::java_lang_management_MemoryPoolMXBean_klass(CHECK_NULL);
531 instanceKlassHandle ik (THREAD, k);
532 objArrayOop r = oopFactory::new_objArray(ik(), num_memory_pools, CHECK_NULL);
533 objArrayHandle poolArray(THREAD, r);
535 if (mgr == NULL) {
536 // Get all memory pools
537 for (int i = 0; i < num_memory_pools; i++) {
538 MemoryPool* pool = MemoryService::get_memory_pool(i);
539 instanceOop p = pool->get_memory_pool_instance(CHECK_NULL);
540 instanceHandle ph(THREAD, p);
541 poolArray->obj_at_put(i, ph());
542 }
543 } else {
544 // Get memory pools managed by a given memory manager
545 for (int i = 0; i < num_memory_pools; i++) {
546 MemoryPool* pool = mgr->get_memory_pool(i);
547 instanceOop p = pool->get_memory_pool_instance(CHECK_NULL);
548 instanceHandle ph(THREAD, p);
549 poolArray->obj_at_put(i, ph());
550 }
551 }
552 return (jobjectArray) JNIHandles::make_local(env, poolArray());
553 JVM_END
555 // Returns an array of java/lang/management/MemoryManagerMXBean object
556 // one for each memory manager if obj == null; otherwise returns
557 // an array of memory managers for a given memory pool if
558 // it is a valid memory pool.
559 JVM_ENTRY(jobjectArray, jmm_GetMemoryManagers(JNIEnv* env, jobject obj))
560 ResourceMark rm(THREAD);
562 int num_mgrs;
563 MemoryPool* pool = NULL;
564 if (obj == NULL) {
565 num_mgrs = MemoryService::num_memory_managers();
566 } else {
567 pool = get_memory_pool_from_jobject(obj, CHECK_NULL);
568 if (pool == NULL) {
569 return NULL;
570 }
571 num_mgrs = pool->num_memory_managers();
572 }
574 // Allocate the resulting MemoryManagerMXBean[] object
575 klassOop k = Management::java_lang_management_MemoryManagerMXBean_klass(CHECK_NULL);
576 instanceKlassHandle ik (THREAD, k);
577 objArrayOop r = oopFactory::new_objArray(ik(), num_mgrs, CHECK_NULL);
578 objArrayHandle mgrArray(THREAD, r);
580 if (pool == NULL) {
581 // Get all memory managers
582 for (int i = 0; i < num_mgrs; i++) {
583 MemoryManager* mgr = MemoryService::get_memory_manager(i);
584 instanceOop p = mgr->get_memory_manager_instance(CHECK_NULL);
585 instanceHandle ph(THREAD, p);
586 mgrArray->obj_at_put(i, ph());
587 }
588 } else {
589 // Get memory managers for a given memory pool
590 for (int i = 0; i < num_mgrs; i++) {
591 MemoryManager* mgr = pool->get_memory_manager(i);
592 instanceOop p = mgr->get_memory_manager_instance(CHECK_NULL);
593 instanceHandle ph(THREAD, p);
594 mgrArray->obj_at_put(i, ph());
595 }
596 }
597 return (jobjectArray) JNIHandles::make_local(env, mgrArray());
598 JVM_END
601 // Returns a java/lang/management/MemoryUsage object containing the memory usage
602 // of a given memory pool.
603 JVM_ENTRY(jobject, jmm_GetMemoryPoolUsage(JNIEnv* env, jobject obj))
604 ResourceMark rm(THREAD);
606 MemoryPool* pool = get_memory_pool_from_jobject(obj, CHECK_NULL);
607 if (pool != NULL) {
608 MemoryUsage usage = pool->get_memory_usage();
609 Handle h = MemoryService::create_MemoryUsage_obj(usage, CHECK_NULL);
610 return JNIHandles::make_local(env, h());
611 } else {
612 return NULL;
613 }
614 JVM_END
616 // Returns a java/lang/management/MemoryUsage object containing the memory usage
617 // of a given memory pool.
618 JVM_ENTRY(jobject, jmm_GetPeakMemoryPoolUsage(JNIEnv* env, jobject obj))
619 ResourceMark rm(THREAD);
621 MemoryPool* pool = get_memory_pool_from_jobject(obj, CHECK_NULL);
622 if (pool != NULL) {
623 MemoryUsage usage = pool->get_peak_memory_usage();
624 Handle h = MemoryService::create_MemoryUsage_obj(usage, CHECK_NULL);
625 return JNIHandles::make_local(env, h());
626 } else {
627 return NULL;
628 }
629 JVM_END
631 // Returns a java/lang/management/MemoryUsage object containing the memory usage
632 // of a given memory pool after most recent GC.
633 JVM_ENTRY(jobject, jmm_GetPoolCollectionUsage(JNIEnv* env, jobject obj))
634 ResourceMark rm(THREAD);
636 MemoryPool* pool = get_memory_pool_from_jobject(obj, CHECK_NULL);
637 if (pool != NULL && pool->is_collected_pool()) {
638 MemoryUsage usage = pool->get_last_collection_usage();
639 Handle h = MemoryService::create_MemoryUsage_obj(usage, CHECK_NULL);
640 return JNIHandles::make_local(env, h());
641 } else {
642 return NULL;
643 }
644 JVM_END
646 // Sets the memory pool sensor for a threshold type
647 JVM_ENTRY(void, jmm_SetPoolSensor(JNIEnv* env, jobject obj, jmmThresholdType type, jobject sensorObj))
648 if (obj == NULL || sensorObj == NULL) {
649 THROW(vmSymbols::java_lang_NullPointerException());
650 }
652 klassOop sensor_klass = Management::sun_management_Sensor_klass(CHECK);
653 oop s = JNIHandles::resolve(sensorObj);
654 assert(s->is_instance(), "Sensor should be an instanceOop");
655 instanceHandle sensor_h(THREAD, (instanceOop) s);
656 if (!sensor_h->is_a(sensor_klass)) {
657 THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(),
658 "Sensor is not an instance of sun.management.Sensor class");
659 }
661 MemoryPool* mpool = get_memory_pool_from_jobject(obj, CHECK);
662 assert(mpool != NULL, "MemoryPool should exist");
664 switch (type) {
665 case JMM_USAGE_THRESHOLD_HIGH:
666 case JMM_USAGE_THRESHOLD_LOW:
667 // have only one sensor for threshold high and low
668 mpool->set_usage_sensor_obj(sensor_h);
669 break;
670 case JMM_COLLECTION_USAGE_THRESHOLD_HIGH:
671 case JMM_COLLECTION_USAGE_THRESHOLD_LOW:
672 // have only one sensor for threshold high and low
673 mpool->set_gc_usage_sensor_obj(sensor_h);
674 break;
675 default:
676 assert(false, "Unrecognized type");
677 }
679 JVM_END
682 // Sets the threshold of a given memory pool.
683 // Returns the previous threshold.
684 //
685 // Input parameters:
686 // pool - the MemoryPoolMXBean object
687 // type - threshold type
688 // threshold - the new threshold (must not be negative)
689 //
690 JVM_ENTRY(jlong, jmm_SetPoolThreshold(JNIEnv* env, jobject obj, jmmThresholdType type, jlong threshold))
691 if (threshold < 0) {
692 THROW_MSG_(vmSymbols::java_lang_IllegalArgumentException(),
693 "Invalid threshold value",
694 -1);
695 }
697 if ((size_t)threshold > max_uintx) {
698 stringStream st;
699 st.print("Invalid valid threshold value. Threshold value (" UINT64_FORMAT ") > max value of size_t (" SIZE_FORMAT ")", (size_t)threshold, max_uintx);
700 THROW_MSG_(vmSymbols::java_lang_IllegalArgumentException(), st.as_string(), -1);
701 }
703 MemoryPool* pool = get_memory_pool_from_jobject(obj, CHECK_(0L));
704 assert(pool != NULL, "MemoryPool should exist");
706 jlong prev = 0;
707 switch (type) {
708 case JMM_USAGE_THRESHOLD_HIGH:
709 if (!pool->usage_threshold()->is_high_threshold_supported()) {
710 return -1;
711 }
712 prev = pool->usage_threshold()->set_high_threshold((size_t) threshold);
713 break;
715 case JMM_USAGE_THRESHOLD_LOW:
716 if (!pool->usage_threshold()->is_low_threshold_supported()) {
717 return -1;
718 }
719 prev = pool->usage_threshold()->set_low_threshold((size_t) threshold);
720 break;
722 case JMM_COLLECTION_USAGE_THRESHOLD_HIGH:
723 if (!pool->gc_usage_threshold()->is_high_threshold_supported()) {
724 return -1;
725 }
726 // return and the new threshold is effective for the next GC
727 return pool->gc_usage_threshold()->set_high_threshold((size_t) threshold);
729 case JMM_COLLECTION_USAGE_THRESHOLD_LOW:
730 if (!pool->gc_usage_threshold()->is_low_threshold_supported()) {
731 return -1;
732 }
733 // return and the new threshold is effective for the next GC
734 return pool->gc_usage_threshold()->set_low_threshold((size_t) threshold);
736 default:
737 assert(false, "Unrecognized type");
738 return -1;
739 }
741 // When the threshold is changed, reevaluate if the low memory
742 // detection is enabled.
743 if (prev != threshold) {
744 LowMemoryDetector::recompute_enabled_for_collected_pools();
745 LowMemoryDetector::detect_low_memory(pool);
746 }
747 return prev;
748 JVM_END
750 // Returns a java/lang/management/MemoryUsage object representing
751 // the memory usage for the heap or non-heap memory.
752 JVM_ENTRY(jobject, jmm_GetMemoryUsage(JNIEnv* env, jboolean heap))
753 ResourceMark rm(THREAD);
755 // Calculate the memory usage
756 size_t total_init = 0;
757 size_t total_used = 0;
758 size_t total_committed = 0;
759 size_t total_max = 0;
760 bool has_undefined_init_size = false;
761 bool has_undefined_max_size = false;
763 for (int i = 0; i < MemoryService::num_memory_pools(); i++) {
764 MemoryPool* pool = MemoryService::get_memory_pool(i);
765 if ((heap && pool->is_heap()) || (!heap && pool->is_non_heap())) {
766 MemoryUsage u = pool->get_memory_usage();
767 total_used += u.used();
768 total_committed += u.committed();
770 // if any one of the memory pool has undefined init_size or max_size,
771 // set it to -1
772 if (u.init_size() == (size_t)-1) {
773 has_undefined_init_size = true;
774 }
775 if (!has_undefined_init_size) {
776 total_init += u.init_size();
777 }
779 if (u.max_size() == (size_t)-1) {
780 has_undefined_max_size = true;
781 }
782 if (!has_undefined_max_size) {
783 total_max += u.max_size();
784 }
785 }
786 }
788 // In our current implementation, all pools should have
789 // defined init and max size
790 assert(!has_undefined_init_size, "Undefined init size");
791 assert(!has_undefined_max_size, "Undefined max size");
793 MemoryUsage usage((heap ? InitialHeapSize : total_init),
794 total_used,
795 total_committed,
796 (heap ? Universe::heap()->max_capacity() : total_max));
798 Handle obj = MemoryService::create_MemoryUsage_obj(usage, CHECK_NULL);
799 return JNIHandles::make_local(env, obj());
800 JVM_END
802 // Returns the boolean value of a given attribute.
803 JVM_LEAF(jboolean, jmm_GetBoolAttribute(JNIEnv *env, jmmBoolAttribute att))
804 switch (att) {
805 case JMM_VERBOSE_GC:
806 return MemoryService::get_verbose();
807 case JMM_VERBOSE_CLASS:
808 return ClassLoadingService::get_verbose();
809 case JMM_THREAD_CONTENTION_MONITORING:
810 return ThreadService::is_thread_monitoring_contention();
811 case JMM_THREAD_CPU_TIME:
812 return ThreadService::is_thread_cpu_time_enabled();
813 default:
814 assert(0, "Unrecognized attribute");
815 return false;
816 }
817 JVM_END
819 // Sets the given boolean attribute and returns the previous value.
820 JVM_ENTRY(jboolean, jmm_SetBoolAttribute(JNIEnv *env, jmmBoolAttribute att, jboolean flag))
821 switch (att) {
822 case JMM_VERBOSE_GC:
823 return MemoryService::set_verbose(flag != 0);
824 case JMM_VERBOSE_CLASS:
825 return ClassLoadingService::set_verbose(flag != 0);
826 case JMM_THREAD_CONTENTION_MONITORING:
827 return ThreadService::set_thread_monitoring_contention(flag != 0);
828 case JMM_THREAD_CPU_TIME:
829 return ThreadService::set_thread_cpu_time_enabled(flag != 0);
830 default:
831 assert(0, "Unrecognized attribute");
832 return false;
833 }
834 JVM_END
837 static jlong get_gc_attribute(GCMemoryManager* mgr, jmmLongAttribute att) {
838 switch (att) {
839 case JMM_GC_TIME_MS:
840 return mgr->gc_time_ms();
842 case JMM_GC_COUNT:
843 return mgr->gc_count();
845 case JMM_GC_EXT_ATTRIBUTE_INFO_SIZE:
846 // current implementation only has 1 ext attribute
847 return 1;
849 default:
850 assert(0, "Unrecognized GC attribute");
851 return -1;
852 }
853 }
855 class VmThreadCountClosure: public ThreadClosure {
856 private:
857 int _count;
858 public:
859 VmThreadCountClosure() : _count(0) {};
860 void do_thread(Thread* thread);
861 int count() { return _count; }
862 };
864 void VmThreadCountClosure::do_thread(Thread* thread) {
865 // exclude externally visible JavaThreads
866 if (thread->is_Java_thread() && !thread->is_hidden_from_external_view()) {
867 return;
868 }
870 _count++;
871 }
873 static jint get_vm_thread_count() {
874 VmThreadCountClosure vmtcc;
875 {
876 MutexLockerEx ml(Threads_lock);
877 Threads::threads_do(&vmtcc);
878 }
880 return vmtcc.count();
881 }
883 static jint get_num_flags() {
884 // last flag entry is always NULL, so subtract 1
885 int nFlags = (int) Flag::numFlags - 1;
886 int count = 0;
887 for (int i = 0; i < nFlags; i++) {
888 Flag* flag = &Flag::flags[i];
889 // Exclude the locked (diagnostic, experimental) flags
890 if (flag->is_unlocked() || flag->is_unlocker()) {
891 count++;
892 }
893 }
894 return count;
895 }
897 static jlong get_long_attribute(jmmLongAttribute att) {
898 switch (att) {
899 case JMM_CLASS_LOADED_COUNT:
900 return ClassLoadingService::loaded_class_count();
902 case JMM_CLASS_UNLOADED_COUNT:
903 return ClassLoadingService::unloaded_class_count();
905 case JMM_THREAD_TOTAL_COUNT:
906 return ThreadService::get_total_thread_count();
908 case JMM_THREAD_LIVE_COUNT:
909 return ThreadService::get_live_thread_count();
911 case JMM_THREAD_PEAK_COUNT:
912 return ThreadService::get_peak_thread_count();
914 case JMM_THREAD_DAEMON_COUNT:
915 return ThreadService::get_daemon_thread_count();
917 case JMM_JVM_INIT_DONE_TIME_MS:
918 return Management::vm_init_done_time();
920 case JMM_COMPILE_TOTAL_TIME_MS:
921 return Management::ticks_to_ms(CompileBroker::total_compilation_ticks());
923 case JMM_OS_PROCESS_ID:
924 return os::current_process_id();
926 // Hotspot-specific counters
927 case JMM_CLASS_LOADED_BYTES:
928 return ClassLoadingService::loaded_class_bytes();
930 case JMM_CLASS_UNLOADED_BYTES:
931 return ClassLoadingService::unloaded_class_bytes();
933 case JMM_SHARED_CLASS_LOADED_COUNT:
934 return ClassLoadingService::loaded_shared_class_count();
936 case JMM_SHARED_CLASS_UNLOADED_COUNT:
937 return ClassLoadingService::unloaded_shared_class_count();
940 case JMM_SHARED_CLASS_LOADED_BYTES:
941 return ClassLoadingService::loaded_shared_class_bytes();
943 case JMM_SHARED_CLASS_UNLOADED_BYTES:
944 return ClassLoadingService::unloaded_shared_class_bytes();
946 case JMM_TOTAL_CLASSLOAD_TIME_MS:
947 return ClassLoader::classloader_time_ms();
949 case JMM_VM_GLOBAL_COUNT:
950 return get_num_flags();
952 case JMM_SAFEPOINT_COUNT:
953 return RuntimeService::safepoint_count();
955 case JMM_TOTAL_SAFEPOINTSYNC_TIME_MS:
956 return RuntimeService::safepoint_sync_time_ms();
958 case JMM_TOTAL_STOPPED_TIME_MS:
959 return RuntimeService::safepoint_time_ms();
961 case JMM_TOTAL_APP_TIME_MS:
962 return RuntimeService::application_time_ms();
964 case JMM_VM_THREAD_COUNT:
965 return get_vm_thread_count();
967 case JMM_CLASS_INIT_TOTAL_COUNT:
968 return ClassLoader::class_init_count();
970 case JMM_CLASS_INIT_TOTAL_TIME_MS:
971 return ClassLoader::class_init_time_ms();
973 case JMM_CLASS_VERIFY_TOTAL_TIME_MS:
974 return ClassLoader::class_verify_time_ms();
976 case JMM_METHOD_DATA_SIZE_BYTES:
977 return ClassLoadingService::class_method_data_size();
979 case JMM_OS_MEM_TOTAL_PHYSICAL_BYTES:
980 return os::physical_memory();
982 default:
983 return -1;
984 }
985 }
988 // Returns the long value of a given attribute.
989 JVM_ENTRY(jlong, jmm_GetLongAttribute(JNIEnv *env, jobject obj, jmmLongAttribute att))
990 if (obj == NULL) {
991 return get_long_attribute(att);
992 } else {
993 GCMemoryManager* mgr = get_gc_memory_manager_from_jobject(obj, CHECK_(0L));
994 if (mgr != NULL) {
995 return get_gc_attribute(mgr, att);
996 }
997 }
998 return -1;
999 JVM_END
1001 // Gets the value of all attributes specified in the given array
1002 // and sets the value in the result array.
1003 // Returns the number of attributes found.
1004 JVM_ENTRY(jint, jmm_GetLongAttributes(JNIEnv *env,
1005 jobject obj,
1006 jmmLongAttribute* atts,
1007 jint count,
1008 jlong* result))
1010 int num_atts = 0;
1011 if (obj == NULL) {
1012 for (int i = 0; i < count; i++) {
1013 result[i] = get_long_attribute(atts[i]);
1014 if (result[i] != -1) {
1015 num_atts++;
1016 }
1017 }
1018 } else {
1019 GCMemoryManager* mgr = get_gc_memory_manager_from_jobject(obj, CHECK_0);
1020 for (int i = 0; i < count; i++) {
1021 result[i] = get_gc_attribute(mgr, atts[i]);
1022 if (result[i] != -1) {
1023 num_atts++;
1024 }
1025 }
1026 }
1027 return num_atts;
1028 JVM_END
1030 // Helper function to do thread dump for a specific list of threads
1031 static void do_thread_dump(ThreadDumpResult* dump_result,
1032 typeArrayHandle ids_ah, // array of thread ID (long[])
1033 int num_threads,
1034 int max_depth,
1035 bool with_locked_monitors,
1036 bool with_locked_synchronizers,
1037 TRAPS) {
1039 // First get an array of threadObj handles.
1040 // A JavaThread may terminate before we get the stack trace.
1041 GrowableArray<instanceHandle>* thread_handle_array = new GrowableArray<instanceHandle>(num_threads);
1042 {
1043 MutexLockerEx ml(Threads_lock);
1044 for (int i = 0; i < num_threads; i++) {
1045 jlong tid = ids_ah->long_at(i);
1046 JavaThread* jt = find_java_thread_from_id(tid);
1047 oop thread_obj = (jt != NULL ? jt->threadObj() : (oop)NULL);
1048 instanceHandle threadObj_h(THREAD, (instanceOop) thread_obj);
1049 thread_handle_array->append(threadObj_h);
1050 }
1051 }
1053 // Obtain thread dumps and thread snapshot information
1054 VM_ThreadDump op(dump_result,
1055 thread_handle_array,
1056 num_threads,
1057 max_depth, /* stack depth */
1058 with_locked_monitors,
1059 with_locked_synchronizers);
1060 VMThread::execute(&op);
1061 }
1063 // Gets an array of ThreadInfo objects. Each element is the ThreadInfo
1064 // for the thread ID specified in the corresponding entry in
1065 // the given array of thread IDs; or NULL if the thread does not exist
1066 // or has terminated.
1067 //
1068 // Input parameters:
1069 // ids - array of thread IDs
1070 // maxDepth - the maximum depth of stack traces to be dumped:
1071 // maxDepth == -1 requests to dump entire stack trace.
1072 // maxDepth == 0 requests no stack trace.
1073 // infoArray - array of ThreadInfo objects
1074 //
1075 JVM_ENTRY(jint, jmm_GetThreadInfo(JNIEnv *env, jlongArray ids, jint maxDepth, jobjectArray infoArray))
1076 // Check if threads is null
1077 if (ids == NULL || infoArray == NULL) {
1078 THROW_(vmSymbols::java_lang_NullPointerException(), -1);
1079 }
1081 if (maxDepth < -1) {
1082 THROW_MSG_(vmSymbols::java_lang_IllegalArgumentException(),
1083 "Invalid maxDepth", -1);
1084 }
1086 ResourceMark rm(THREAD);
1087 typeArrayOop ta = typeArrayOop(JNIHandles::resolve_non_null(ids));
1088 typeArrayHandle ids_ah(THREAD, ta);
1090 oop infoArray_obj = JNIHandles::resolve_non_null(infoArray);
1091 objArrayOop oa = objArrayOop(infoArray_obj);
1092 objArrayHandle infoArray_h(THREAD, oa);
1094 // validate the thread id array
1095 validate_thread_id_array(ids_ah, CHECK_0);
1097 // validate the ThreadInfo[] parameters
1098 validate_thread_info_array(infoArray_h, CHECK_0);
1100 // infoArray must be of the same length as the given array of thread IDs
1101 int num_threads = ids_ah->length();
1102 if (num_threads != infoArray_h->length()) {
1103 THROW_MSG_(vmSymbols::java_lang_IllegalArgumentException(),
1104 "The length of the given ThreadInfo array does not match the length of the given array of thread IDs", -1);
1105 }
1107 if (JDK_Version::is_gte_jdk16x_version()) {
1108 // make sure the AbstractOwnableSynchronizer klass is loaded before taking thread snapshots
1109 java_util_concurrent_locks_AbstractOwnableSynchronizer::initialize(CHECK_0);
1110 }
1112 // Must use ThreadDumpResult to store the ThreadSnapshot.
1113 // GC may occur after the thread snapshots are taken but before
1114 // this function returns. The threadObj and other oops kept
1115 // in the ThreadSnapshot are marked and adjusted during GC.
1116 ThreadDumpResult dump_result(num_threads);
1118 if (maxDepth == 0) {
1119 // no stack trace dumped - do not need to stop the world
1120 {
1121 MutexLockerEx ml(Threads_lock);
1122 for (int i = 0; i < num_threads; i++) {
1123 jlong tid = ids_ah->long_at(i);
1124 JavaThread* jt = find_java_thread_from_id(tid);
1125 ThreadSnapshot* ts;
1126 if (jt == NULL) {
1127 // if the thread does not exist or now it is terminated,
1128 // create dummy snapshot
1129 ts = new ThreadSnapshot();
1130 } else {
1131 ts = new ThreadSnapshot(jt);
1132 }
1133 dump_result.add_thread_snapshot(ts);
1134 }
1135 }
1136 } else {
1137 // obtain thread dump with the specific list of threads with stack trace
1139 do_thread_dump(&dump_result,
1140 ids_ah,
1141 num_threads,
1142 maxDepth,
1143 false, /* no locked monitor */
1144 false, /* no locked synchronizers */
1145 CHECK_0);
1146 }
1148 int num_snapshots = dump_result.num_snapshots();
1149 assert(num_snapshots == num_threads, "Must match the number of thread snapshots");
1150 int index = 0;
1151 for (ThreadSnapshot* ts = dump_result.snapshots(); ts != NULL; index++, ts = ts->next()) {
1152 // For each thread, create an java/lang/management/ThreadInfo object
1153 // and fill with the thread information
1155 if (ts->threadObj() == NULL) {
1156 // if the thread does not exist or now it is terminated, set threadinfo to NULL
1157 infoArray_h->obj_at_put(index, NULL);
1158 continue;
1159 }
1161 // Create java.lang.management.ThreadInfo object
1162 instanceOop info_obj = Management::create_thread_info_instance(ts, CHECK_0);
1163 infoArray_h->obj_at_put(index, info_obj);
1164 }
1165 return 0;
1166 JVM_END
1168 // Dump thread info for the specified threads.
1169 // It returns an array of ThreadInfo objects. Each element is the ThreadInfo
1170 // for the thread ID specified in the corresponding entry in
1171 // the given array of thread IDs; or NULL if the thread does not exist
1172 // or has terminated.
1173 //
1174 // Input parameter:
1175 // ids - array of thread IDs; NULL indicates all live threads
1176 // locked_monitors - if true, dump locked object monitors
1177 // locked_synchronizers - if true, dump locked JSR-166 synchronizers
1178 //
1179 JVM_ENTRY(jobjectArray, jmm_DumpThreads(JNIEnv *env, jlongArray thread_ids, jboolean locked_monitors, jboolean locked_synchronizers))
1180 ResourceMark rm(THREAD);
1182 if (JDK_Version::is_gte_jdk16x_version()) {
1183 // make sure the AbstractOwnableSynchronizer klass is loaded before taking thread snapshots
1184 java_util_concurrent_locks_AbstractOwnableSynchronizer::initialize(CHECK_NULL);
1185 }
1187 typeArrayOop ta = typeArrayOop(JNIHandles::resolve(thread_ids));
1188 int num_threads = (ta != NULL ? ta->length() : 0);
1189 typeArrayHandle ids_ah(THREAD, ta);
1191 ThreadDumpResult dump_result(num_threads); // can safepoint
1193 if (ids_ah() != NULL) {
1195 // validate the thread id array
1196 validate_thread_id_array(ids_ah, CHECK_NULL);
1198 // obtain thread dump of a specific list of threads
1199 do_thread_dump(&dump_result,
1200 ids_ah,
1201 num_threads,
1202 -1, /* entire stack */
1203 (locked_monitors ? true : false), /* with locked monitors */
1204 (locked_synchronizers ? true : false), /* with locked synchronizers */
1205 CHECK_NULL);
1206 } else {
1207 // obtain thread dump of all threads
1208 VM_ThreadDump op(&dump_result,
1209 -1, /* entire stack */
1210 (locked_monitors ? true : false), /* with locked monitors */
1211 (locked_synchronizers ? true : false) /* with locked synchronizers */);
1212 VMThread::execute(&op);
1213 }
1215 int num_snapshots = dump_result.num_snapshots();
1217 // create the result ThreadInfo[] object
1218 klassOop k = Management::java_lang_management_ThreadInfo_klass(CHECK_NULL);
1219 instanceKlassHandle ik (THREAD, k);
1220 objArrayOop r = oopFactory::new_objArray(ik(), num_snapshots, CHECK_NULL);
1221 objArrayHandle result_h(THREAD, r);
1223 int index = 0;
1224 for (ThreadSnapshot* ts = dump_result.snapshots(); ts != NULL; ts = ts->next(), index++) {
1225 if (ts->threadObj() == NULL) {
1226 // if the thread does not exist or now it is terminated, set threadinfo to NULL
1227 result_h->obj_at_put(index, NULL);
1228 continue;
1229 }
1233 ThreadStackTrace* stacktrace = ts->get_stack_trace();
1234 assert(stacktrace != NULL, "Must have a stack trace dumped");
1236 // Create Object[] filled with locked monitors
1237 // Create int[] filled with the stack depth where a monitor was locked
1238 int num_frames = stacktrace->get_stack_depth();
1239 int num_locked_monitors = stacktrace->num_jni_locked_monitors();
1241 // Count the total number of locked monitors
1242 for (int i = 0; i < num_frames; i++) {
1243 StackFrameInfo* frame = stacktrace->stack_frame_at(i);
1244 num_locked_monitors += frame->num_locked_monitors();
1245 }
1247 objArrayHandle monitors_array;
1248 typeArrayHandle depths_array;
1249 objArrayHandle synchronizers_array;
1251 if (locked_monitors) {
1252 // Constructs Object[] and int[] to contain the object monitor and the stack depth
1253 // where the thread locked it
1254 objArrayOop array = oopFactory::new_system_objArray(num_locked_monitors, CHECK_NULL);
1255 objArrayHandle mh(THREAD, array);
1256 monitors_array = mh;
1258 typeArrayOop tarray = oopFactory::new_typeArray(T_INT, num_locked_monitors, CHECK_NULL);
1259 typeArrayHandle dh(THREAD, tarray);
1260 depths_array = dh;
1262 int count = 0;
1263 int j = 0;
1264 for (int depth = 0; depth < num_frames; depth++) {
1265 StackFrameInfo* frame = stacktrace->stack_frame_at(depth);
1266 int len = frame->num_locked_monitors();
1267 GrowableArray<oop>* locked_monitors = frame->locked_monitors();
1268 for (j = 0; j < len; j++) {
1269 oop monitor = locked_monitors->at(j);
1270 assert(monitor != NULL && monitor->is_instance(), "must be a Java object");
1271 monitors_array->obj_at_put(count, monitor);
1272 depths_array->int_at_put(count, depth);
1273 count++;
1274 }
1275 }
1277 GrowableArray<oop>* jni_locked_monitors = stacktrace->jni_locked_monitors();
1278 for (j = 0; j < jni_locked_monitors->length(); j++) {
1279 oop object = jni_locked_monitors->at(j);
1280 assert(object != NULL && object->is_instance(), "must be a Java object");
1281 monitors_array->obj_at_put(count, object);
1282 // Monitor locked via JNI MonitorEnter call doesn't have stack depth info
1283 depths_array->int_at_put(count, -1);
1284 count++;
1285 }
1286 assert(count == num_locked_monitors, "number of locked monitors doesn't match");
1287 }
1289 if (locked_synchronizers) {
1290 // Create Object[] filled with locked JSR-166 synchronizers
1291 assert(ts->threadObj() != NULL, "Must be a valid JavaThread");
1292 ThreadConcurrentLocks* tcl = ts->get_concurrent_locks();
1293 GrowableArray<instanceOop>* locks = (tcl != NULL ? tcl->owned_locks() : NULL);
1294 int num_locked_synchronizers = (locks != NULL ? locks->length() : 0);
1296 objArrayOop array = oopFactory::new_system_objArray(num_locked_synchronizers, CHECK_NULL);
1297 objArrayHandle sh(THREAD, array);
1298 synchronizers_array = sh;
1300 for (int k = 0; k < num_locked_synchronizers; k++) {
1301 synchronizers_array->obj_at_put(k, locks->at(k));
1302 }
1303 }
1305 // Create java.lang.management.ThreadInfo object
1306 instanceOop info_obj = Management::create_thread_info_instance(ts,
1307 monitors_array,
1308 depths_array,
1309 synchronizers_array,
1310 CHECK_NULL);
1311 result_h->obj_at_put(index, info_obj);
1312 }
1314 return (jobjectArray) JNIHandles::make_local(env, result_h());
1315 JVM_END
1317 // Returns an array of Class objects.
1318 JVM_ENTRY(jobjectArray, jmm_GetLoadedClasses(JNIEnv *env))
1319 ResourceMark rm(THREAD);
1321 LoadedClassesEnumerator lce(THREAD); // Pass current Thread as parameter
1323 int num_classes = lce.num_loaded_classes();
1324 objArrayOop r = oopFactory::new_objArray(SystemDictionary::Class_klass(), num_classes, CHECK_0);
1325 objArrayHandle classes_ah(THREAD, r);
1327 for (int i = 0; i < num_classes; i++) {
1328 KlassHandle kh = lce.get_klass(i);
1329 oop mirror = Klass::cast(kh())->java_mirror();
1330 classes_ah->obj_at_put(i, mirror);
1331 }
1333 return (jobjectArray) JNIHandles::make_local(env, classes_ah());
1334 JVM_END
1336 // Reset statistic. Return true if the requested statistic is reset.
1337 // Otherwise, return false.
1338 //
1339 // Input parameters:
1340 // obj - specify which instance the statistic associated with to be reset
1341 // For PEAK_POOL_USAGE stat, obj is required to be a memory pool object.
1342 // For THREAD_CONTENTION_COUNT and TIME stat, obj is required to be a thread ID.
1343 // type - the type of statistic to be reset
1344 //
1345 JVM_ENTRY(jboolean, jmm_ResetStatistic(JNIEnv *env, jvalue obj, jmmStatisticType type))
1346 ResourceMark rm(THREAD);
1348 switch (type) {
1349 case JMM_STAT_PEAK_THREAD_COUNT:
1350 ThreadService::reset_peak_thread_count();
1351 return true;
1353 case JMM_STAT_THREAD_CONTENTION_COUNT:
1354 case JMM_STAT_THREAD_CONTENTION_TIME: {
1355 jlong tid = obj.j;
1356 if (tid < 0) {
1357 THROW_(vmSymbols::java_lang_IllegalArgumentException(), JNI_FALSE);
1358 }
1360 // Look for the JavaThread of this given tid
1361 MutexLockerEx ml(Threads_lock);
1362 if (tid == 0) {
1363 // reset contention statistics for all threads if tid == 0
1364 for (JavaThread* java_thread = Threads::first(); java_thread != NULL; java_thread = java_thread->next()) {
1365 if (type == JMM_STAT_THREAD_CONTENTION_COUNT) {
1366 ThreadService::reset_contention_count_stat(java_thread);
1367 } else {
1368 ThreadService::reset_contention_time_stat(java_thread);
1369 }
1370 }
1371 } else {
1372 // reset contention statistics for a given thread
1373 JavaThread* java_thread = find_java_thread_from_id(tid);
1374 if (java_thread == NULL) {
1375 return false;
1376 }
1378 if (type == JMM_STAT_THREAD_CONTENTION_COUNT) {
1379 ThreadService::reset_contention_count_stat(java_thread);
1380 } else {
1381 ThreadService::reset_contention_time_stat(java_thread);
1382 }
1383 }
1384 return true;
1385 break;
1386 }
1387 case JMM_STAT_PEAK_POOL_USAGE: {
1388 jobject o = obj.l;
1389 if (o == NULL) {
1390 THROW_(vmSymbols::java_lang_NullPointerException(), JNI_FALSE);
1391 }
1393 oop pool_obj = JNIHandles::resolve(o);
1394 assert(pool_obj->is_instance(), "Should be an instanceOop");
1395 instanceHandle ph(THREAD, (instanceOop) pool_obj);
1397 MemoryPool* pool = MemoryService::get_memory_pool(ph);
1398 if (pool != NULL) {
1399 pool->reset_peak_memory_usage();
1400 return true;
1401 }
1402 break;
1403 }
1404 case JMM_STAT_GC_STAT: {
1405 jobject o = obj.l;
1406 if (o == NULL) {
1407 THROW_(vmSymbols::java_lang_NullPointerException(), JNI_FALSE);
1408 }
1410 GCMemoryManager* mgr = get_gc_memory_manager_from_jobject(o, CHECK_0);
1411 if (mgr != NULL) {
1412 mgr->reset_gc_stat();
1413 return true;
1414 }
1415 break;
1416 }
1417 default:
1418 assert(0, "Unknown Statistic Type");
1419 }
1420 return false;
1421 JVM_END
1423 // Returns the fast estimate of CPU time consumed by
1424 // a given thread (in nanoseconds).
1425 // If thread_id == 0, return CPU time for the current thread.
1426 JVM_ENTRY(jlong, jmm_GetThreadCpuTime(JNIEnv *env, jlong thread_id))
1427 if (!os::is_thread_cpu_time_supported()) {
1428 return -1;
1429 }
1431 if (thread_id < 0) {
1432 THROW_MSG_(vmSymbols::java_lang_IllegalArgumentException(),
1433 "Invalid thread ID", -1);
1434 }
1436 JavaThread* java_thread = NULL;
1437 if (thread_id == 0) {
1438 // current thread
1439 return os::current_thread_cpu_time();
1440 } else {
1441 MutexLockerEx ml(Threads_lock);
1442 java_thread = find_java_thread_from_id(thread_id);
1443 if (java_thread != NULL) {
1444 return os::thread_cpu_time((Thread*) java_thread);
1445 }
1446 }
1447 return -1;
1448 JVM_END
1450 // Returns the CPU time consumed by a given thread (in nanoseconds).
1451 // If thread_id == 0, CPU time for the current thread is returned.
1452 // If user_sys_cpu_time = true, user level and system CPU time of
1453 // a given thread is returned; otherwise, only user level CPU time
1454 // is returned.
1455 JVM_ENTRY(jlong, jmm_GetThreadCpuTimeWithKind(JNIEnv *env, jlong thread_id, jboolean user_sys_cpu_time))
1456 if (!os::is_thread_cpu_time_supported()) {
1457 return -1;
1458 }
1460 if (thread_id < 0) {
1461 THROW_MSG_(vmSymbols::java_lang_IllegalArgumentException(),
1462 "Invalid thread ID", -1);
1463 }
1465 JavaThread* java_thread = NULL;
1466 if (thread_id == 0) {
1467 // current thread
1468 return os::current_thread_cpu_time(user_sys_cpu_time != 0);
1469 } else {
1470 MutexLockerEx ml(Threads_lock);
1471 java_thread = find_java_thread_from_id(thread_id);
1472 if (java_thread != NULL) {
1473 return os::thread_cpu_time((Thread*) java_thread, user_sys_cpu_time != 0);
1474 }
1475 }
1476 return -1;
1477 JVM_END
1479 // Returns a String array of all VM global flag names
1480 JVM_ENTRY(jobjectArray, jmm_GetVMGlobalNames(JNIEnv *env))
1481 // last flag entry is always NULL, so subtract 1
1482 int nFlags = (int) Flag::numFlags - 1;
1483 // allocate a temp array
1484 objArrayOop r = oopFactory::new_objArray(SystemDictionary::String_klass(),
1485 nFlags, CHECK_0);
1486 objArrayHandle flags_ah(THREAD, r);
1487 int num_entries = 0;
1488 for (int i = 0; i < nFlags; i++) {
1489 Flag* flag = &Flag::flags[i];
1490 // Exclude the locked (experimental, diagnostic) flags
1491 if (flag->is_unlocked() || flag->is_unlocker()) {
1492 Handle s = java_lang_String::create_from_str(flag->name, CHECK_0);
1493 flags_ah->obj_at_put(num_entries, s());
1494 num_entries++;
1495 }
1496 }
1498 if (num_entries < nFlags) {
1499 // Return array of right length
1500 objArrayOop res = oopFactory::new_objArray(SystemDictionary::String_klass(), num_entries, CHECK_0);
1501 for(int i = 0; i < num_entries; i++) {
1502 res->obj_at_put(i, flags_ah->obj_at(i));
1503 }
1504 return (jobjectArray)JNIHandles::make_local(env, res);
1505 }
1507 return (jobjectArray)JNIHandles::make_local(env, flags_ah());
1508 JVM_END
1510 // Utility function used by jmm_GetVMGlobals. Returns false if flag type
1511 // can't be determined, true otherwise. If false is returned, then *global
1512 // will be incomplete and invalid.
1513 bool add_global_entry(JNIEnv* env, Handle name, jmmVMGlobal *global, Flag *flag, TRAPS) {
1514 Handle flag_name;
1515 if (name() == NULL) {
1516 flag_name = java_lang_String::create_from_str(flag->name, CHECK_false);
1517 } else {
1518 flag_name = name;
1519 }
1520 global->name = (jstring)JNIHandles::make_local(env, flag_name());
1522 if (flag->is_bool()) {
1523 global->value.z = flag->get_bool() ? JNI_TRUE : JNI_FALSE;
1524 global->type = JMM_VMGLOBAL_TYPE_JBOOLEAN;
1525 } else if (flag->is_intx()) {
1526 global->value.j = (jlong)flag->get_intx();
1527 global->type = JMM_VMGLOBAL_TYPE_JLONG;
1528 } else if (flag->is_uintx()) {
1529 global->value.j = (jlong)flag->get_uintx();
1530 global->type = JMM_VMGLOBAL_TYPE_JLONG;
1531 } else if (flag->is_uint64_t()) {
1532 global->value.j = (jlong)flag->get_uint64_t();
1533 global->type = JMM_VMGLOBAL_TYPE_JLONG;
1534 } else if (flag->is_ccstr()) {
1535 Handle str = java_lang_String::create_from_str(flag->get_ccstr(), CHECK_false);
1536 global->value.l = (jobject)JNIHandles::make_local(env, str());
1537 global->type = JMM_VMGLOBAL_TYPE_JSTRING;
1538 } else {
1539 global->type = JMM_VMGLOBAL_TYPE_UNKNOWN;
1540 return false;
1541 }
1543 global->writeable = flag->is_writeable();
1544 global->external = flag->is_external();
1545 switch (flag->origin) {
1546 case DEFAULT:
1547 global->origin = JMM_VMGLOBAL_ORIGIN_DEFAULT;
1548 break;
1549 case COMMAND_LINE:
1550 global->origin = JMM_VMGLOBAL_ORIGIN_COMMAND_LINE;
1551 break;
1552 case ENVIRON_VAR:
1553 global->origin = JMM_VMGLOBAL_ORIGIN_ENVIRON_VAR;
1554 break;
1555 case CONFIG_FILE:
1556 global->origin = JMM_VMGLOBAL_ORIGIN_CONFIG_FILE;
1557 break;
1558 case MANAGEMENT:
1559 global->origin = JMM_VMGLOBAL_ORIGIN_MANAGEMENT;
1560 break;
1561 case ERGONOMIC:
1562 global->origin = JMM_VMGLOBAL_ORIGIN_ERGONOMIC;
1563 break;
1564 default:
1565 global->origin = JMM_VMGLOBAL_ORIGIN_OTHER;
1566 }
1568 return true;
1569 }
1571 // Fill globals array of count length with jmmVMGlobal entries
1572 // specified by names. If names == NULL, fill globals array
1573 // with all Flags. Return value is number of entries
1574 // created in globals.
1575 // If a Flag with a given name in an array element does not
1576 // exist, globals[i].name will be set to NULL.
1577 JVM_ENTRY(jint, jmm_GetVMGlobals(JNIEnv *env,
1578 jobjectArray names,
1579 jmmVMGlobal *globals,
1580 jint count))
1583 if (globals == NULL) {
1584 THROW_(vmSymbols::java_lang_NullPointerException(), 0);
1585 }
1587 ResourceMark rm(THREAD);
1589 if (names != NULL) {
1590 // return the requested globals
1591 objArrayOop ta = objArrayOop(JNIHandles::resolve_non_null(names));
1592 objArrayHandle names_ah(THREAD, ta);
1593 // Make sure we have a String array
1594 klassOop element_klass = objArrayKlass::cast(names_ah->klass())->element_klass();
1595 if (element_klass != SystemDictionary::String_klass()) {
1596 THROW_MSG_(vmSymbols::java_lang_IllegalArgumentException(),
1597 "Array element type is not String class", 0);
1598 }
1600 int names_length = names_ah->length();
1601 int num_entries = 0;
1602 for (int i = 0; i < names_length && i < count; i++) {
1603 oop s = names_ah->obj_at(i);
1604 if (s == NULL) {
1605 THROW_(vmSymbols::java_lang_NullPointerException(), 0);
1606 }
1608 Handle sh(THREAD, s);
1609 char* str = java_lang_String::as_utf8_string(s);
1610 Flag* flag = Flag::find_flag(str, strlen(str));
1611 if (flag != NULL &&
1612 add_global_entry(env, sh, &globals[i], flag, THREAD)) {
1613 num_entries++;
1614 } else {
1615 globals[i].name = NULL;
1616 }
1617 }
1618 return num_entries;
1619 } else {
1620 // return all globals if names == NULL
1622 // last flag entry is always NULL, so subtract 1
1623 int nFlags = (int) Flag::numFlags - 1;
1624 Handle null_h;
1625 int num_entries = 0;
1626 for (int i = 0; i < nFlags && num_entries < count; i++) {
1627 Flag* flag = &Flag::flags[i];
1628 // Exclude the locked (diagnostic, experimental) flags
1629 if ((flag->is_unlocked() || flag->is_unlocker()) &&
1630 add_global_entry(env, null_h, &globals[num_entries], flag, THREAD)) {
1631 num_entries++;
1632 }
1633 }
1634 return num_entries;
1635 }
1636 JVM_END
1638 JVM_ENTRY(void, jmm_SetVMGlobal(JNIEnv *env, jstring flag_name, jvalue new_value))
1639 ResourceMark rm(THREAD);
1641 oop fn = JNIHandles::resolve_external_guard(flag_name);
1642 if (fn == NULL) {
1643 THROW_MSG(vmSymbols::java_lang_NullPointerException(),
1644 "The flag name cannot be null.");
1645 }
1646 char* name = java_lang_String::as_utf8_string(fn);
1647 Flag* flag = Flag::find_flag(name, strlen(name));
1648 if (flag == NULL) {
1649 THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(),
1650 "Flag does not exist.");
1651 }
1652 if (!flag->is_writeable()) {
1653 THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(),
1654 "This flag is not writeable.");
1655 }
1657 bool succeed;
1658 if (flag->is_bool()) {
1659 bool bvalue = (new_value.z == JNI_TRUE ? true : false);
1660 succeed = CommandLineFlags::boolAtPut(name, &bvalue, MANAGEMENT);
1661 } else if (flag->is_intx()) {
1662 intx ivalue = (intx)new_value.j;
1663 succeed = CommandLineFlags::intxAtPut(name, &ivalue, MANAGEMENT);
1664 } else if (flag->is_uintx()) {
1665 uintx uvalue = (uintx)new_value.j;
1666 succeed = CommandLineFlags::uintxAtPut(name, &uvalue, MANAGEMENT);
1667 } else if (flag->is_uint64_t()) {
1668 uint64_t uvalue = (uint64_t)new_value.j;
1669 succeed = CommandLineFlags::uint64_tAtPut(name, &uvalue, MANAGEMENT);
1670 } else if (flag->is_ccstr()) {
1671 oop str = JNIHandles::resolve_external_guard(new_value.l);
1672 if (str == NULL) {
1673 THROW(vmSymbols::java_lang_NullPointerException());
1674 }
1675 ccstr svalue = java_lang_String::as_utf8_string(str);
1676 succeed = CommandLineFlags::ccstrAtPut(name, &svalue, MANAGEMENT);
1677 }
1678 assert(succeed, "Setting flag should succeed");
1679 JVM_END
1681 class ThreadTimesClosure: public ThreadClosure {
1682 private:
1683 objArrayOop _names;
1684 typeArrayOop _times;
1685 int _names_len;
1686 int _times_len;
1687 int _count;
1689 public:
1690 ThreadTimesClosure(objArrayOop names, typeArrayOop times);
1691 virtual void do_thread(Thread* thread);
1692 int count() { return _count; }
1693 };
1695 ThreadTimesClosure::ThreadTimesClosure(objArrayOop names,
1696 typeArrayOop times) {
1697 assert(names != NULL, "names was NULL");
1698 assert(times != NULL, "times was NULL");
1699 _names = names;
1700 _names_len = names->length();
1701 _times = times;
1702 _times_len = times->length();
1703 _count = 0;
1704 }
1706 void ThreadTimesClosure::do_thread(Thread* thread) {
1707 Handle s;
1708 assert(thread != NULL, "thread was NULL");
1710 // exclude externally visible JavaThreads
1711 if (thread->is_Java_thread() && !thread->is_hidden_from_external_view()) {
1712 return;
1713 }
1715 if (_count >= _names_len || _count >= _times_len) {
1716 // skip if the result array is not big enough
1717 return;
1718 }
1720 EXCEPTION_MARK;
1722 assert(thread->name() != NULL, "All threads should have a name");
1723 s = java_lang_String::create_from_str(thread->name(), CHECK);
1724 _names->obj_at_put(_count, s());
1726 _times->long_at_put(_count, os::is_thread_cpu_time_supported() ?
1727 os::thread_cpu_time(thread) : -1);
1728 _count++;
1729 }
1731 // Fills names with VM internal thread names and times with the corresponding
1732 // CPU times. If names or times is NULL, a NullPointerException is thrown.
1733 // If the element type of names is not String, an IllegalArgumentException is
1734 // thrown.
1735 // If an array is not large enough to hold all the entries, only the entries
1736 // that fit will be returned. Return value is the number of VM internal
1737 // threads entries.
1738 JVM_ENTRY(jint, jmm_GetInternalThreadTimes(JNIEnv *env,
1739 jobjectArray names,
1740 jlongArray times))
1741 if (names == NULL || times == NULL) {
1742 THROW_(vmSymbols::java_lang_NullPointerException(), 0);
1743 }
1744 objArrayOop na = objArrayOop(JNIHandles::resolve_non_null(names));
1745 objArrayHandle names_ah(THREAD, na);
1747 // Make sure we have a String array
1748 klassOop element_klass = objArrayKlass::cast(names_ah->klass())->element_klass();
1749 if (element_klass != SystemDictionary::String_klass()) {
1750 THROW_MSG_(vmSymbols::java_lang_IllegalArgumentException(),
1751 "Array element type is not String class", 0);
1752 }
1754 typeArrayOop ta = typeArrayOop(JNIHandles::resolve_non_null(times));
1755 typeArrayHandle times_ah(THREAD, ta);
1757 ThreadTimesClosure ttc(names_ah(), times_ah());
1758 {
1759 MutexLockerEx ml(Threads_lock);
1760 Threads::threads_do(&ttc);
1761 }
1763 return ttc.count();
1764 JVM_END
1766 static Handle find_deadlocks(bool object_monitors_only, TRAPS) {
1767 ResourceMark rm(THREAD);
1769 VM_FindDeadlocks op(!object_monitors_only /* also check concurrent locks? */);
1770 VMThread::execute(&op);
1772 DeadlockCycle* deadlocks = op.result();
1773 if (deadlocks == NULL) {
1774 // no deadlock found and return
1775 return Handle();
1776 }
1778 int num_threads = 0;
1779 DeadlockCycle* cycle;
1780 for (cycle = deadlocks; cycle != NULL; cycle = cycle->next()) {
1781 num_threads += cycle->num_threads();
1782 }
1784 objArrayOop r = oopFactory::new_objArray(SystemDictionary::Thread_klass(), num_threads, CHECK_NH);
1785 objArrayHandle threads_ah(THREAD, r);
1787 int index = 0;
1788 for (cycle = deadlocks; cycle != NULL; cycle = cycle->next()) {
1789 GrowableArray<JavaThread*>* deadlock_threads = cycle->threads();
1790 int len = deadlock_threads->length();
1791 for (int i = 0; i < len; i++) {
1792 threads_ah->obj_at_put(index, deadlock_threads->at(i)->threadObj());
1793 index++;
1794 }
1795 }
1796 return threads_ah;
1797 }
1799 // Finds cycles of threads that are deadlocked involved in object monitors
1800 // and JSR-166 synchronizers.
1801 // Returns an array of Thread objects which are in deadlock, if any.
1802 // Otherwise, returns NULL.
1803 //
1804 // Input parameter:
1805 // object_monitors_only - if true, only check object monitors
1806 //
1807 JVM_ENTRY(jobjectArray, jmm_FindDeadlockedThreads(JNIEnv *env, jboolean object_monitors_only))
1808 Handle result = find_deadlocks(object_monitors_only != 0, CHECK_0);
1809 return (jobjectArray) JNIHandles::make_local(env, result());
1810 JVM_END
1812 // Finds cycles of threads that are deadlocked on monitor locks
1813 // Returns an array of Thread objects which are in deadlock, if any.
1814 // Otherwise, returns NULL.
1815 JVM_ENTRY(jobjectArray, jmm_FindMonitorDeadlockedThreads(JNIEnv *env))
1816 Handle result = find_deadlocks(true, CHECK_0);
1817 return (jobjectArray) JNIHandles::make_local(env, result());
1818 JVM_END
1820 // Gets the information about GC extension attributes including
1821 // the name of the attribute, its type, and a short description.
1822 //
1823 // Input parameters:
1824 // mgr - GC memory manager
1825 // info - caller allocated array of jmmExtAttributeInfo
1826 // count - number of elements of the info array
1827 //
1828 // Returns the number of GC extension attributes filled in the info array; or
1829 // -1 if info is not big enough
1830 //
1831 JVM_ENTRY(jint, jmm_GetGCExtAttributeInfo(JNIEnv *env, jobject mgr, jmmExtAttributeInfo* info, jint count))
1832 // All GC memory managers have 1 attribute (number of GC threads)
1833 if (count == 0) {
1834 return 0;
1835 }
1837 if (info == NULL) {
1838 THROW_(vmSymbols::java_lang_NullPointerException(), 0);
1839 }
1841 info[0].name = "GcThreadCount";
1842 info[0].type = 'I';
1843 info[0].description = "Number of GC threads";
1844 return 1;
1845 JVM_END
1847 // verify the given array is an array of java/lang/management/MemoryUsage objects
1848 // of a given length and return the objArrayOop
1849 static objArrayOop get_memory_usage_objArray(jobjectArray array, int length, TRAPS) {
1850 if (array == NULL) {
1851 THROW_(vmSymbols::java_lang_NullPointerException(), 0);
1852 }
1854 objArrayOop oa = objArrayOop(JNIHandles::resolve_non_null(array));
1855 objArrayHandle array_h(THREAD, oa);
1857 // array must be of the given length
1858 if (length != array_h->length()) {
1859 THROW_MSG_(vmSymbols::java_lang_IllegalArgumentException(),
1860 "The length of the given MemoryUsage array does not match the number of memory pools.", 0);
1861 }
1863 // check if the element of array is of type MemoryUsage class
1864 klassOop usage_klass = Management::java_lang_management_MemoryUsage_klass(CHECK_0);
1865 klassOop element_klass = objArrayKlass::cast(array_h->klass())->element_klass();
1866 if (element_klass != usage_klass) {
1867 THROW_MSG_(vmSymbols::java_lang_IllegalArgumentException(),
1868 "The element type is not MemoryUsage class", 0);
1869 }
1871 return array_h();
1872 }
1874 // Gets the statistics of the last GC of a given GC memory manager.
1875 // Input parameters:
1876 // obj - GarbageCollectorMXBean object
1877 // gc_stat - caller allocated jmmGCStat where:
1878 // a. before_gc_usage - array of MemoryUsage objects
1879 // b. after_gc_usage - array of MemoryUsage objects
1880 // c. gc_ext_attributes_values_size is set to the
1881 // gc_ext_attribute_values array allocated
1882 // d. gc_ext_attribute_values is a caller allocated array of jvalue.
1883 //
1884 // On return,
1885 // gc_index == 0 indicates no GC statistics available
1886 //
1887 // before_gc_usage and after_gc_usage - filled with per memory pool
1888 // before and after GC usage in the same order as the memory pools
1889 // returned by GetMemoryPools for a given GC memory manager.
1890 // num_gc_ext_attributes indicates the number of elements in
1891 // the gc_ext_attribute_values array is filled; or
1892 // -1 if the gc_ext_attributes_values array is not big enough
1893 //
1894 JVM_ENTRY(void, jmm_GetLastGCStat(JNIEnv *env, jobject obj, jmmGCStat *gc_stat))
1895 ResourceMark rm(THREAD);
1897 if (gc_stat->gc_ext_attribute_values_size > 0 && gc_stat->gc_ext_attribute_values == NULL) {
1898 THROW(vmSymbols::java_lang_NullPointerException());
1899 }
1901 // Get the GCMemoryManager
1902 GCMemoryManager* mgr = get_gc_memory_manager_from_jobject(obj, CHECK);
1903 if (mgr->last_gc_stat() == NULL) {
1904 gc_stat->gc_index = 0;
1905 return;
1906 }
1908 // Make a copy of the last GC statistics
1909 // GC may occur while constructing the last GC information
1910 int num_pools = MemoryService::num_memory_pools();
1911 GCStatInfo* stat = new GCStatInfo(num_pools);
1912 stat->copy_stat(mgr->last_gc_stat());
1914 gc_stat->gc_index = stat->gc_index();
1915 gc_stat->start_time = Management::ticks_to_ms(stat->start_time());
1916 gc_stat->end_time = Management::ticks_to_ms(stat->end_time());
1918 // Current implementation does not have GC extension attributes
1919 gc_stat->num_gc_ext_attributes = 0;
1921 // Fill the arrays of MemoryUsage objects with before and after GC
1922 // per pool memory usage
1923 objArrayOop bu = get_memory_usage_objArray(gc_stat->usage_before_gc,
1924 num_pools,
1925 CHECK);
1926 objArrayHandle usage_before_gc_ah(THREAD, bu);
1928 objArrayOop au = get_memory_usage_objArray(gc_stat->usage_after_gc,
1929 num_pools,
1930 CHECK);
1931 objArrayHandle usage_after_gc_ah(THREAD, au);
1933 for (int i = 0; i < num_pools; i++) {
1934 Handle before_usage = MemoryService::create_MemoryUsage_obj(stat->before_gc_usage_for_pool(i), CHECK);
1935 Handle after_usage;
1937 MemoryUsage u = stat->after_gc_usage_for_pool(i);
1938 if (u.max_size() == 0 && u.used() > 0) {
1939 // If max size == 0, this pool is a survivor space.
1940 // Set max size = -1 since the pools will be swapped after GC.
1941 MemoryUsage usage(u.init_size(), u.used(), u.committed(), (size_t)-1);
1942 after_usage = MemoryService::create_MemoryUsage_obj(usage, CHECK);
1943 } else {
1944 after_usage = MemoryService::create_MemoryUsage_obj(stat->after_gc_usage_for_pool(i), CHECK);
1945 }
1946 usage_before_gc_ah->obj_at_put(i, before_usage());
1947 usage_after_gc_ah->obj_at_put(i, after_usage());
1948 }
1950 if (gc_stat->gc_ext_attribute_values_size > 0) {
1951 // Current implementation only has 1 attribute (number of GC threads)
1952 // The type is 'I'
1953 gc_stat->gc_ext_attribute_values[0].i = mgr->num_gc_threads();
1954 }
1955 JVM_END
1957 // Dump heap - Returns 0 if succeeds.
1958 JVM_ENTRY(jint, jmm_DumpHeap0(JNIEnv *env, jstring outputfile, jboolean live))
1959 #ifndef SERVICES_KERNEL
1960 ResourceMark rm(THREAD);
1961 oop on = JNIHandles::resolve_external_guard(outputfile);
1962 if (on == NULL) {
1963 THROW_MSG_(vmSymbols::java_lang_NullPointerException(),
1964 "Output file name cannot be null.", -1);
1965 }
1966 char* name = java_lang_String::as_utf8_string(on);
1967 if (name == NULL) {
1968 THROW_MSG_(vmSymbols::java_lang_NullPointerException(),
1969 "Output file name cannot be null.", -1);
1970 }
1971 HeapDumper dumper(live ? true : false);
1972 if (dumper.dump(name) != 0) {
1973 const char* errmsg = dumper.error_as_C_string();
1974 THROW_MSG_(vmSymbols::java_io_IOException(), errmsg, -1);
1975 }
1976 return 0;
1977 #else // SERVICES_KERNEL
1978 return -1;
1979 #endif // SERVICES_KERNEL
1980 JVM_END
1982 jlong Management::ticks_to_ms(jlong ticks) {
1983 assert(os::elapsed_frequency() > 0, "Must be non-zero");
1984 return (jlong)(((double)ticks / (double)os::elapsed_frequency())
1985 * (double)1000.0);
1986 }
1988 const struct jmmInterface_1_ jmm_interface = {
1989 NULL,
1990 NULL,
1991 jmm_GetVersion,
1992 jmm_GetOptionalSupport,
1993 jmm_GetInputArguments,
1994 jmm_GetThreadInfo,
1995 jmm_GetInputArgumentArray,
1996 jmm_GetMemoryPools,
1997 jmm_GetMemoryManagers,
1998 jmm_GetMemoryPoolUsage,
1999 jmm_GetPeakMemoryPoolUsage,
2000 NULL,
2001 jmm_GetMemoryUsage,
2002 jmm_GetLongAttribute,
2003 jmm_GetBoolAttribute,
2004 jmm_SetBoolAttribute,
2005 jmm_GetLongAttributes,
2006 jmm_FindMonitorDeadlockedThreads,
2007 jmm_GetThreadCpuTime,
2008 jmm_GetVMGlobalNames,
2009 jmm_GetVMGlobals,
2010 jmm_GetInternalThreadTimes,
2011 jmm_ResetStatistic,
2012 jmm_SetPoolSensor,
2013 jmm_SetPoolThreshold,
2014 jmm_GetPoolCollectionUsage,
2015 jmm_GetGCExtAttributeInfo,
2016 jmm_GetLastGCStat,
2017 jmm_GetThreadCpuTimeWithKind,
2018 NULL,
2019 jmm_DumpHeap0,
2020 jmm_FindDeadlockedThreads,
2021 jmm_SetVMGlobal,
2022 NULL,
2023 jmm_DumpThreads
2024 };
2026 void* Management::get_jmm_interface(int version) {
2027 if (version == JMM_VERSION_1_0) {
2028 return (void*) &jmm_interface;
2029 }
2030 return NULL;
2031 }