management.cpp revision 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
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 (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;
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, 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());
800JVM_END
801
802// Returns the boolean value of a given attribute.
803JVM_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  }
817JVM_END
818
819// Sets the given boolean attribute and returns the previous value.
820JVM_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  }
834JVM_END
835
836
837static 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
855class 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
864void 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
873static 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
883static 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
897static 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.
989JVM_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;
999JVM_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.
1004JVM_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;
1028JVM_END
1029
1030// Helper function to do thread dump for a specific list of threads
1031static 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//
1075JVM_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;
1166JVM_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//
1179JVM_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());
1315JVM_END
1316
1317// Returns an array of Class objects.
1318JVM_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());
1334JVM_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//
1345JVM_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;
1421JVM_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.
1426JVM_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;
1448JVM_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.
1455JVM_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;
1477JVM_END
1478
1479// Returns a String array of all VM global flag names
1480JVM_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());
1508JVM_END
1509
1510// utility function used by jmm_GetVMGlobals
1511void 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.
1568JVM_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  }
1627JVM_END
1628
1629JVM_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");
1667JVM_END
1668
1669class 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
1683ThreadTimesClosure::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
1694void 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.
1726JVM_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();
1752JVM_END
1753
1754static 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//
1795JVM_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());
1798JVM_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.
1803JVM_ENTRY(jobjectArray, jmm_FindMonitorDeadlockedThreads(JNIEnv *env))
1804  Handle result = find_deadlocks(true, CHECK_0);
1805  return (jobjectArray) JNIHandles::make_local(env, result());
1806JVM_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//
1819JVM_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;
1833JVM_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
1837static 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//
1882JVM_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  }
1943JVM_END
1944
1945// Dump heap - Returns 0 if succeeds.
1946JVM_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
1968JVM_END
1969
1970jlong 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
1976const 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
2014void* Management::get_jmm_interface(int version) {
2015  if (version == JMM_VERSION_1_0) {
2016    return (void*) &jmm_interface;
2017  }
2018  return NULL;
2019}
2020