Fri, 27 Aug 2010 13:34:14 -0400
6980206: G1: assert(has_undefined_max_size, "Undefined max size");
Summary: An assert in the management.cpp is too strong and assumes the max size is always defined on memory pools, even when we don't need to use it.
Reviewed-by: mchung, johnc
1 /*
2 * Copyright (c) 2003, 2009, Oracle and/or its affiliates. All rights reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation.
8 *
9 * This code is distributed in the hope that it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
12 * version 2 for more details (a copy is included in the LICENSE file that
13 * accompanied this code).
14 *
15 * You should have received a copy of the GNU General Public License version
16 * 2 along with this work; if not, write to the Free Software Foundation,
17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
18 *
19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
20 * or visit www.oracle.com if you need additional information or have any
21 * questions.
22 *
23 */
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, we make sure that all non-heap
789 // pools have defined init and max sizes. Heap pools do not matter,
790 // as we never use total_init and total_max for them.
791 assert(heap || !has_undefined_init_size, "Undefined init size");
792 assert(heap || !has_undefined_max_size, "Undefined max size");
794 MemoryUsage usage((heap ? InitialHeapSize : total_init),
795 total_used,
796 total_committed,
797 (heap ? Universe::heap()->max_capacity() : total_max));
799 Handle obj = MemoryService::create_MemoryUsage_obj(usage, CHECK_NULL);
800 return JNIHandles::make_local(env, obj());
801 JVM_END
803 // Returns the boolean value of a given attribute.
804 JVM_LEAF(jboolean, jmm_GetBoolAttribute(JNIEnv *env, jmmBoolAttribute att))
805 switch (att) {
806 case JMM_VERBOSE_GC:
807 return MemoryService::get_verbose();
808 case JMM_VERBOSE_CLASS:
809 return ClassLoadingService::get_verbose();
810 case JMM_THREAD_CONTENTION_MONITORING:
811 return ThreadService::is_thread_monitoring_contention();
812 case JMM_THREAD_CPU_TIME:
813 return ThreadService::is_thread_cpu_time_enabled();
814 default:
815 assert(0, "Unrecognized attribute");
816 return false;
817 }
818 JVM_END
820 // Sets the given boolean attribute and returns the previous value.
821 JVM_ENTRY(jboolean, jmm_SetBoolAttribute(JNIEnv *env, jmmBoolAttribute att, jboolean flag))
822 switch (att) {
823 case JMM_VERBOSE_GC:
824 return MemoryService::set_verbose(flag != 0);
825 case JMM_VERBOSE_CLASS:
826 return ClassLoadingService::set_verbose(flag != 0);
827 case JMM_THREAD_CONTENTION_MONITORING:
828 return ThreadService::set_thread_monitoring_contention(flag != 0);
829 case JMM_THREAD_CPU_TIME:
830 return ThreadService::set_thread_cpu_time_enabled(flag != 0);
831 default:
832 assert(0, "Unrecognized attribute");
833 return false;
834 }
835 JVM_END
838 static jlong get_gc_attribute(GCMemoryManager* mgr, jmmLongAttribute att) {
839 switch (att) {
840 case JMM_GC_TIME_MS:
841 return mgr->gc_time_ms();
843 case JMM_GC_COUNT:
844 return mgr->gc_count();
846 case JMM_GC_EXT_ATTRIBUTE_INFO_SIZE:
847 // current implementation only has 1 ext attribute
848 return 1;
850 default:
851 assert(0, "Unrecognized GC attribute");
852 return -1;
853 }
854 }
856 class VmThreadCountClosure: public ThreadClosure {
857 private:
858 int _count;
859 public:
860 VmThreadCountClosure() : _count(0) {};
861 void do_thread(Thread* thread);
862 int count() { return _count; }
863 };
865 void VmThreadCountClosure::do_thread(Thread* thread) {
866 // exclude externally visible JavaThreads
867 if (thread->is_Java_thread() && !thread->is_hidden_from_external_view()) {
868 return;
869 }
871 _count++;
872 }
874 static jint get_vm_thread_count() {
875 VmThreadCountClosure vmtcc;
876 {
877 MutexLockerEx ml(Threads_lock);
878 Threads::threads_do(&vmtcc);
879 }
881 return vmtcc.count();
882 }
884 static jint get_num_flags() {
885 // last flag entry is always NULL, so subtract 1
886 int nFlags = (int) Flag::numFlags - 1;
887 int count = 0;
888 for (int i = 0; i < nFlags; i++) {
889 Flag* flag = &Flag::flags[i];
890 // Exclude the locked (diagnostic, experimental) flags
891 if (flag->is_unlocked() || flag->is_unlocker()) {
892 count++;
893 }
894 }
895 return count;
896 }
898 static jlong get_long_attribute(jmmLongAttribute att) {
899 switch (att) {
900 case JMM_CLASS_LOADED_COUNT:
901 return ClassLoadingService::loaded_class_count();
903 case JMM_CLASS_UNLOADED_COUNT:
904 return ClassLoadingService::unloaded_class_count();
906 case JMM_THREAD_TOTAL_COUNT:
907 return ThreadService::get_total_thread_count();
909 case JMM_THREAD_LIVE_COUNT:
910 return ThreadService::get_live_thread_count();
912 case JMM_THREAD_PEAK_COUNT:
913 return ThreadService::get_peak_thread_count();
915 case JMM_THREAD_DAEMON_COUNT:
916 return ThreadService::get_daemon_thread_count();
918 case JMM_JVM_INIT_DONE_TIME_MS:
919 return Management::vm_init_done_time();
921 case JMM_COMPILE_TOTAL_TIME_MS:
922 return Management::ticks_to_ms(CompileBroker::total_compilation_ticks());
924 case JMM_OS_PROCESS_ID:
925 return os::current_process_id();
927 // Hotspot-specific counters
928 case JMM_CLASS_LOADED_BYTES:
929 return ClassLoadingService::loaded_class_bytes();
931 case JMM_CLASS_UNLOADED_BYTES:
932 return ClassLoadingService::unloaded_class_bytes();
934 case JMM_SHARED_CLASS_LOADED_COUNT:
935 return ClassLoadingService::loaded_shared_class_count();
937 case JMM_SHARED_CLASS_UNLOADED_COUNT:
938 return ClassLoadingService::unloaded_shared_class_count();
941 case JMM_SHARED_CLASS_LOADED_BYTES:
942 return ClassLoadingService::loaded_shared_class_bytes();
944 case JMM_SHARED_CLASS_UNLOADED_BYTES:
945 return ClassLoadingService::unloaded_shared_class_bytes();
947 case JMM_TOTAL_CLASSLOAD_TIME_MS:
948 return ClassLoader::classloader_time_ms();
950 case JMM_VM_GLOBAL_COUNT:
951 return get_num_flags();
953 case JMM_SAFEPOINT_COUNT:
954 return RuntimeService::safepoint_count();
956 case JMM_TOTAL_SAFEPOINTSYNC_TIME_MS:
957 return RuntimeService::safepoint_sync_time_ms();
959 case JMM_TOTAL_STOPPED_TIME_MS:
960 return RuntimeService::safepoint_time_ms();
962 case JMM_TOTAL_APP_TIME_MS:
963 return RuntimeService::application_time_ms();
965 case JMM_VM_THREAD_COUNT:
966 return get_vm_thread_count();
968 case JMM_CLASS_INIT_TOTAL_COUNT:
969 return ClassLoader::class_init_count();
971 case JMM_CLASS_INIT_TOTAL_TIME_MS:
972 return ClassLoader::class_init_time_ms();
974 case JMM_CLASS_VERIFY_TOTAL_TIME_MS:
975 return ClassLoader::class_verify_time_ms();
977 case JMM_METHOD_DATA_SIZE_BYTES:
978 return ClassLoadingService::class_method_data_size();
980 case JMM_OS_MEM_TOTAL_PHYSICAL_BYTES:
981 return os::physical_memory();
983 default:
984 return -1;
985 }
986 }
989 // Returns the long value of a given attribute.
990 JVM_ENTRY(jlong, jmm_GetLongAttribute(JNIEnv *env, jobject obj, jmmLongAttribute att))
991 if (obj == NULL) {
992 return get_long_attribute(att);
993 } else {
994 GCMemoryManager* mgr = get_gc_memory_manager_from_jobject(obj, CHECK_(0L));
995 if (mgr != NULL) {
996 return get_gc_attribute(mgr, att);
997 }
998 }
999 return -1;
1000 JVM_END
1002 // Gets the value of all attributes specified in the given array
1003 // and sets the value in the result array.
1004 // Returns the number of attributes found.
1005 JVM_ENTRY(jint, jmm_GetLongAttributes(JNIEnv *env,
1006 jobject obj,
1007 jmmLongAttribute* atts,
1008 jint count,
1009 jlong* result))
1011 int num_atts = 0;
1012 if (obj == NULL) {
1013 for (int i = 0; i < count; i++) {
1014 result[i] = get_long_attribute(atts[i]);
1015 if (result[i] != -1) {
1016 num_atts++;
1017 }
1018 }
1019 } else {
1020 GCMemoryManager* mgr = get_gc_memory_manager_from_jobject(obj, CHECK_0);
1021 for (int i = 0; i < count; i++) {
1022 result[i] = get_gc_attribute(mgr, atts[i]);
1023 if (result[i] != -1) {
1024 num_atts++;
1025 }
1026 }
1027 }
1028 return num_atts;
1029 JVM_END
1031 // Helper function to do thread dump for a specific list of threads
1032 static void do_thread_dump(ThreadDumpResult* dump_result,
1033 typeArrayHandle ids_ah, // array of thread ID (long[])
1034 int num_threads,
1035 int max_depth,
1036 bool with_locked_monitors,
1037 bool with_locked_synchronizers,
1038 TRAPS) {
1040 // First get an array of threadObj handles.
1041 // A JavaThread may terminate before we get the stack trace.
1042 GrowableArray<instanceHandle>* thread_handle_array = new GrowableArray<instanceHandle>(num_threads);
1043 {
1044 MutexLockerEx ml(Threads_lock);
1045 for (int i = 0; i < num_threads; i++) {
1046 jlong tid = ids_ah->long_at(i);
1047 JavaThread* jt = find_java_thread_from_id(tid);
1048 oop thread_obj = (jt != NULL ? jt->threadObj() : (oop)NULL);
1049 instanceHandle threadObj_h(THREAD, (instanceOop) thread_obj);
1050 thread_handle_array->append(threadObj_h);
1051 }
1052 }
1054 // Obtain thread dumps and thread snapshot information
1055 VM_ThreadDump op(dump_result,
1056 thread_handle_array,
1057 num_threads,
1058 max_depth, /* stack depth */
1059 with_locked_monitors,
1060 with_locked_synchronizers);
1061 VMThread::execute(&op);
1062 }
1064 // Gets an array of ThreadInfo objects. Each element is the ThreadInfo
1065 // for the thread ID specified in the corresponding entry in
1066 // the given array of thread IDs; or NULL if the thread does not exist
1067 // or has terminated.
1068 //
1069 // Input parameters:
1070 // ids - array of thread IDs
1071 // maxDepth - the maximum depth of stack traces to be dumped:
1072 // maxDepth == -1 requests to dump entire stack trace.
1073 // maxDepth == 0 requests no stack trace.
1074 // infoArray - array of ThreadInfo objects
1075 //
1076 JVM_ENTRY(jint, jmm_GetThreadInfo(JNIEnv *env, jlongArray ids, jint maxDepth, jobjectArray infoArray))
1077 // Check if threads is null
1078 if (ids == NULL || infoArray == NULL) {
1079 THROW_(vmSymbols::java_lang_NullPointerException(), -1);
1080 }
1082 if (maxDepth < -1) {
1083 THROW_MSG_(vmSymbols::java_lang_IllegalArgumentException(),
1084 "Invalid maxDepth", -1);
1085 }
1087 ResourceMark rm(THREAD);
1088 typeArrayOop ta = typeArrayOop(JNIHandles::resolve_non_null(ids));
1089 typeArrayHandle ids_ah(THREAD, ta);
1091 oop infoArray_obj = JNIHandles::resolve_non_null(infoArray);
1092 objArrayOop oa = objArrayOop(infoArray_obj);
1093 objArrayHandle infoArray_h(THREAD, oa);
1095 // validate the thread id array
1096 validate_thread_id_array(ids_ah, CHECK_0);
1098 // validate the ThreadInfo[] parameters
1099 validate_thread_info_array(infoArray_h, CHECK_0);
1101 // infoArray must be of the same length as the given array of thread IDs
1102 int num_threads = ids_ah->length();
1103 if (num_threads != infoArray_h->length()) {
1104 THROW_MSG_(vmSymbols::java_lang_IllegalArgumentException(),
1105 "The length of the given ThreadInfo array does not match the length of the given array of thread IDs", -1);
1106 }
1108 if (JDK_Version::is_gte_jdk16x_version()) {
1109 // make sure the AbstractOwnableSynchronizer klass is loaded before taking thread snapshots
1110 java_util_concurrent_locks_AbstractOwnableSynchronizer::initialize(CHECK_0);
1111 }
1113 // Must use ThreadDumpResult to store the ThreadSnapshot.
1114 // GC may occur after the thread snapshots are taken but before
1115 // this function returns. The threadObj and other oops kept
1116 // in the ThreadSnapshot are marked and adjusted during GC.
1117 ThreadDumpResult dump_result(num_threads);
1119 if (maxDepth == 0) {
1120 // no stack trace dumped - do not need to stop the world
1121 {
1122 MutexLockerEx ml(Threads_lock);
1123 for (int i = 0; i < num_threads; i++) {
1124 jlong tid = ids_ah->long_at(i);
1125 JavaThread* jt = find_java_thread_from_id(tid);
1126 ThreadSnapshot* ts;
1127 if (jt == NULL) {
1128 // if the thread does not exist or now it is terminated,
1129 // create dummy snapshot
1130 ts = new ThreadSnapshot();
1131 } else {
1132 ts = new ThreadSnapshot(jt);
1133 }
1134 dump_result.add_thread_snapshot(ts);
1135 }
1136 }
1137 } else {
1138 // obtain thread dump with the specific list of threads with stack trace
1140 do_thread_dump(&dump_result,
1141 ids_ah,
1142 num_threads,
1143 maxDepth,
1144 false, /* no locked monitor */
1145 false, /* no locked synchronizers */
1146 CHECK_0);
1147 }
1149 int num_snapshots = dump_result.num_snapshots();
1150 assert(num_snapshots == num_threads, "Must match the number of thread snapshots");
1151 int index = 0;
1152 for (ThreadSnapshot* ts = dump_result.snapshots(); ts != NULL; index++, ts = ts->next()) {
1153 // For each thread, create an java/lang/management/ThreadInfo object
1154 // and fill with the thread information
1156 if (ts->threadObj() == NULL) {
1157 // if the thread does not exist or now it is terminated, set threadinfo to NULL
1158 infoArray_h->obj_at_put(index, NULL);
1159 continue;
1160 }
1162 // Create java.lang.management.ThreadInfo object
1163 instanceOop info_obj = Management::create_thread_info_instance(ts, CHECK_0);
1164 infoArray_h->obj_at_put(index, info_obj);
1165 }
1166 return 0;
1167 JVM_END
1169 // Dump thread info for the specified threads.
1170 // It returns an array of ThreadInfo objects. Each element is the ThreadInfo
1171 // for the thread ID specified in the corresponding entry in
1172 // the given array of thread IDs; or NULL if the thread does not exist
1173 // or has terminated.
1174 //
1175 // Input parameter:
1176 // ids - array of thread IDs; NULL indicates all live threads
1177 // locked_monitors - if true, dump locked object monitors
1178 // locked_synchronizers - if true, dump locked JSR-166 synchronizers
1179 //
1180 JVM_ENTRY(jobjectArray, jmm_DumpThreads(JNIEnv *env, jlongArray thread_ids, jboolean locked_monitors, jboolean locked_synchronizers))
1181 ResourceMark rm(THREAD);
1183 if (JDK_Version::is_gte_jdk16x_version()) {
1184 // make sure the AbstractOwnableSynchronizer klass is loaded before taking thread snapshots
1185 java_util_concurrent_locks_AbstractOwnableSynchronizer::initialize(CHECK_NULL);
1186 }
1188 typeArrayOop ta = typeArrayOop(JNIHandles::resolve(thread_ids));
1189 int num_threads = (ta != NULL ? ta->length() : 0);
1190 typeArrayHandle ids_ah(THREAD, ta);
1192 ThreadDumpResult dump_result(num_threads); // can safepoint
1194 if (ids_ah() != NULL) {
1196 // validate the thread id array
1197 validate_thread_id_array(ids_ah, CHECK_NULL);
1199 // obtain thread dump of a specific list of threads
1200 do_thread_dump(&dump_result,
1201 ids_ah,
1202 num_threads,
1203 -1, /* entire stack */
1204 (locked_monitors ? true : false), /* with locked monitors */
1205 (locked_synchronizers ? true : false), /* with locked synchronizers */
1206 CHECK_NULL);
1207 } else {
1208 // obtain thread dump of all threads
1209 VM_ThreadDump op(&dump_result,
1210 -1, /* entire stack */
1211 (locked_monitors ? true : false), /* with locked monitors */
1212 (locked_synchronizers ? true : false) /* with locked synchronizers */);
1213 VMThread::execute(&op);
1214 }
1216 int num_snapshots = dump_result.num_snapshots();
1218 // create the result ThreadInfo[] object
1219 klassOop k = Management::java_lang_management_ThreadInfo_klass(CHECK_NULL);
1220 instanceKlassHandle ik (THREAD, k);
1221 objArrayOop r = oopFactory::new_objArray(ik(), num_snapshots, CHECK_NULL);
1222 objArrayHandle result_h(THREAD, r);
1224 int index = 0;
1225 for (ThreadSnapshot* ts = dump_result.snapshots(); ts != NULL; ts = ts->next(), index++) {
1226 if (ts->threadObj() == NULL) {
1227 // if the thread does not exist or now it is terminated, set threadinfo to NULL
1228 result_h->obj_at_put(index, NULL);
1229 continue;
1230 }
1234 ThreadStackTrace* stacktrace = ts->get_stack_trace();
1235 assert(stacktrace != NULL, "Must have a stack trace dumped");
1237 // Create Object[] filled with locked monitors
1238 // Create int[] filled with the stack depth where a monitor was locked
1239 int num_frames = stacktrace->get_stack_depth();
1240 int num_locked_monitors = stacktrace->num_jni_locked_monitors();
1242 // Count the total number of locked monitors
1243 for (int i = 0; i < num_frames; i++) {
1244 StackFrameInfo* frame = stacktrace->stack_frame_at(i);
1245 num_locked_monitors += frame->num_locked_monitors();
1246 }
1248 objArrayHandle monitors_array;
1249 typeArrayHandle depths_array;
1250 objArrayHandle synchronizers_array;
1252 if (locked_monitors) {
1253 // Constructs Object[] and int[] to contain the object monitor and the stack depth
1254 // where the thread locked it
1255 objArrayOop array = oopFactory::new_system_objArray(num_locked_monitors, CHECK_NULL);
1256 objArrayHandle mh(THREAD, array);
1257 monitors_array = mh;
1259 typeArrayOop tarray = oopFactory::new_typeArray(T_INT, num_locked_monitors, CHECK_NULL);
1260 typeArrayHandle dh(THREAD, tarray);
1261 depths_array = dh;
1263 int count = 0;
1264 int j = 0;
1265 for (int depth = 0; depth < num_frames; depth++) {
1266 StackFrameInfo* frame = stacktrace->stack_frame_at(depth);
1267 int len = frame->num_locked_monitors();
1268 GrowableArray<oop>* locked_monitors = frame->locked_monitors();
1269 for (j = 0; j < len; j++) {
1270 oop monitor = locked_monitors->at(j);
1271 assert(monitor != NULL && monitor->is_instance(), "must be a Java object");
1272 monitors_array->obj_at_put(count, monitor);
1273 depths_array->int_at_put(count, depth);
1274 count++;
1275 }
1276 }
1278 GrowableArray<oop>* jni_locked_monitors = stacktrace->jni_locked_monitors();
1279 for (j = 0; j < jni_locked_monitors->length(); j++) {
1280 oop object = jni_locked_monitors->at(j);
1281 assert(object != NULL && object->is_instance(), "must be a Java object");
1282 monitors_array->obj_at_put(count, object);
1283 // Monitor locked via JNI MonitorEnter call doesn't have stack depth info
1284 depths_array->int_at_put(count, -1);
1285 count++;
1286 }
1287 assert(count == num_locked_monitors, "number of locked monitors doesn't match");
1288 }
1290 if (locked_synchronizers) {
1291 // Create Object[] filled with locked JSR-166 synchronizers
1292 assert(ts->threadObj() != NULL, "Must be a valid JavaThread");
1293 ThreadConcurrentLocks* tcl = ts->get_concurrent_locks();
1294 GrowableArray<instanceOop>* locks = (tcl != NULL ? tcl->owned_locks() : NULL);
1295 int num_locked_synchronizers = (locks != NULL ? locks->length() : 0);
1297 objArrayOop array = oopFactory::new_system_objArray(num_locked_synchronizers, CHECK_NULL);
1298 objArrayHandle sh(THREAD, array);
1299 synchronizers_array = sh;
1301 for (int k = 0; k < num_locked_synchronizers; k++) {
1302 synchronizers_array->obj_at_put(k, locks->at(k));
1303 }
1304 }
1306 // Create java.lang.management.ThreadInfo object
1307 instanceOop info_obj = Management::create_thread_info_instance(ts,
1308 monitors_array,
1309 depths_array,
1310 synchronizers_array,
1311 CHECK_NULL);
1312 result_h->obj_at_put(index, info_obj);
1313 }
1315 return (jobjectArray) JNIHandles::make_local(env, result_h());
1316 JVM_END
1318 // Returns an array of Class objects.
1319 JVM_ENTRY(jobjectArray, jmm_GetLoadedClasses(JNIEnv *env))
1320 ResourceMark rm(THREAD);
1322 LoadedClassesEnumerator lce(THREAD); // Pass current Thread as parameter
1324 int num_classes = lce.num_loaded_classes();
1325 objArrayOop r = oopFactory::new_objArray(SystemDictionary::Class_klass(), num_classes, CHECK_0);
1326 objArrayHandle classes_ah(THREAD, r);
1328 for (int i = 0; i < num_classes; i++) {
1329 KlassHandle kh = lce.get_klass(i);
1330 oop mirror = Klass::cast(kh())->java_mirror();
1331 classes_ah->obj_at_put(i, mirror);
1332 }
1334 return (jobjectArray) JNIHandles::make_local(env, classes_ah());
1335 JVM_END
1337 // Reset statistic. Return true if the requested statistic is reset.
1338 // Otherwise, return false.
1339 //
1340 // Input parameters:
1341 // obj - specify which instance the statistic associated with to be reset
1342 // For PEAK_POOL_USAGE stat, obj is required to be a memory pool object.
1343 // For THREAD_CONTENTION_COUNT and TIME stat, obj is required to be a thread ID.
1344 // type - the type of statistic to be reset
1345 //
1346 JVM_ENTRY(jboolean, jmm_ResetStatistic(JNIEnv *env, jvalue obj, jmmStatisticType type))
1347 ResourceMark rm(THREAD);
1349 switch (type) {
1350 case JMM_STAT_PEAK_THREAD_COUNT:
1351 ThreadService::reset_peak_thread_count();
1352 return true;
1354 case JMM_STAT_THREAD_CONTENTION_COUNT:
1355 case JMM_STAT_THREAD_CONTENTION_TIME: {
1356 jlong tid = obj.j;
1357 if (tid < 0) {
1358 THROW_(vmSymbols::java_lang_IllegalArgumentException(), JNI_FALSE);
1359 }
1361 // Look for the JavaThread of this given tid
1362 MutexLockerEx ml(Threads_lock);
1363 if (tid == 0) {
1364 // reset contention statistics for all threads if tid == 0
1365 for (JavaThread* java_thread = Threads::first(); java_thread != NULL; java_thread = java_thread->next()) {
1366 if (type == JMM_STAT_THREAD_CONTENTION_COUNT) {
1367 ThreadService::reset_contention_count_stat(java_thread);
1368 } else {
1369 ThreadService::reset_contention_time_stat(java_thread);
1370 }
1371 }
1372 } else {
1373 // reset contention statistics for a given thread
1374 JavaThread* java_thread = find_java_thread_from_id(tid);
1375 if (java_thread == NULL) {
1376 return false;
1377 }
1379 if (type == JMM_STAT_THREAD_CONTENTION_COUNT) {
1380 ThreadService::reset_contention_count_stat(java_thread);
1381 } else {
1382 ThreadService::reset_contention_time_stat(java_thread);
1383 }
1384 }
1385 return true;
1386 break;
1387 }
1388 case JMM_STAT_PEAK_POOL_USAGE: {
1389 jobject o = obj.l;
1390 if (o == NULL) {
1391 THROW_(vmSymbols::java_lang_NullPointerException(), JNI_FALSE);
1392 }
1394 oop pool_obj = JNIHandles::resolve(o);
1395 assert(pool_obj->is_instance(), "Should be an instanceOop");
1396 instanceHandle ph(THREAD, (instanceOop) pool_obj);
1398 MemoryPool* pool = MemoryService::get_memory_pool(ph);
1399 if (pool != NULL) {
1400 pool->reset_peak_memory_usage();
1401 return true;
1402 }
1403 break;
1404 }
1405 case JMM_STAT_GC_STAT: {
1406 jobject o = obj.l;
1407 if (o == NULL) {
1408 THROW_(vmSymbols::java_lang_NullPointerException(), JNI_FALSE);
1409 }
1411 GCMemoryManager* mgr = get_gc_memory_manager_from_jobject(o, CHECK_0);
1412 if (mgr != NULL) {
1413 mgr->reset_gc_stat();
1414 return true;
1415 }
1416 break;
1417 }
1418 default:
1419 assert(0, "Unknown Statistic Type");
1420 }
1421 return false;
1422 JVM_END
1424 // Returns the fast estimate of CPU time consumed by
1425 // a given thread (in nanoseconds).
1426 // If thread_id == 0, return CPU time for the current thread.
1427 JVM_ENTRY(jlong, jmm_GetThreadCpuTime(JNIEnv *env, jlong thread_id))
1428 if (!os::is_thread_cpu_time_supported()) {
1429 return -1;
1430 }
1432 if (thread_id < 0) {
1433 THROW_MSG_(vmSymbols::java_lang_IllegalArgumentException(),
1434 "Invalid thread ID", -1);
1435 }
1437 JavaThread* java_thread = NULL;
1438 if (thread_id == 0) {
1439 // current thread
1440 return os::current_thread_cpu_time();
1441 } else {
1442 MutexLockerEx ml(Threads_lock);
1443 java_thread = find_java_thread_from_id(thread_id);
1444 if (java_thread != NULL) {
1445 return os::thread_cpu_time((Thread*) java_thread);
1446 }
1447 }
1448 return -1;
1449 JVM_END
1451 // Returns the CPU time consumed by a given thread (in nanoseconds).
1452 // If thread_id == 0, CPU time for the current thread is returned.
1453 // If user_sys_cpu_time = true, user level and system CPU time of
1454 // a given thread is returned; otherwise, only user level CPU time
1455 // is returned.
1456 JVM_ENTRY(jlong, jmm_GetThreadCpuTimeWithKind(JNIEnv *env, jlong thread_id, jboolean user_sys_cpu_time))
1457 if (!os::is_thread_cpu_time_supported()) {
1458 return -1;
1459 }
1461 if (thread_id < 0) {
1462 THROW_MSG_(vmSymbols::java_lang_IllegalArgumentException(),
1463 "Invalid thread ID", -1);
1464 }
1466 JavaThread* java_thread = NULL;
1467 if (thread_id == 0) {
1468 // current thread
1469 return os::current_thread_cpu_time(user_sys_cpu_time != 0);
1470 } else {
1471 MutexLockerEx ml(Threads_lock);
1472 java_thread = find_java_thread_from_id(thread_id);
1473 if (java_thread != NULL) {
1474 return os::thread_cpu_time((Thread*) java_thread, user_sys_cpu_time != 0);
1475 }
1476 }
1477 return -1;
1478 JVM_END
1480 // Returns a String array of all VM global flag names
1481 JVM_ENTRY(jobjectArray, jmm_GetVMGlobalNames(JNIEnv *env))
1482 // last flag entry is always NULL, so subtract 1
1483 int nFlags = (int) Flag::numFlags - 1;
1484 // allocate a temp array
1485 objArrayOop r = oopFactory::new_objArray(SystemDictionary::String_klass(),
1486 nFlags, CHECK_0);
1487 objArrayHandle flags_ah(THREAD, r);
1488 int num_entries = 0;
1489 for (int i = 0; i < nFlags; i++) {
1490 Flag* flag = &Flag::flags[i];
1491 // Exclude the locked (experimental, diagnostic) flags
1492 if (flag->is_unlocked() || flag->is_unlocker()) {
1493 Handle s = java_lang_String::create_from_str(flag->name, CHECK_0);
1494 flags_ah->obj_at_put(num_entries, s());
1495 num_entries++;
1496 }
1497 }
1499 if (num_entries < nFlags) {
1500 // Return array of right length
1501 objArrayOop res = oopFactory::new_objArray(SystemDictionary::String_klass(), num_entries, CHECK_0);
1502 for(int i = 0; i < num_entries; i++) {
1503 res->obj_at_put(i, flags_ah->obj_at(i));
1504 }
1505 return (jobjectArray)JNIHandles::make_local(env, res);
1506 }
1508 return (jobjectArray)JNIHandles::make_local(env, flags_ah());
1509 JVM_END
1511 // Utility function used by jmm_GetVMGlobals. Returns false if flag type
1512 // can't be determined, true otherwise. If false is returned, then *global
1513 // will be incomplete and invalid.
1514 bool add_global_entry(JNIEnv* env, Handle name, jmmVMGlobal *global, Flag *flag, TRAPS) {
1515 Handle flag_name;
1516 if (name() == NULL) {
1517 flag_name = java_lang_String::create_from_str(flag->name, CHECK_false);
1518 } else {
1519 flag_name = name;
1520 }
1521 global->name = (jstring)JNIHandles::make_local(env, flag_name());
1523 if (flag->is_bool()) {
1524 global->value.z = flag->get_bool() ? JNI_TRUE : JNI_FALSE;
1525 global->type = JMM_VMGLOBAL_TYPE_JBOOLEAN;
1526 } else if (flag->is_intx()) {
1527 global->value.j = (jlong)flag->get_intx();
1528 global->type = JMM_VMGLOBAL_TYPE_JLONG;
1529 } else if (flag->is_uintx()) {
1530 global->value.j = (jlong)flag->get_uintx();
1531 global->type = JMM_VMGLOBAL_TYPE_JLONG;
1532 } else if (flag->is_uint64_t()) {
1533 global->value.j = (jlong)flag->get_uint64_t();
1534 global->type = JMM_VMGLOBAL_TYPE_JLONG;
1535 } else if (flag->is_ccstr()) {
1536 Handle str = java_lang_String::create_from_str(flag->get_ccstr(), CHECK_false);
1537 global->value.l = (jobject)JNIHandles::make_local(env, str());
1538 global->type = JMM_VMGLOBAL_TYPE_JSTRING;
1539 } else {
1540 global->type = JMM_VMGLOBAL_TYPE_UNKNOWN;
1541 return false;
1542 }
1544 global->writeable = flag->is_writeable();
1545 global->external = flag->is_external();
1546 switch (flag->origin) {
1547 case DEFAULT:
1548 global->origin = JMM_VMGLOBAL_ORIGIN_DEFAULT;
1549 break;
1550 case COMMAND_LINE:
1551 global->origin = JMM_VMGLOBAL_ORIGIN_COMMAND_LINE;
1552 break;
1553 case ENVIRON_VAR:
1554 global->origin = JMM_VMGLOBAL_ORIGIN_ENVIRON_VAR;
1555 break;
1556 case CONFIG_FILE:
1557 global->origin = JMM_VMGLOBAL_ORIGIN_CONFIG_FILE;
1558 break;
1559 case MANAGEMENT:
1560 global->origin = JMM_VMGLOBAL_ORIGIN_MANAGEMENT;
1561 break;
1562 case ERGONOMIC:
1563 global->origin = JMM_VMGLOBAL_ORIGIN_ERGONOMIC;
1564 break;
1565 default:
1566 global->origin = JMM_VMGLOBAL_ORIGIN_OTHER;
1567 }
1569 return true;
1570 }
1572 // Fill globals array of count length with jmmVMGlobal entries
1573 // specified by names. If names == NULL, fill globals array
1574 // with all Flags. Return value is number of entries
1575 // created in globals.
1576 // If a Flag with a given name in an array element does not
1577 // exist, globals[i].name will be set to NULL.
1578 JVM_ENTRY(jint, jmm_GetVMGlobals(JNIEnv *env,
1579 jobjectArray names,
1580 jmmVMGlobal *globals,
1581 jint count))
1584 if (globals == NULL) {
1585 THROW_(vmSymbols::java_lang_NullPointerException(), 0);
1586 }
1588 ResourceMark rm(THREAD);
1590 if (names != NULL) {
1591 // return the requested globals
1592 objArrayOop ta = objArrayOop(JNIHandles::resolve_non_null(names));
1593 objArrayHandle names_ah(THREAD, ta);
1594 // Make sure we have a String array
1595 klassOop element_klass = objArrayKlass::cast(names_ah->klass())->element_klass();
1596 if (element_klass != SystemDictionary::String_klass()) {
1597 THROW_MSG_(vmSymbols::java_lang_IllegalArgumentException(),
1598 "Array element type is not String class", 0);
1599 }
1601 int names_length = names_ah->length();
1602 int num_entries = 0;
1603 for (int i = 0; i < names_length && i < count; i++) {
1604 oop s = names_ah->obj_at(i);
1605 if (s == NULL) {
1606 THROW_(vmSymbols::java_lang_NullPointerException(), 0);
1607 }
1609 Handle sh(THREAD, s);
1610 char* str = java_lang_String::as_utf8_string(s);
1611 Flag* flag = Flag::find_flag(str, strlen(str));
1612 if (flag != NULL &&
1613 add_global_entry(env, sh, &globals[i], flag, THREAD)) {
1614 num_entries++;
1615 } else {
1616 globals[i].name = NULL;
1617 }
1618 }
1619 return num_entries;
1620 } else {
1621 // return all globals if names == NULL
1623 // last flag entry is always NULL, so subtract 1
1624 int nFlags = (int) Flag::numFlags - 1;
1625 Handle null_h;
1626 int num_entries = 0;
1627 for (int i = 0; i < nFlags && num_entries < count; i++) {
1628 Flag* flag = &Flag::flags[i];
1629 // Exclude the locked (diagnostic, experimental) flags
1630 if ((flag->is_unlocked() || flag->is_unlocker()) &&
1631 add_global_entry(env, null_h, &globals[num_entries], flag, THREAD)) {
1632 num_entries++;
1633 }
1634 }
1635 return num_entries;
1636 }
1637 JVM_END
1639 JVM_ENTRY(void, jmm_SetVMGlobal(JNIEnv *env, jstring flag_name, jvalue new_value))
1640 ResourceMark rm(THREAD);
1642 oop fn = JNIHandles::resolve_external_guard(flag_name);
1643 if (fn == NULL) {
1644 THROW_MSG(vmSymbols::java_lang_NullPointerException(),
1645 "The flag name cannot be null.");
1646 }
1647 char* name = java_lang_String::as_utf8_string(fn);
1648 Flag* flag = Flag::find_flag(name, strlen(name));
1649 if (flag == NULL) {
1650 THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(),
1651 "Flag does not exist.");
1652 }
1653 if (!flag->is_writeable()) {
1654 THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(),
1655 "This flag is not writeable.");
1656 }
1658 bool succeed;
1659 if (flag->is_bool()) {
1660 bool bvalue = (new_value.z == JNI_TRUE ? true : false);
1661 succeed = CommandLineFlags::boolAtPut(name, &bvalue, MANAGEMENT);
1662 } else if (flag->is_intx()) {
1663 intx ivalue = (intx)new_value.j;
1664 succeed = CommandLineFlags::intxAtPut(name, &ivalue, MANAGEMENT);
1665 } else if (flag->is_uintx()) {
1666 uintx uvalue = (uintx)new_value.j;
1667 succeed = CommandLineFlags::uintxAtPut(name, &uvalue, MANAGEMENT);
1668 } else if (flag->is_uint64_t()) {
1669 uint64_t uvalue = (uint64_t)new_value.j;
1670 succeed = CommandLineFlags::uint64_tAtPut(name, &uvalue, MANAGEMENT);
1671 } else if (flag->is_ccstr()) {
1672 oop str = JNIHandles::resolve_external_guard(new_value.l);
1673 if (str == NULL) {
1674 THROW(vmSymbols::java_lang_NullPointerException());
1675 }
1676 ccstr svalue = java_lang_String::as_utf8_string(str);
1677 succeed = CommandLineFlags::ccstrAtPut(name, &svalue, MANAGEMENT);
1678 }
1679 assert(succeed, "Setting flag should succeed");
1680 JVM_END
1682 class ThreadTimesClosure: public ThreadClosure {
1683 private:
1684 objArrayOop _names;
1685 typeArrayOop _times;
1686 int _names_len;
1687 int _times_len;
1688 int _count;
1690 public:
1691 ThreadTimesClosure(objArrayOop names, typeArrayOop times);
1692 virtual void do_thread(Thread* thread);
1693 int count() { return _count; }
1694 };
1696 ThreadTimesClosure::ThreadTimesClosure(objArrayOop names,
1697 typeArrayOop times) {
1698 assert(names != NULL, "names was NULL");
1699 assert(times != NULL, "times was NULL");
1700 _names = names;
1701 _names_len = names->length();
1702 _times = times;
1703 _times_len = times->length();
1704 _count = 0;
1705 }
1707 void ThreadTimesClosure::do_thread(Thread* thread) {
1708 Handle s;
1709 assert(thread != NULL, "thread was NULL");
1711 // exclude externally visible JavaThreads
1712 if (thread->is_Java_thread() && !thread->is_hidden_from_external_view()) {
1713 return;
1714 }
1716 if (_count >= _names_len || _count >= _times_len) {
1717 // skip if the result array is not big enough
1718 return;
1719 }
1721 EXCEPTION_MARK;
1723 assert(thread->name() != NULL, "All threads should have a name");
1724 s = java_lang_String::create_from_str(thread->name(), CHECK);
1725 _names->obj_at_put(_count, s());
1727 _times->long_at_put(_count, os::is_thread_cpu_time_supported() ?
1728 os::thread_cpu_time(thread) : -1);
1729 _count++;
1730 }
1732 // Fills names with VM internal thread names and times with the corresponding
1733 // CPU times. If names or times is NULL, a NullPointerException is thrown.
1734 // If the element type of names is not String, an IllegalArgumentException is
1735 // thrown.
1736 // If an array is not large enough to hold all the entries, only the entries
1737 // that fit will be returned. Return value is the number of VM internal
1738 // threads entries.
1739 JVM_ENTRY(jint, jmm_GetInternalThreadTimes(JNIEnv *env,
1740 jobjectArray names,
1741 jlongArray times))
1742 if (names == NULL || times == NULL) {
1743 THROW_(vmSymbols::java_lang_NullPointerException(), 0);
1744 }
1745 objArrayOop na = objArrayOop(JNIHandles::resolve_non_null(names));
1746 objArrayHandle names_ah(THREAD, na);
1748 // Make sure we have a String array
1749 klassOop element_klass = objArrayKlass::cast(names_ah->klass())->element_klass();
1750 if (element_klass != SystemDictionary::String_klass()) {
1751 THROW_MSG_(vmSymbols::java_lang_IllegalArgumentException(),
1752 "Array element type is not String class", 0);
1753 }
1755 typeArrayOop ta = typeArrayOop(JNIHandles::resolve_non_null(times));
1756 typeArrayHandle times_ah(THREAD, ta);
1758 ThreadTimesClosure ttc(names_ah(), times_ah());
1759 {
1760 MutexLockerEx ml(Threads_lock);
1761 Threads::threads_do(&ttc);
1762 }
1764 return ttc.count();
1765 JVM_END
1767 static Handle find_deadlocks(bool object_monitors_only, TRAPS) {
1768 ResourceMark rm(THREAD);
1770 VM_FindDeadlocks op(!object_monitors_only /* also check concurrent locks? */);
1771 VMThread::execute(&op);
1773 DeadlockCycle* deadlocks = op.result();
1774 if (deadlocks == NULL) {
1775 // no deadlock found and return
1776 return Handle();
1777 }
1779 int num_threads = 0;
1780 DeadlockCycle* cycle;
1781 for (cycle = deadlocks; cycle != NULL; cycle = cycle->next()) {
1782 num_threads += cycle->num_threads();
1783 }
1785 objArrayOop r = oopFactory::new_objArray(SystemDictionary::Thread_klass(), num_threads, CHECK_NH);
1786 objArrayHandle threads_ah(THREAD, r);
1788 int index = 0;
1789 for (cycle = deadlocks; cycle != NULL; cycle = cycle->next()) {
1790 GrowableArray<JavaThread*>* deadlock_threads = cycle->threads();
1791 int len = deadlock_threads->length();
1792 for (int i = 0; i < len; i++) {
1793 threads_ah->obj_at_put(index, deadlock_threads->at(i)->threadObj());
1794 index++;
1795 }
1796 }
1797 return threads_ah;
1798 }
1800 // Finds cycles of threads that are deadlocked involved in object monitors
1801 // and JSR-166 synchronizers.
1802 // Returns an array of Thread objects which are in deadlock, if any.
1803 // Otherwise, returns NULL.
1804 //
1805 // Input parameter:
1806 // object_monitors_only - if true, only check object monitors
1807 //
1808 JVM_ENTRY(jobjectArray, jmm_FindDeadlockedThreads(JNIEnv *env, jboolean object_monitors_only))
1809 Handle result = find_deadlocks(object_monitors_only != 0, CHECK_0);
1810 return (jobjectArray) JNIHandles::make_local(env, result());
1811 JVM_END
1813 // Finds cycles of threads that are deadlocked on monitor locks
1814 // Returns an array of Thread objects which are in deadlock, if any.
1815 // Otherwise, returns NULL.
1816 JVM_ENTRY(jobjectArray, jmm_FindMonitorDeadlockedThreads(JNIEnv *env))
1817 Handle result = find_deadlocks(true, CHECK_0);
1818 return (jobjectArray) JNIHandles::make_local(env, result());
1819 JVM_END
1821 // Gets the information about GC extension attributes including
1822 // the name of the attribute, its type, and a short description.
1823 //
1824 // Input parameters:
1825 // mgr - GC memory manager
1826 // info - caller allocated array of jmmExtAttributeInfo
1827 // count - number of elements of the info array
1828 //
1829 // Returns the number of GC extension attributes filled in the info array; or
1830 // -1 if info is not big enough
1831 //
1832 JVM_ENTRY(jint, jmm_GetGCExtAttributeInfo(JNIEnv *env, jobject mgr, jmmExtAttributeInfo* info, jint count))
1833 // All GC memory managers have 1 attribute (number of GC threads)
1834 if (count == 0) {
1835 return 0;
1836 }
1838 if (info == NULL) {
1839 THROW_(vmSymbols::java_lang_NullPointerException(), 0);
1840 }
1842 info[0].name = "GcThreadCount";
1843 info[0].type = 'I';
1844 info[0].description = "Number of GC threads";
1845 return 1;
1846 JVM_END
1848 // verify the given array is an array of java/lang/management/MemoryUsage objects
1849 // of a given length and return the objArrayOop
1850 static objArrayOop get_memory_usage_objArray(jobjectArray array, int length, TRAPS) {
1851 if (array == NULL) {
1852 THROW_(vmSymbols::java_lang_NullPointerException(), 0);
1853 }
1855 objArrayOop oa = objArrayOop(JNIHandles::resolve_non_null(array));
1856 objArrayHandle array_h(THREAD, oa);
1858 // array must be of the given length
1859 if (length != array_h->length()) {
1860 THROW_MSG_(vmSymbols::java_lang_IllegalArgumentException(),
1861 "The length of the given MemoryUsage array does not match the number of memory pools.", 0);
1862 }
1864 // check if the element of array is of type MemoryUsage class
1865 klassOop usage_klass = Management::java_lang_management_MemoryUsage_klass(CHECK_0);
1866 klassOop element_klass = objArrayKlass::cast(array_h->klass())->element_klass();
1867 if (element_klass != usage_klass) {
1868 THROW_MSG_(vmSymbols::java_lang_IllegalArgumentException(),
1869 "The element type is not MemoryUsage class", 0);
1870 }
1872 return array_h();
1873 }
1875 // Gets the statistics of the last GC of a given GC memory manager.
1876 // Input parameters:
1877 // obj - GarbageCollectorMXBean object
1878 // gc_stat - caller allocated jmmGCStat where:
1879 // a. before_gc_usage - array of MemoryUsage objects
1880 // b. after_gc_usage - array of MemoryUsage objects
1881 // c. gc_ext_attributes_values_size is set to the
1882 // gc_ext_attribute_values array allocated
1883 // d. gc_ext_attribute_values is a caller allocated array of jvalue.
1884 //
1885 // On return,
1886 // gc_index == 0 indicates no GC statistics available
1887 //
1888 // before_gc_usage and after_gc_usage - filled with per memory pool
1889 // before and after GC usage in the same order as the memory pools
1890 // returned by GetMemoryPools for a given GC memory manager.
1891 // num_gc_ext_attributes indicates the number of elements in
1892 // the gc_ext_attribute_values array is filled; or
1893 // -1 if the gc_ext_attributes_values array is not big enough
1894 //
1895 JVM_ENTRY(void, jmm_GetLastGCStat(JNIEnv *env, jobject obj, jmmGCStat *gc_stat))
1896 ResourceMark rm(THREAD);
1898 if (gc_stat->gc_ext_attribute_values_size > 0 && gc_stat->gc_ext_attribute_values == NULL) {
1899 THROW(vmSymbols::java_lang_NullPointerException());
1900 }
1902 // Get the GCMemoryManager
1903 GCMemoryManager* mgr = get_gc_memory_manager_from_jobject(obj, CHECK);
1905 // Make a copy of the last GC statistics
1906 // GC may occur while constructing the last GC information
1907 int num_pools = MemoryService::num_memory_pools();
1908 GCStatInfo* stat = new GCStatInfo(num_pools);
1909 if (mgr->get_last_gc_stat(stat) == 0) {
1910 gc_stat->gc_index = 0;
1911 return;
1912 }
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 }