management.cpp revision 1677:1c63587d925b
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 */
24
25# include "incls/_precompiled.incl"
26# include "incls/_management.cpp.incl"
27
28PerfVariable* Management::_begin_vm_creation_time = NULL;
29PerfVariable* Management::_end_vm_creation_time = NULL;
30PerfVariable* Management::_vm_init_done_time = NULL;
31
32klassOop Management::_sensor_klass = NULL;
33klassOop Management::_threadInfo_klass = NULL;
34klassOop Management::_memoryUsage_klass = NULL;
35klassOop Management::_memoryPoolMXBean_klass = NULL;
36klassOop Management::_memoryManagerMXBean_klass = NULL;
37klassOop Management::_garbageCollectorMXBean_klass = NULL;
38klassOop Management::_managementFactory_klass = NULL;
39
40jmmOptionalSupport Management::_optional_support = {0};
41TimeStamp Management::_stamp;
42
43void management_init() {
44  Management::init();
45  ThreadService::init();
46  RuntimeService::init();
47  ClassLoadingService::init();
48}
49
50void 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
89void 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
116void Management::get_optional_support(jmmOptionalSupport* support) {
117  memcpy(support, &_optional_support, sizeof(jmmOptionalSupport));
118}
119
120klassOop 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
129void 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
139jlong Management::timestamp() {
140  TimeStamp t;
141  t.update();
142  return t.ticks() - _stamp.ticks();
143}
144
145void 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
158klassOop 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
165klassOop 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
172klassOop 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
179klassOop 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
186klassOop 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
193klassOop 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
200klassOop 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
207static 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
250instanceOop 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
276instanceOop 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
312static 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
329static 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
352static 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
364static 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
385static 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
398static 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.
412JVM_LEAF(jint, jmm_GetVersion(JNIEnv *env))
413  return JMM_VERSION;
414JVM_END
415
416// Gets the list of VM monitoring and management optional supports
417// Returns 0 if succeeded; otherwise returns non-zero.
418JVM_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;
424JVM_END
425
426// Returns a java.lang.String object containing the input arguments to the VM.
427JVM_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());
479JVM_END
480
481// Returns an array of java.lang.String object containing the input arguments to the VM.
482JVM_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());
508JVM_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.
514JVM_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());
553JVM_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.
559JVM_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());
598JVM_END
599
600
601// Returns a java/lang/management/MemoryUsage object containing the memory usage
602// of a given memory pool.
603JVM_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  }
614JVM_END
615
616// Returns a java/lang/management/MemoryUsage object containing the memory usage
617// of a given memory pool.
618JVM_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  }
629JVM_END
630
631// Returns a java/lang/management/MemoryUsage object containing the memory usage
632// of a given memory pool after most recent GC.
633JVM_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  }
644JVM_END
645
646// Sets the memory pool sensor for a threshold type
647JVM_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
679JVM_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//
690JVM_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 ((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  }
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;
748JVM_END
749
750// Returns a java/lang/management/MemoryUsage object representing
751// the memory usage for the heap or non-heap memory.
752JVM_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, 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");
793
794  MemoryUsage usage((heap ? InitialHeapSize : total_init),
795                    total_used,
796                    total_committed,
797                    (heap ? Universe::heap()->max_capacity() : total_max));
798
799  Handle obj = MemoryService::create_MemoryUsage_obj(usage, CHECK_NULL);
800  return JNIHandles::make_local(env, obj());
801JVM_END
802
803// Returns the boolean value of a given attribute.
804JVM_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  }
818JVM_END
819
820// Sets the given boolean attribute and returns the previous value.
821JVM_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  }
835JVM_END
836
837
838static jlong get_gc_attribute(GCMemoryManager* mgr, jmmLongAttribute att) {
839  switch (att) {
840  case JMM_GC_TIME_MS:
841    return mgr->gc_time_ms();
842
843  case JMM_GC_COUNT:
844    return mgr->gc_count();
845
846  case JMM_GC_EXT_ATTRIBUTE_INFO_SIZE:
847    // current implementation only has 1 ext attribute
848    return 1;
849
850  default:
851    assert(0, "Unrecognized GC attribute");
852    return -1;
853  }
854}
855
856class 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};
864
865void 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  }
870
871  _count++;
872}
873
874static jint get_vm_thread_count() {
875  VmThreadCountClosure vmtcc;
876  {
877    MutexLockerEx ml(Threads_lock);
878    Threads::threads_do(&vmtcc);
879  }
880
881  return vmtcc.count();
882}
883
884static 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}
897
898static jlong get_long_attribute(jmmLongAttribute att) {
899  switch (att) {
900  case JMM_CLASS_LOADED_COUNT:
901    return ClassLoadingService::loaded_class_count();
902
903  case JMM_CLASS_UNLOADED_COUNT:
904    return ClassLoadingService::unloaded_class_count();
905
906  case JMM_THREAD_TOTAL_COUNT:
907    return ThreadService::get_total_thread_count();
908
909  case JMM_THREAD_LIVE_COUNT:
910    return ThreadService::get_live_thread_count();
911
912  case JMM_THREAD_PEAK_COUNT:
913    return ThreadService::get_peak_thread_count();
914
915  case JMM_THREAD_DAEMON_COUNT:
916    return ThreadService::get_daemon_thread_count();
917
918  case JMM_JVM_INIT_DONE_TIME_MS:
919    return Management::vm_init_done_time();
920
921  case JMM_COMPILE_TOTAL_TIME_MS:
922    return Management::ticks_to_ms(CompileBroker::total_compilation_ticks());
923
924  case JMM_OS_PROCESS_ID:
925    return os::current_process_id();
926
927  // Hotspot-specific counters
928  case JMM_CLASS_LOADED_BYTES:
929    return ClassLoadingService::loaded_class_bytes();
930
931  case JMM_CLASS_UNLOADED_BYTES:
932    return ClassLoadingService::unloaded_class_bytes();
933
934  case JMM_SHARED_CLASS_LOADED_COUNT:
935    return ClassLoadingService::loaded_shared_class_count();
936
937  case JMM_SHARED_CLASS_UNLOADED_COUNT:
938    return ClassLoadingService::unloaded_shared_class_count();
939
940
941  case JMM_SHARED_CLASS_LOADED_BYTES:
942    return ClassLoadingService::loaded_shared_class_bytes();
943
944  case JMM_SHARED_CLASS_UNLOADED_BYTES:
945    return ClassLoadingService::unloaded_shared_class_bytes();
946
947  case JMM_TOTAL_CLASSLOAD_TIME_MS:
948    return ClassLoader::classloader_time_ms();
949
950  case JMM_VM_GLOBAL_COUNT:
951    return get_num_flags();
952
953  case JMM_SAFEPOINT_COUNT:
954    return RuntimeService::safepoint_count();
955
956  case JMM_TOTAL_SAFEPOINTSYNC_TIME_MS:
957    return RuntimeService::safepoint_sync_time_ms();
958
959  case JMM_TOTAL_STOPPED_TIME_MS:
960    return RuntimeService::safepoint_time_ms();
961
962  case JMM_TOTAL_APP_TIME_MS:
963    return RuntimeService::application_time_ms();
964
965  case JMM_VM_THREAD_COUNT:
966    return get_vm_thread_count();
967
968  case JMM_CLASS_INIT_TOTAL_COUNT:
969    return ClassLoader::class_init_count();
970
971  case JMM_CLASS_INIT_TOTAL_TIME_MS:
972    return ClassLoader::class_init_time_ms();
973
974  case JMM_CLASS_VERIFY_TOTAL_TIME_MS:
975    return ClassLoader::class_verify_time_ms();
976
977  case JMM_METHOD_DATA_SIZE_BYTES:
978    return ClassLoadingService::class_method_data_size();
979
980  case JMM_OS_MEM_TOTAL_PHYSICAL_BYTES:
981    return os::physical_memory();
982
983  default:
984    return -1;
985  }
986}
987
988
989// Returns the long value of a given attribute.
990JVM_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;
1000JVM_END
1001
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.
1005JVM_ENTRY(jint, jmm_GetLongAttributes(JNIEnv *env,
1006                                      jobject obj,
1007                                      jmmLongAttribute* atts,
1008                                      jint count,
1009                                      jlong* result))
1010
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;
1029JVM_END
1030
1031// Helper function to do thread dump for a specific list of threads
1032static 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) {
1039
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  }
1053
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}
1063
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//
1076JVM_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  }
1081
1082  if (maxDepth < -1) {
1083    THROW_MSG_(vmSymbols::java_lang_IllegalArgumentException(),
1084               "Invalid maxDepth", -1);
1085  }
1086
1087  ResourceMark rm(THREAD);
1088  typeArrayOop ta = typeArrayOop(JNIHandles::resolve_non_null(ids));
1089  typeArrayHandle ids_ah(THREAD, ta);
1090
1091  oop infoArray_obj = JNIHandles::resolve_non_null(infoArray);
1092  objArrayOop oa = objArrayOop(infoArray_obj);
1093  objArrayHandle infoArray_h(THREAD, oa);
1094
1095  // validate the thread id array
1096  validate_thread_id_array(ids_ah, CHECK_0);
1097
1098  // validate the ThreadInfo[] parameters
1099  validate_thread_info_array(infoArray_h, CHECK_0);
1100
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  }
1107
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  }
1112
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);
1118
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
1139
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  }
1148
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
1155
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    }
1161
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;
1167JVM_END
1168
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//
1180JVM_ENTRY(jobjectArray, jmm_DumpThreads(JNIEnv *env, jlongArray thread_ids, jboolean locked_monitors, jboolean locked_synchronizers))
1181  ResourceMark rm(THREAD);
1182
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  }
1187
1188  typeArrayOop ta = typeArrayOop(JNIHandles::resolve(thread_ids));
1189  int num_threads = (ta != NULL ? ta->length() : 0);
1190  typeArrayHandle ids_ah(THREAD, ta);
1191
1192  ThreadDumpResult dump_result(num_threads);  // can safepoint
1193
1194  if (ids_ah() != NULL) {
1195
1196    // validate the thread id array
1197    validate_thread_id_array(ids_ah, CHECK_NULL);
1198
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  }
1215
1216  int num_snapshots = dump_result.num_snapshots();
1217
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);
1223
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    }
1231
1232
1233
1234    ThreadStackTrace* stacktrace = ts->get_stack_trace();
1235    assert(stacktrace != NULL, "Must have a stack trace dumped");
1236
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();
1241
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    }
1247
1248    objArrayHandle monitors_array;
1249    typeArrayHandle depths_array;
1250    objArrayHandle synchronizers_array;
1251
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;
1258
1259      typeArrayOop tarray = oopFactory::new_typeArray(T_INT, num_locked_monitors, CHECK_NULL);
1260      typeArrayHandle dh(THREAD, tarray);
1261      depths_array = dh;
1262
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      }
1277
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    }
1289
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);
1296
1297      objArrayOop array = oopFactory::new_system_objArray(num_locked_synchronizers, CHECK_NULL);
1298      objArrayHandle sh(THREAD, array);
1299      synchronizers_array = sh;
1300
1301      for (int k = 0; k < num_locked_synchronizers; k++) {
1302        synchronizers_array->obj_at_put(k, locks->at(k));
1303      }
1304    }
1305
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  }
1314
1315  return (jobjectArray) JNIHandles::make_local(env, result_h());
1316JVM_END
1317
1318// Returns an array of Class objects.
1319JVM_ENTRY(jobjectArray, jmm_GetLoadedClasses(JNIEnv *env))
1320  ResourceMark rm(THREAD);
1321
1322  LoadedClassesEnumerator lce(THREAD);  // Pass current Thread as parameter
1323
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);
1327
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  }
1333
1334  return (jobjectArray) JNIHandles::make_local(env, classes_ah());
1335JVM_END
1336
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//
1346JVM_ENTRY(jboolean, jmm_ResetStatistic(JNIEnv *env, jvalue obj, jmmStatisticType type))
1347  ResourceMark rm(THREAD);
1348
1349  switch (type) {
1350    case JMM_STAT_PEAK_THREAD_COUNT:
1351      ThreadService::reset_peak_thread_count();
1352      return true;
1353
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      }
1360
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        }
1378
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      }
1393
1394      oop pool_obj = JNIHandles::resolve(o);
1395      assert(pool_obj->is_instance(), "Should be an instanceOop");
1396      instanceHandle ph(THREAD, (instanceOop) pool_obj);
1397
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      }
1410
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;
1422JVM_END
1423
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.
1427JVM_ENTRY(jlong, jmm_GetThreadCpuTime(JNIEnv *env, jlong thread_id))
1428  if (!os::is_thread_cpu_time_supported()) {
1429    return -1;
1430  }
1431
1432  if (thread_id < 0) {
1433    THROW_MSG_(vmSymbols::java_lang_IllegalArgumentException(),
1434               "Invalid thread ID", -1);
1435  }
1436
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;
1449JVM_END
1450
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.
1456JVM_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  }
1460
1461  if (thread_id < 0) {
1462    THROW_MSG_(vmSymbols::java_lang_IllegalArgumentException(),
1463               "Invalid thread ID", -1);
1464  }
1465
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;
1478JVM_END
1479
1480// Returns a String array of all VM global flag names
1481JVM_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  }
1498
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  }
1507
1508  return (jobjectArray)JNIHandles::make_local(env, flags_ah());
1509JVM_END
1510
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.
1514bool 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());
1522
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  }
1543
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  }
1568
1569  return true;
1570}
1571
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.
1578JVM_ENTRY(jint, jmm_GetVMGlobals(JNIEnv *env,
1579                                 jobjectArray names,
1580                                 jmmVMGlobal *globals,
1581                                 jint count))
1582
1583
1584  if (globals == NULL) {
1585    THROW_(vmSymbols::java_lang_NullPointerException(), 0);
1586  }
1587
1588  ResourceMark rm(THREAD);
1589
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    }
1600
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      }
1608
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
1622
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  }
1637JVM_END
1638
1639JVM_ENTRY(void, jmm_SetVMGlobal(JNIEnv *env, jstring flag_name, jvalue new_value))
1640  ResourceMark rm(THREAD);
1641
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  }
1657
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");
1680JVM_END
1681
1682class ThreadTimesClosure: public ThreadClosure {
1683 private:
1684  objArrayOop _names;
1685  typeArrayOop _times;
1686  int _names_len;
1687  int _times_len;
1688  int _count;
1689
1690 public:
1691  ThreadTimesClosure(objArrayOop names, typeArrayOop times);
1692  virtual void do_thread(Thread* thread);
1693  int count() { return _count; }
1694};
1695
1696ThreadTimesClosure::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}
1706
1707void ThreadTimesClosure::do_thread(Thread* thread) {
1708  Handle s;
1709  assert(thread != NULL, "thread was NULL");
1710
1711  // exclude externally visible JavaThreads
1712  if (thread->is_Java_thread() && !thread->is_hidden_from_external_view()) {
1713    return;
1714  }
1715
1716  if (_count >= _names_len || _count >= _times_len) {
1717    // skip if the result array is not big enough
1718    return;
1719  }
1720
1721  EXCEPTION_MARK;
1722
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());
1726
1727  _times->long_at_put(_count, os::is_thread_cpu_time_supported() ?
1728                        os::thread_cpu_time(thread) : -1);
1729  _count++;
1730}
1731
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.
1739JVM_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);
1747
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  }
1754
1755  typeArrayOop ta = typeArrayOop(JNIHandles::resolve_non_null(times));
1756  typeArrayHandle times_ah(THREAD, ta);
1757
1758  ThreadTimesClosure ttc(names_ah(), times_ah());
1759  {
1760    MutexLockerEx ml(Threads_lock);
1761    Threads::threads_do(&ttc);
1762  }
1763
1764  return ttc.count();
1765JVM_END
1766
1767static Handle find_deadlocks(bool object_monitors_only, TRAPS) {
1768  ResourceMark rm(THREAD);
1769
1770  VM_FindDeadlocks op(!object_monitors_only /* also check concurrent locks? */);
1771  VMThread::execute(&op);
1772
1773  DeadlockCycle* deadlocks = op.result();
1774  if (deadlocks == NULL) {
1775    // no deadlock found and return
1776    return Handle();
1777  }
1778
1779  int num_threads = 0;
1780  DeadlockCycle* cycle;
1781  for (cycle = deadlocks; cycle != NULL; cycle = cycle->next()) {
1782    num_threads += cycle->num_threads();
1783  }
1784
1785  objArrayOop r = oopFactory::new_objArray(SystemDictionary::Thread_klass(), num_threads, CHECK_NH);
1786  objArrayHandle threads_ah(THREAD, r);
1787
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}
1799
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//
1808JVM_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());
1811JVM_END
1812
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.
1816JVM_ENTRY(jobjectArray, jmm_FindMonitorDeadlockedThreads(JNIEnv *env))
1817  Handle result = find_deadlocks(true, CHECK_0);
1818  return (jobjectArray) JNIHandles::make_local(env, result());
1819JVM_END
1820
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//
1832JVM_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  }
1837
1838  if (info == NULL) {
1839   THROW_(vmSymbols::java_lang_NullPointerException(), 0);
1840  }
1841
1842  info[0].name = "GcThreadCount";
1843  info[0].type = 'I';
1844  info[0].description = "Number of GC threads";
1845  return 1;
1846JVM_END
1847
1848// verify the given array is an array of java/lang/management/MemoryUsage objects
1849// of a given length and return the objArrayOop
1850static objArrayOop get_memory_usage_objArray(jobjectArray array, int length, TRAPS) {
1851  if (array == NULL) {
1852    THROW_(vmSymbols::java_lang_NullPointerException(), 0);
1853  }
1854
1855  objArrayOop oa = objArrayOop(JNIHandles::resolve_non_null(array));
1856  objArrayHandle array_h(THREAD, oa);
1857
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  }
1863
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  }
1871
1872  return array_h();
1873}
1874
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//
1895JVM_ENTRY(void, jmm_GetLastGCStat(JNIEnv *env, jobject obj, jmmGCStat *gc_stat))
1896  ResourceMark rm(THREAD);
1897
1898  if (gc_stat->gc_ext_attribute_values_size > 0 && gc_stat->gc_ext_attribute_values == NULL) {
1899    THROW(vmSymbols::java_lang_NullPointerException());
1900  }
1901
1902  // Get the GCMemoryManager
1903  GCMemoryManager* mgr = get_gc_memory_manager_from_jobject(obj, CHECK);
1904
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  }
1913
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());
1917
1918  // Current implementation does not have GC extension attributes
1919  gc_stat->num_gc_ext_attributes = 0;
1920
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);
1927
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);
1932
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;
1936
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  }
1949
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  }
1955JVM_END
1956
1957// Dump heap - Returns 0 if succeeds.
1958JVM_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
1980JVM_END
1981
1982jlong 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}
1987
1988const 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};
2025
2026void* Management::get_jmm_interface(int version) {
2027  if (version == JMM_VERSION_1_0) {
2028    return (void*) &jmm_interface;
2029  }
2030  return NULL;
2031}
2032