comparison src/share/vm/services/management.cpp @ 0:a61af66fc99e jdk7-b24

Initial load
author duke
date Sat, 01 Dec 2007 00:00:00 +0000
parents
children d28aa69f0959
comparison
equal deleted inserted replaced
-1:000000000000 0:a61af66fc99e
1 /*
2 * Copyright 2003-2007 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 */
24
25 # include "incls/_precompiled.incl"
26 # include "incls/_management.cpp.incl"
27
28 PerfVariable* Management::_begin_vm_creation_time = NULL;
29 PerfVariable* Management::_end_vm_creation_time = NULL;
30 PerfVariable* Management::_vm_init_done_time = NULL;
31
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;
39
40 jmmOptionalSupport Management::_optional_support = {0};
41 TimeStamp Management::_stamp;
42
43 void management_init() {
44 Management::init();
45 ThreadService::init();
46 RuntimeService::init();
47 ClassLoadingService::init();
48 }
49
50 void Management::init() {
51 EXCEPTION_MARK;
52
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.
56
57 _begin_vm_creation_time =
58 PerfDataManager::create_variable(SUN_RT, "createVmBeginTime",
59 PerfData::U_None, CHECK);
60
61 _end_vm_creation_time =
62 PerfDataManager::create_variable(SUN_RT, "createVmEndTime",
63 PerfData::U_None, CHECK);
64
65 _vm_init_done_time =
66 PerfDataManager::create_variable(SUN_RT, "vmInitDoneTime",
67 PerfData::U_None, CHECK);
68
69 // Initialize optional support
70 _optional_support.isLowMemoryDetectionSupported = 1;
71 _optional_support.isCompilationTimeMonitoringSupported = 1;
72 _optional_support.isThreadContentionMonitoringSupported = 1;
73
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 }
88
89 void Management::initialize(TRAPS) {
90 // Start the low memory detector thread
91 LowMemoryDetector::initialize();
92
93 if (ManagementServer) {
94 ResourceMark rm(THREAD);
95 HandleMark hm(THREAD);
96
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);
106
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 }
115
116 void Management::get_optional_support(jmmOptionalSupport* support) {
117 memcpy(support, &_optional_support, sizeof(jmmOptionalSupport));
118 }
119
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 }
128
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;
133
134 _begin_vm_creation_time->set_value(begin);
135 _end_vm_creation_time->set_value(begin + duration);
136 PerfMemory::set_accessible(true);
137 }
138
139 jlong Management::timestamp() {
140 TimeStamp t;
141 t.update();
142 return t.ticks() - _stamp.ticks();
143 }
144
145 void Management::oops_do(OopClosure* f) {
146 MemoryService::oops_do(f);
147 ThreadService::oops_do(f);
148
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 }
157
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 }
164
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 }
171
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 }
178
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 }
185
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 }
192
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 }
199
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 }
206
207 static void initialize_ThreadInfo_constructor_arguments(JavaCallArguments* args, ThreadSnapshot* snapshot, TRAPS) {
208 Handle snapshot_thread(THREAD, snapshot->threadObj());
209
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 }
220
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 }
229
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 }
237
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 }
248
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);
253
254 JavaValue result(T_VOID);
255 JavaCallArguments args(14);
256
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);
261
262 // initialize the arguments for the ThreadInfo constructor
263 initialize_ThreadInfo_constructor_arguments(&args, snapshot, CHECK_NULL);
264
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);
272
273 return (instanceOop) element();
274 }
275
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);
283
284 JavaValue result(T_VOID);
285 JavaCallArguments args(17);
286
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);
291
292 // initialize the arguments for the ThreadInfo constructor
293 initialize_ThreadInfo_constructor_arguments(&args, snapshot, CHECK_NULL);
294
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);
299
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);
307
308 return (instanceOop) element();
309 }
310
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");
314
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 }
328
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);
335
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 }
342
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 }
351
352 static MemoryPool* get_memory_pool_from_jobject(jobject obj, TRAPS) {
353 if (obj == NULL) {
354 THROW_(vmSymbols::java_lang_NullPointerException(), NULL);
355 }
356
357 oop pool_obj = JNIHandles::resolve(obj);
358 assert(pool_obj->is_instance(), "Should be an instanceOop");
359 instanceHandle ph(THREAD, (instanceOop) pool_obj);
360
361 return MemoryService::get_memory_pool(ph);
362 }
363
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 }
371
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 }
382
383 }
384
385 static void validate_thread_info_array(objArrayHandle infoArray_h, TRAPS) {
386
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 }
394
395 }
396
397
398 static MemoryManager* get_memory_manager_from_jobject(jobject obj, TRAPS) {
399 if (obj == NULL) {
400 THROW_(vmSymbols::java_lang_NullPointerException(), NULL);
401 }
402
403 oop mgr_obj = JNIHandles::resolve(obj);
404 assert(mgr_obj->is_instance(), "Should be an instanceOop");
405 instanceHandle mh(THREAD, (instanceOop) mgr_obj);
406
407 return MemoryService::get_memory_manager(mh);
408 }
409
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
415
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
425
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);
429
430 if (Arguments::num_jvm_args() == 0 && Arguments::num_jvm_flags() == 0) {
431 return NULL;
432 }
433
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();
438
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;
449
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 }
462
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 }
467
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 }
476
477 Handle hargs = java_lang_String::create_from_platform_dependent_str(args, CHECK_NULL);
478 return JNIHandles::make_local(env, hargs());
479 JVM_END
480
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);
484
485 if (Arguments::num_jvm_args() == 0 && Arguments::num_jvm_flags() == 0) {
486 return NULL;
487 }
488
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();
493
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);
497
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
509
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);
516
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 }
528
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);
534
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
554
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);
561
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 }
573
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);
579
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
599
600
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);
605
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
615
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);
620
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
630
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);
635
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
645
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 }
651
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 }
660
661 MemoryPool* mpool = get_memory_pool_from_jobject(obj, CHECK);
662 assert(mpool != NULL, "MemoryPool should exist");
663
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 }
678
679 JVM_END
680
681
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 }
696
697 if (threshold > max_intx) {
698 THROW_MSG_(vmSymbols::java_lang_IllegalArgumentException(),
699 "Invalid threshold value > max value of size_t",
700 -1);
701 }
702
703 MemoryPool* pool = get_memory_pool_from_jobject(obj, CHECK_(0L));
704 assert(pool != NULL, "MemoryPool should exist");
705
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;
714
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;
721
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);
728
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);
735
736 default:
737 assert(false, "Unrecognized type");
738 return -1;
739 }
740
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
749
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);
754
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;
762
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();
769
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 }
778
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 }
787
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");
792
793 MemoryUsage usage((heap ? Arguments::initial_heap_size() : total_init),
794 total_used,
795 total_committed,
796 (heap ? Universe::heap()->max_capacity() : total_max));
797
798 Handle obj = MemoryService::create_MemoryUsage_obj(usage, CHECK_NULL);
799 return JNIHandles::make_local(env, obj());
800 JVM_END
801
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
818
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
835
836
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();
841
842 case JMM_GC_COUNT:
843 return mgr->gc_count();
844
845 case JMM_GC_EXT_ATTRIBUTE_INFO_SIZE:
846 // current implementation only has 1 ext attribute
847 return 1;
848
849 default:
850 assert(0, "Unrecognized GC attribute");
851 return -1;
852 }
853 }
854
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 };
863
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 }
869
870 _count++;
871 }
872
873 static jint get_vm_thread_count() {
874 VmThreadCountClosure vmtcc;
875 {
876 MutexLockerEx ml(Threads_lock);
877 Threads::threads_do(&vmtcc);
878 }
879
880 return vmtcc.count();
881 }
882
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 diagnostic flags
890 if (flag->is_unlocked() || flag->is_unlocker()) {
891 count++;
892 }
893 }
894 return count;
895 }
896
897 static jlong get_long_attribute(jmmLongAttribute att) {
898 switch (att) {
899 case JMM_CLASS_LOADED_COUNT:
900 return ClassLoadingService::loaded_class_count();
901
902 case JMM_CLASS_UNLOADED_COUNT:
903 return ClassLoadingService::unloaded_class_count();
904
905 case JMM_THREAD_TOTAL_COUNT:
906 return ThreadService::get_total_thread_count();
907
908 case JMM_THREAD_LIVE_COUNT:
909 return ThreadService::get_live_thread_count();
910
911 case JMM_THREAD_PEAK_COUNT:
912 return ThreadService::get_peak_thread_count();
913
914 case JMM_THREAD_DAEMON_COUNT:
915 return ThreadService::get_daemon_thread_count();
916
917 case JMM_JVM_INIT_DONE_TIME_MS:
918 return Management::vm_init_done_time();
919
920 case JMM_COMPILE_TOTAL_TIME_MS:
921 return Management::ticks_to_ms(CompileBroker::total_compilation_ticks());
922
923 case JMM_OS_PROCESS_ID:
924 return os::current_process_id();
925
926 // Hotspot-specific counters
927 case JMM_CLASS_LOADED_BYTES:
928 return ClassLoadingService::loaded_class_bytes();
929
930 case JMM_CLASS_UNLOADED_BYTES:
931 return ClassLoadingService::unloaded_class_bytes();
932
933 case JMM_SHARED_CLASS_LOADED_COUNT:
934 return ClassLoadingService::loaded_shared_class_count();
935
936 case JMM_SHARED_CLASS_UNLOADED_COUNT:
937 return ClassLoadingService::unloaded_shared_class_count();
938
939
940 case JMM_SHARED_CLASS_LOADED_BYTES:
941 return ClassLoadingService::loaded_shared_class_bytes();
942
943 case JMM_SHARED_CLASS_UNLOADED_BYTES:
944 return ClassLoadingService::unloaded_shared_class_bytes();
945
946 case JMM_TOTAL_CLASSLOAD_TIME_MS:
947 return ClassLoader::classloader_time_ms();
948
949 case JMM_VM_GLOBAL_COUNT:
950 return get_num_flags();
951
952 case JMM_SAFEPOINT_COUNT:
953 return RuntimeService::safepoint_count();
954
955 case JMM_TOTAL_SAFEPOINTSYNC_TIME_MS:
956 return RuntimeService::safepoint_sync_time_ms();
957
958 case JMM_TOTAL_STOPPED_TIME_MS:
959 return RuntimeService::safepoint_time_ms();
960
961 case JMM_TOTAL_APP_TIME_MS:
962 return RuntimeService::application_time_ms();
963
964 case JMM_VM_THREAD_COUNT:
965 return get_vm_thread_count();
966
967 case JMM_CLASS_INIT_TOTAL_COUNT:
968 return ClassLoader::class_init_count();
969
970 case JMM_CLASS_INIT_TOTAL_TIME_MS:
971 return ClassLoader::class_init_time_ms();
972
973 case JMM_CLASS_VERIFY_TOTAL_TIME_MS:
974 return ClassLoader::class_verify_time_ms();
975
976 case JMM_METHOD_DATA_SIZE_BYTES:
977 return ClassLoadingService::class_method_data_size();
978
979 case JMM_OS_MEM_TOTAL_PHYSICAL_BYTES:
980 return os::physical_memory();
981
982 default:
983 return -1;
984 }
985 }
986
987
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
1000
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))
1009
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
1029
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) {
1038
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 }
1052
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 }
1062
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 }
1080
1081 if (maxDepth < -1) {
1082 THROW_MSG_(vmSymbols::java_lang_IllegalArgumentException(),
1083 "Invalid maxDepth", -1);
1084 }
1085
1086 ResourceMark rm(THREAD);
1087 typeArrayOop ta = typeArrayOop(JNIHandles::resolve_non_null(ids));
1088 typeArrayHandle ids_ah(THREAD, ta);
1089
1090 oop infoArray_obj = JNIHandles::resolve_non_null(infoArray);
1091 objArrayOop oa = objArrayOop(infoArray_obj);
1092 objArrayHandle infoArray_h(THREAD, oa);
1093
1094 // validate the thread id array
1095 validate_thread_id_array(ids_ah, CHECK_0);
1096
1097 // validate the ThreadInfo[] parameters
1098 validate_thread_info_array(infoArray_h, CHECK_0);
1099
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 }
1106
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 }
1111
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);
1117
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
1138
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 }
1147
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
1154
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 }
1160
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
1167
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);
1181
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 }
1186
1187 typeArrayOop ta = typeArrayOop(JNIHandles::resolve(thread_ids));
1188 int num_threads = (ta != NULL ? ta->length() : 0);
1189 typeArrayHandle ids_ah(THREAD, ta);
1190
1191 ThreadDumpResult dump_result(num_threads); // can safepoint
1192
1193 if (ids_ah() != NULL) {
1194
1195 // validate the thread id array
1196 validate_thread_id_array(ids_ah, CHECK_NULL);
1197
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 }
1214
1215 int num_snapshots = dump_result.num_snapshots();
1216
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);
1222
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 }
1230
1231
1232
1233 ThreadStackTrace* stacktrace = ts->get_stack_trace();
1234 assert(stacktrace != NULL, "Must have a stack trace dumped");
1235
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();
1240
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 }
1246
1247 objArrayHandle monitors_array;
1248 typeArrayHandle depths_array;
1249 objArrayHandle synchronizers_array;
1250
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;
1257
1258 typeArrayOop tarray = oopFactory::new_typeArray(T_INT, num_locked_monitors, CHECK_NULL);
1259 typeArrayHandle dh(THREAD, tarray);
1260 depths_array = dh;
1261
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 }
1276
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 }
1288
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);
1295
1296 objArrayOop array = oopFactory::new_system_objArray(num_locked_synchronizers, CHECK_NULL);
1297 objArrayHandle sh(THREAD, array);
1298 synchronizers_array = sh;
1299
1300 for (int k = 0; k < num_locked_synchronizers; k++) {
1301 synchronizers_array->obj_at_put(k, locks->at(k));
1302 }
1303 }
1304
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 }
1313
1314 return (jobjectArray) JNIHandles::make_local(env, result_h());
1315 JVM_END
1316
1317 // Returns an array of Class objects.
1318 JVM_ENTRY(jobjectArray, jmm_GetLoadedClasses(JNIEnv *env))
1319 ResourceMark rm(THREAD);
1320
1321 LoadedClassesEnumerator lce(THREAD); // Pass current Thread as parameter
1322
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);
1326
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 }
1332
1333 return (jobjectArray) JNIHandles::make_local(env, classes_ah());
1334 JVM_END
1335
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);
1347
1348 switch (type) {
1349 case JMM_STAT_PEAK_THREAD_COUNT:
1350 ThreadService::reset_peak_thread_count();
1351 return true;
1352
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 }
1359
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 }
1377
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 }
1392
1393 oop pool_obj = JNIHandles::resolve(o);
1394 assert(pool_obj->is_instance(), "Should be an instanceOop");
1395 instanceHandle ph(THREAD, (instanceOop) pool_obj);
1396
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 }
1409
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
1422
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 }
1430
1431 if (thread_id < 0) {
1432 THROW_MSG_(vmSymbols::java_lang_IllegalArgumentException(),
1433 "Invalid thread ID", -1);
1434 }
1435
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
1449
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 }
1459
1460 if (thread_id < 0) {
1461 THROW_MSG_(vmSymbols::java_lang_IllegalArgumentException(),
1462 "Invalid thread ID", -1);
1463 }
1464
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
1478
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 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 }
1497
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 }
1506
1507 return (jobjectArray)JNIHandles::make_local(env, flags_ah());
1508 JVM_END
1509
1510 // utility function used by jmm_GetVMGlobals
1511 void add_global_entry(JNIEnv* env, Handle name, jmmVMGlobal *global, Flag *flag, TRAPS) {
1512 Handle flag_name;
1513 if (name() == NULL) {
1514 flag_name = java_lang_String::create_from_str(flag->name, CHECK);
1515 } else {
1516 flag_name = name;
1517 }
1518 global->name = (jstring)JNIHandles::make_local(env, flag_name());
1519 global->type = JMM_VMGLOBAL_TYPE_UNKNOWN;
1520
1521 if (flag->is_bool()) {
1522 global->value.z = flag->get_bool() ? JNI_TRUE : JNI_FALSE;
1523 global->type = JMM_VMGLOBAL_TYPE_JBOOLEAN;
1524 } else if (flag->is_intx()) {
1525 global->value.j = (jlong)flag->get_intx();
1526 global->type = JMM_VMGLOBAL_TYPE_JLONG;
1527 } else if (flag->is_uintx()) {
1528 global->value.j = (jlong)flag->get_uintx();
1529 global->type = JMM_VMGLOBAL_TYPE_JLONG;
1530 } else if (flag->is_ccstr()) {
1531 Handle str = java_lang_String::create_from_str(flag->get_ccstr(), CHECK);
1532 global->value.l = (jobject)JNIHandles::make_local(env, str());
1533 global->type = JMM_VMGLOBAL_TYPE_JSTRING;
1534 }
1535
1536 global->writeable = flag->is_writeable();
1537 global->external = flag->is_external();
1538 switch (flag->origin) {
1539 case DEFAULT:
1540 global->origin = JMM_VMGLOBAL_ORIGIN_DEFAULT;
1541 break;
1542 case COMMAND_LINE:
1543 global->origin = JMM_VMGLOBAL_ORIGIN_COMMAND_LINE;
1544 break;
1545 case ENVIRON_VAR:
1546 global->origin = JMM_VMGLOBAL_ORIGIN_ENVIRON_VAR;
1547 break;
1548 case CONFIG_FILE:
1549 global->origin = JMM_VMGLOBAL_ORIGIN_CONFIG_FILE;
1550 break;
1551 case MANAGEMENT:
1552 global->origin = JMM_VMGLOBAL_ORIGIN_MANAGEMENT;
1553 break;
1554 case ERGONOMIC:
1555 global->origin = JMM_VMGLOBAL_ORIGIN_ERGONOMIC;
1556 break;
1557 default:
1558 global->origin = JMM_VMGLOBAL_ORIGIN_OTHER;
1559 }
1560 }
1561
1562 // Fill globals array of count length with jmmVMGlobal entries
1563 // specified by names. If names == NULL, fill globals array
1564 // with all Flags. Return value is number of entries
1565 // created in globals.
1566 // If a Flag with a given name in an array element does not
1567 // exist, globals[i].name will be set to NULL.
1568 JVM_ENTRY(jint, jmm_GetVMGlobals(JNIEnv *env,
1569 jobjectArray names,
1570 jmmVMGlobal *globals,
1571 jint count))
1572
1573
1574 if (globals == NULL) {
1575 THROW_(vmSymbols::java_lang_NullPointerException(), 0);
1576 }
1577
1578 ResourceMark rm(THREAD);
1579
1580 if (names != NULL) {
1581 // return the requested globals
1582 objArrayOop ta = objArrayOop(JNIHandles::resolve_non_null(names));
1583 objArrayHandle names_ah(THREAD, ta);
1584 // Make sure we have a String array
1585 klassOop element_klass = objArrayKlass::cast(names_ah->klass())->element_klass();
1586 if (element_klass != SystemDictionary::string_klass()) {
1587 THROW_MSG_(vmSymbols::java_lang_IllegalArgumentException(),
1588 "Array element type is not String class", 0);
1589 }
1590
1591 int names_length = names_ah->length();
1592 int num_entries = 0;
1593 for (int i = 0; i < names_length && i < count; i++) {
1594 oop s = names_ah->obj_at(i);
1595 if (s == NULL) {
1596 THROW_(vmSymbols::java_lang_NullPointerException(), 0);
1597 }
1598
1599 Handle sh(THREAD, s);
1600 char* str = java_lang_String::as_utf8_string(s);
1601 Flag* flag = Flag::find_flag(str, strlen(str));
1602 if (flag != NULL) {
1603 add_global_entry(env, sh, &globals[i], flag, THREAD);
1604 num_entries++;
1605 } else {
1606 globals[i].name = NULL;
1607 }
1608 }
1609 return num_entries;
1610 } else {
1611 // return all globals if names == NULL
1612
1613 // last flag entry is always NULL, so subtract 1
1614 int nFlags = (int) Flag::numFlags - 1;
1615 Handle null_h;
1616 int num_entries = 0;
1617 for (int i = 0; i < nFlags && num_entries < count; i++) {
1618 Flag* flag = &Flag::flags[i];
1619 // Exclude the diagnostic flags
1620 if (flag->is_unlocked() || flag->is_unlocker()) {
1621 add_global_entry(env, null_h, &globals[num_entries], flag, THREAD);
1622 num_entries++;
1623 }
1624 }
1625 return num_entries;
1626 }
1627 JVM_END
1628
1629 JVM_ENTRY(void, jmm_SetVMGlobal(JNIEnv *env, jstring flag_name, jvalue new_value))
1630 ResourceMark rm(THREAD);
1631
1632 oop fn = JNIHandles::resolve_external_guard(flag_name);
1633 if (fn == NULL) {
1634 THROW_MSG(vmSymbols::java_lang_NullPointerException(),
1635 "The flag name cannot be null.");
1636 }
1637 char* name = java_lang_String::as_utf8_string(fn);
1638 Flag* flag = Flag::find_flag(name, strlen(name));
1639 if (flag == NULL) {
1640 THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(),
1641 "Flag does not exist.");
1642 }
1643 if (!flag->is_writeable()) {
1644 THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(),
1645 "This flag is not writeable.");
1646 }
1647
1648 bool succeed;
1649 if (flag->is_bool()) {
1650 bool bvalue = (new_value.z == JNI_TRUE ? true : false);
1651 succeed = CommandLineFlags::boolAtPut(name, &bvalue, MANAGEMENT);
1652 } else if (flag->is_intx()) {
1653 intx ivalue = new_value.j;
1654 succeed = CommandLineFlags::intxAtPut(name, &ivalue, MANAGEMENT);
1655 } else if (flag->is_uintx()) {
1656 uintx uvalue = new_value.j;
1657 succeed = CommandLineFlags::uintxAtPut(name, &uvalue, MANAGEMENT);
1658 } else if (flag->is_ccstr()) {
1659 oop str = JNIHandles::resolve_external_guard(new_value.l);
1660 if (str == NULL) {
1661 THROW(vmSymbols::java_lang_NullPointerException());
1662 }
1663 ccstr svalue = java_lang_String::as_utf8_string(str);
1664 succeed = CommandLineFlags::ccstrAtPut(name, &svalue, MANAGEMENT);
1665 }
1666 assert(succeed, "Setting flag should succeed");
1667 JVM_END
1668
1669 class ThreadTimesClosure: public ThreadClosure {
1670 private:
1671 objArrayOop _names;
1672 typeArrayOop _times;
1673 int _names_len;
1674 int _times_len;
1675 int _count;
1676
1677 public:
1678 ThreadTimesClosure(objArrayOop names, typeArrayOop times);
1679 virtual void do_thread(Thread* thread);
1680 int count() { return _count; }
1681 };
1682
1683 ThreadTimesClosure::ThreadTimesClosure(objArrayOop names,
1684 typeArrayOop times) {
1685 assert(names != NULL, "names was NULL");
1686 assert(times != NULL, "times was NULL");
1687 _names = names;
1688 _names_len = names->length();
1689 _times = times;
1690 _times_len = times->length();
1691 _count = 0;
1692 }
1693
1694 void ThreadTimesClosure::do_thread(Thread* thread) {
1695 Handle s;
1696 assert(thread != NULL, "thread was NULL");
1697
1698 // exclude externally visible JavaThreads
1699 if (thread->is_Java_thread() && !thread->is_hidden_from_external_view()) {
1700 return;
1701 }
1702
1703 if (_count >= _names_len || _count >= _times_len) {
1704 // skip if the result array is not big enough
1705 return;
1706 }
1707
1708 EXCEPTION_MARK;
1709
1710 assert(thread->name() != NULL, "All threads should have a name");
1711 s = java_lang_String::create_from_str(thread->name(), CHECK);
1712 _names->obj_at_put(_count, s());
1713
1714 _times->long_at_put(_count, os::is_thread_cpu_time_supported() ?
1715 os::thread_cpu_time(thread) : -1);
1716 _count++;
1717 }
1718
1719 // Fills names with VM internal thread names and times with the corresponding
1720 // CPU times. If names or times is NULL, a NullPointerException is thrown.
1721 // If the element type of names is not String, an IllegalArgumentException is
1722 // thrown.
1723 // If an array is not large enough to hold all the entries, only the entries
1724 // that fit will be returned. Return value is the number of VM internal
1725 // threads entries.
1726 JVM_ENTRY(jint, jmm_GetInternalThreadTimes(JNIEnv *env,
1727 jobjectArray names,
1728 jlongArray times))
1729 if (names == NULL || times == NULL) {
1730 THROW_(vmSymbols::java_lang_NullPointerException(), 0);
1731 }
1732 objArrayOop na = objArrayOop(JNIHandles::resolve_non_null(names));
1733 objArrayHandle names_ah(THREAD, na);
1734
1735 // Make sure we have a String array
1736 klassOop element_klass = objArrayKlass::cast(names_ah->klass())->element_klass();
1737 if (element_klass != SystemDictionary::string_klass()) {
1738 THROW_MSG_(vmSymbols::java_lang_IllegalArgumentException(),
1739 "Array element type is not String class", 0);
1740 }
1741
1742 typeArrayOop ta = typeArrayOop(JNIHandles::resolve_non_null(times));
1743 typeArrayHandle times_ah(THREAD, ta);
1744
1745 ThreadTimesClosure ttc(names_ah(), times_ah());
1746 {
1747 MutexLockerEx ml(Threads_lock);
1748 Threads::threads_do(&ttc);
1749 }
1750
1751 return ttc.count();
1752 JVM_END
1753
1754 static Handle find_deadlocks(bool object_monitors_only, TRAPS) {
1755 ResourceMark rm(THREAD);
1756
1757 VM_FindDeadlocks op(!object_monitors_only /* also check concurrent locks? */);
1758 VMThread::execute(&op);
1759
1760 DeadlockCycle* deadlocks = op.result();
1761 if (deadlocks == NULL) {
1762 // no deadlock found and return
1763 return Handle();
1764 }
1765
1766 int num_threads = 0;
1767 DeadlockCycle* cycle;
1768 for (cycle = deadlocks; cycle != NULL; cycle = cycle->next()) {
1769 num_threads += cycle->num_threads();
1770 }
1771
1772 objArrayOop r = oopFactory::new_objArray(SystemDictionary::thread_klass(), num_threads, CHECK_NH);
1773 objArrayHandle threads_ah(THREAD, r);
1774
1775 int index = 0;
1776 for (cycle = deadlocks; cycle != NULL; cycle = cycle->next()) {
1777 GrowableArray<JavaThread*>* deadlock_threads = cycle->threads();
1778 int len = deadlock_threads->length();
1779 for (int i = 0; i < len; i++) {
1780 threads_ah->obj_at_put(index, deadlock_threads->at(i)->threadObj());
1781 index++;
1782 }
1783 }
1784 return threads_ah;
1785 }
1786
1787 // Finds cycles of threads that are deadlocked involved in object monitors
1788 // and JSR-166 synchronizers.
1789 // Returns an array of Thread objects which are in deadlock, if any.
1790 // Otherwise, returns NULL.
1791 //
1792 // Input parameter:
1793 // object_monitors_only - if true, only check object monitors
1794 //
1795 JVM_ENTRY(jobjectArray, jmm_FindDeadlockedThreads(JNIEnv *env, jboolean object_monitors_only))
1796 Handle result = find_deadlocks(object_monitors_only != 0, CHECK_0);
1797 return (jobjectArray) JNIHandles::make_local(env, result());
1798 JVM_END
1799
1800 // Finds cycles of threads that are deadlocked on monitor locks
1801 // Returns an array of Thread objects which are in deadlock, if any.
1802 // Otherwise, returns NULL.
1803 JVM_ENTRY(jobjectArray, jmm_FindMonitorDeadlockedThreads(JNIEnv *env))
1804 Handle result = find_deadlocks(true, CHECK_0);
1805 return (jobjectArray) JNIHandles::make_local(env, result());
1806 JVM_END
1807
1808 // Gets the information about GC extension attributes including
1809 // the name of the attribute, its type, and a short description.
1810 //
1811 // Input parameters:
1812 // mgr - GC memory manager
1813 // info - caller allocated array of jmmExtAttributeInfo
1814 // count - number of elements of the info array
1815 //
1816 // Returns the number of GC extension attributes filled in the info array; or
1817 // -1 if info is not big enough
1818 //
1819 JVM_ENTRY(jint, jmm_GetGCExtAttributeInfo(JNIEnv *env, jobject mgr, jmmExtAttributeInfo* info, jint count))
1820 // All GC memory managers have 1 attribute (number of GC threads)
1821 if (count == 0) {
1822 return 0;
1823 }
1824
1825 if (info == NULL) {
1826 THROW_(vmSymbols::java_lang_NullPointerException(), 0);
1827 }
1828
1829 info[0].name = "GcThreadCount";
1830 info[0].type = 'I';
1831 info[0].description = "Number of GC threads";
1832 return 1;
1833 JVM_END
1834
1835 // verify the given array is an array of java/lang/management/MemoryUsage objects
1836 // of a given length and return the objArrayOop
1837 static objArrayOop get_memory_usage_objArray(jobjectArray array, int length, TRAPS) {
1838 if (array == NULL) {
1839 THROW_(vmSymbols::java_lang_NullPointerException(), 0);
1840 }
1841
1842 objArrayOop oa = objArrayOop(JNIHandles::resolve_non_null(array));
1843 objArrayHandle array_h(THREAD, oa);
1844
1845 // array must be of the given length
1846 if (length != array_h->length()) {
1847 THROW_MSG_(vmSymbols::java_lang_IllegalArgumentException(),
1848 "The length of the given MemoryUsage array does not match the number of memory pools.", 0);
1849 }
1850
1851 // check if the element of array is of type MemoryUsage class
1852 klassOop usage_klass = Management::java_lang_management_MemoryUsage_klass(CHECK_0);
1853 klassOop element_klass = objArrayKlass::cast(array_h->klass())->element_klass();
1854 if (element_klass != usage_klass) {
1855 THROW_MSG_(vmSymbols::java_lang_IllegalArgumentException(),
1856 "The element type is not MemoryUsage class", 0);
1857 }
1858
1859 return array_h();
1860 }
1861
1862 // Gets the statistics of the last GC of a given GC memory manager.
1863 // Input parameters:
1864 // obj - GarbageCollectorMXBean object
1865 // gc_stat - caller allocated jmmGCStat where:
1866 // a. before_gc_usage - array of MemoryUsage objects
1867 // b. after_gc_usage - array of MemoryUsage objects
1868 // c. gc_ext_attributes_values_size is set to the
1869 // gc_ext_attribute_values array allocated
1870 // d. gc_ext_attribute_values is a caller allocated array of jvalue.
1871 //
1872 // On return,
1873 // gc_index == 0 indicates no GC statistics available
1874 //
1875 // before_gc_usage and after_gc_usage - filled with per memory pool
1876 // before and after GC usage in the same order as the memory pools
1877 // returned by GetMemoryPools for a given GC memory manager.
1878 // num_gc_ext_attributes indicates the number of elements in
1879 // the gc_ext_attribute_values array is filled; or
1880 // -1 if the gc_ext_attributes_values array is not big enough
1881 //
1882 JVM_ENTRY(void, jmm_GetLastGCStat(JNIEnv *env, jobject obj, jmmGCStat *gc_stat))
1883 ResourceMark rm(THREAD);
1884
1885 if (gc_stat->gc_ext_attribute_values_size > 0 && gc_stat->gc_ext_attribute_values == NULL) {
1886 THROW(vmSymbols::java_lang_NullPointerException());
1887 }
1888
1889 // Get the GCMemoryManager
1890 GCMemoryManager* mgr = get_gc_memory_manager_from_jobject(obj, CHECK);
1891 if (mgr->last_gc_stat() == NULL) {
1892 gc_stat->gc_index = 0;
1893 return;
1894 }
1895
1896 // Make a copy of the last GC statistics
1897 // GC may occur while constructing the last GC information
1898 int num_pools = MemoryService::num_memory_pools();
1899 GCStatInfo* stat = new GCStatInfo(num_pools);
1900 stat->copy_stat(mgr->last_gc_stat());
1901
1902 gc_stat->gc_index = stat->gc_index();
1903 gc_stat->start_time = Management::ticks_to_ms(stat->start_time());
1904 gc_stat->end_time = Management::ticks_to_ms(stat->end_time());
1905
1906 // Current implementation does not have GC extension attributes
1907 gc_stat->num_gc_ext_attributes = 0;
1908
1909 // Fill the arrays of MemoryUsage objects with before and after GC
1910 // per pool memory usage
1911 objArrayOop bu = get_memory_usage_objArray(gc_stat->usage_before_gc,
1912 num_pools,
1913 CHECK);
1914 objArrayHandle usage_before_gc_ah(THREAD, bu);
1915
1916 objArrayOop au = get_memory_usage_objArray(gc_stat->usage_after_gc,
1917 num_pools,
1918 CHECK);
1919 objArrayHandle usage_after_gc_ah(THREAD, au);
1920
1921 for (int i = 0; i < num_pools; i++) {
1922 Handle before_usage = MemoryService::create_MemoryUsage_obj(stat->before_gc_usage_for_pool(i), CHECK);
1923 Handle after_usage;
1924
1925 MemoryUsage u = stat->after_gc_usage_for_pool(i);
1926 if (u.max_size() == 0 && u.used() > 0) {
1927 // If max size == 0, this pool is a survivor space.
1928 // Set max size = -1 since the pools will be swapped after GC.
1929 MemoryUsage usage(u.init_size(), u.used(), u.committed(), (size_t)-1);
1930 after_usage = MemoryService::create_MemoryUsage_obj(usage, CHECK);
1931 } else {
1932 after_usage = MemoryService::create_MemoryUsage_obj(stat->after_gc_usage_for_pool(i), CHECK);
1933 }
1934 usage_before_gc_ah->obj_at_put(i, before_usage());
1935 usage_after_gc_ah->obj_at_put(i, after_usage());
1936 }
1937
1938 if (gc_stat->gc_ext_attribute_values_size > 0) {
1939 // Current implementation only has 1 attribute (number of GC threads)
1940 // The type is 'I'
1941 gc_stat->gc_ext_attribute_values[0].i = mgr->num_gc_threads();
1942 }
1943 JVM_END
1944
1945 // Dump heap - Returns 0 if succeeds.
1946 JVM_ENTRY(jint, jmm_DumpHeap0(JNIEnv *env, jstring outputfile, jboolean live))
1947 #ifndef SERVICES_KERNEL
1948 ResourceMark rm(THREAD);
1949 oop on = JNIHandles::resolve_external_guard(outputfile);
1950 if (on == NULL) {
1951 THROW_MSG_(vmSymbols::java_lang_NullPointerException(),
1952 "Output file name cannot be null.", -1);
1953 }
1954 char* name = java_lang_String::as_utf8_string(on);
1955 if (name == NULL) {
1956 THROW_MSG_(vmSymbols::java_lang_NullPointerException(),
1957 "Output file name cannot be null.", -1);
1958 }
1959 HeapDumper dumper(live ? true : false);
1960 if (dumper.dump(name) != 0) {
1961 const char* errmsg = dumper.error_as_C_string();
1962 THROW_MSG_(vmSymbols::java_io_IOException(), errmsg, -1);
1963 }
1964 return 0;
1965 #else // SERVICES_KERNEL
1966 return -1;
1967 #endif // SERVICES_KERNEL
1968 JVM_END
1969
1970 jlong Management::ticks_to_ms(jlong ticks) {
1971 assert(os::elapsed_frequency() > 0, "Must be non-zero");
1972 return (jlong)(((double)ticks / (double)os::elapsed_frequency())
1973 * (double)1000.0);
1974 }
1975
1976 const struct jmmInterface_1_ jmm_interface = {
1977 NULL,
1978 NULL,
1979 jmm_GetVersion,
1980 jmm_GetOptionalSupport,
1981 jmm_GetInputArguments,
1982 jmm_GetThreadInfo,
1983 jmm_GetInputArgumentArray,
1984 jmm_GetMemoryPools,
1985 jmm_GetMemoryManagers,
1986 jmm_GetMemoryPoolUsage,
1987 jmm_GetPeakMemoryPoolUsage,
1988 NULL,
1989 jmm_GetMemoryUsage,
1990 jmm_GetLongAttribute,
1991 jmm_GetBoolAttribute,
1992 jmm_SetBoolAttribute,
1993 jmm_GetLongAttributes,
1994 jmm_FindMonitorDeadlockedThreads,
1995 jmm_GetThreadCpuTime,
1996 jmm_GetVMGlobalNames,
1997 jmm_GetVMGlobals,
1998 jmm_GetInternalThreadTimes,
1999 jmm_ResetStatistic,
2000 jmm_SetPoolSensor,
2001 jmm_SetPoolThreshold,
2002 jmm_GetPoolCollectionUsage,
2003 jmm_GetGCExtAttributeInfo,
2004 jmm_GetLastGCStat,
2005 jmm_GetThreadCpuTimeWithKind,
2006 NULL,
2007 jmm_DumpHeap0,
2008 jmm_FindDeadlockedThreads,
2009 jmm_SetVMGlobal,
2010 NULL,
2011 jmm_DumpThreads
2012 };
2013
2014 void* Management::get_jmm_interface(int version) {
2015 if (version == JMM_VERSION_1_0) {
2016 return (void*) &jmm_interface;
2017 }
2018 return NULL;
2019 }