1 /* 2 * Copyright (c) 2003, 2015, 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 "precompiled.hpp" 26 #include "classfile/systemDictionary.hpp" 27 #include "compiler/compileBroker.hpp" 28 #include "memory/iterator.hpp" 29 #include "memory/oopFactory.hpp" 30 #include "memory/resourceArea.hpp" 31 #include "oops/klass.hpp" 32 #include "oops/objArrayKlass.hpp" 33 #include "oops/objArrayOop.inline.hpp" 34 #include "oops/oop.inline.hpp" 35 #include "runtime/arguments.hpp" 36 #include "runtime/globals.hpp" 37 #include "runtime/handles.inline.hpp" 38 #include "runtime/interfaceSupport.hpp" 39 #include "runtime/javaCalls.hpp" 40 #include "runtime/jniHandles.hpp" 41 #include "runtime/os.hpp" 42 #include "runtime/serviceThread.hpp" 43 #include "runtime/thread.inline.hpp" 44 #include "services/classLoadingService.hpp" 45 #include "services/diagnosticCommand.hpp" 46 #include "services/diagnosticFramework.hpp" 47 #include "services/writeableFlags.hpp" 48 #include "services/heapDumper.hpp" 49 #include "services/jmm.h" 50 #include "services/lowMemoryDetector.hpp" 51 #include "services/gcNotifier.hpp" 52 #include "services/nmtDCmd.hpp" 53 #include "services/management.hpp" 54 #include "services/memoryManager.hpp" 55 #include "services/memoryPool.hpp" 56 #include "services/memoryService.hpp" 57 #include "services/runtimeService.hpp" 58 #include "services/threadService.hpp" 59 #include "utilities/macros.hpp" 60 61 PRAGMA_FORMAT_MUTE_WARNINGS_FOR_GCC 62 63 PerfVariable* Management::_begin_vm_creation_time = NULL; 64 PerfVariable* Management::_end_vm_creation_time = NULL; 65 PerfVariable* Management::_vm_init_done_time = NULL; 66 67 Klass* Management::_diagnosticCommandImpl_klass = NULL; 68 Klass* Management::_garbageCollectorExtImpl_klass = NULL; 69 Klass* Management::_garbageCollectorMXBean_klass = NULL; 70 Klass* Management::_gcInfo_klass = NULL; 71 Klass* Management::_managementFactoryHelper_klass = NULL; 72 Klass* Management::_memoryManagerMXBean_klass = NULL; 73 Klass* Management::_memoryPoolMXBean_klass = NULL; 74 Klass* Management::_memoryUsage_klass = NULL; 75 Klass* Management::_sensor_klass = NULL; 76 Klass* Management::_threadInfo_klass = NULL; 77 78 jmmOptionalSupport Management::_optional_support = {0}; 79 TimeStamp Management::_stamp; 80 81 void management_init() { 82 #if INCLUDE_MANAGEMENT 83 Management::init(); 84 ThreadService::init(); 85 RuntimeService::init(); 86 ClassLoadingService::init(); 87 #else 88 ThreadService::init(); 89 // Make sure the VM version is initialized 90 // This is normally called by RuntimeService::init(). 91 // Since that is conditionalized out, we need to call it here. 92 Abstract_VM_Version::initialize(); 93 #endif // INCLUDE_MANAGEMENT 94 } 95 96 #if INCLUDE_MANAGEMENT 97 98 void Management::init() { 99 EXCEPTION_MARK; 100 101 // These counters are for java.lang.management API support. 102 // They are created even if -XX:-UsePerfData is set and in 103 // that case, they will be allocated on C heap. 104 105 _begin_vm_creation_time = 106 PerfDataManager::create_variable(SUN_RT, "createVmBeginTime", 107 PerfData::U_None, CHECK); 108 109 _end_vm_creation_time = 110 PerfDataManager::create_variable(SUN_RT, "createVmEndTime", 111 PerfData::U_None, CHECK); 112 113 _vm_init_done_time = 114 PerfDataManager::create_variable(SUN_RT, "vmInitDoneTime", 115 PerfData::U_None, CHECK); 116 117 // Initialize optional support 118 _optional_support.isLowMemoryDetectionSupported = 1; 119 _optional_support.isCompilationTimeMonitoringSupported = 1; 120 _optional_support.isThreadContentionMonitoringSupported = 1; 121 122 if (os::is_thread_cpu_time_supported()) { 123 _optional_support.isCurrentThreadCpuTimeSupported = 1; 124 _optional_support.isOtherThreadCpuTimeSupported = 1; 125 } else { 126 _optional_support.isCurrentThreadCpuTimeSupported = 0; 127 _optional_support.isOtherThreadCpuTimeSupported = 0; 128 } 129 130 _optional_support.isBootClassPathSupported = 1; 131 _optional_support.isObjectMonitorUsageSupported = 1; 132 #if INCLUDE_SERVICES 133 // This depends on the heap inspector 134 _optional_support.isSynchronizerUsageSupported = 1; 135 #endif // INCLUDE_SERVICES 136 _optional_support.isThreadAllocatedMemorySupported = 1; 137 _optional_support.isRemoteDiagnosticCommandsSupported = 1; 138 139 // Registration of the diagnostic commands 140 DCmdRegistrant::register_dcmds(); 141 DCmdRegistrant::register_dcmds_ext(); 142 uint32_t full_export = DCmd_Source_Internal | DCmd_Source_AttachAPI 143 | DCmd_Source_MBean; 144 DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl<NMTDCmd>(full_export, true, false)); 145 } 146 147 void Management::initialize(TRAPS) { 148 // Start the service thread 149 ServiceThread::initialize(); 150 151 if (ManagementServer) { 152 ResourceMark rm(THREAD); 153 HandleMark hm(THREAD); 154 155 // Load and initialize the sun.management.Agent class 156 // invoke startAgent method to start the management server 157 Handle loader = Handle(THREAD, SystemDictionary::java_system_loader()); 158 Klass* k = SystemDictionary::resolve_or_null(vmSymbols::sun_management_Agent(), 159 loader, 160 Handle(), 161 THREAD); 162 if (k == NULL) { 163 vm_exit_during_initialization("Management agent initialization failure: " 164 "class sun.management.Agent not found."); 165 } 166 instanceKlassHandle ik (THREAD, k); 167 168 JavaValue result(T_VOID); 169 JavaCalls::call_static(&result, 170 ik, 171 vmSymbols::startAgent_name(), 172 vmSymbols::void_method_signature(), 173 CHECK); 174 } 175 } 176 177 void Management::get_optional_support(jmmOptionalSupport* support) { 178 memcpy(support, &_optional_support, sizeof(jmmOptionalSupport)); 179 } 180 181 Klass* Management::load_and_initialize_klass(Symbol* sh, TRAPS) { 182 Klass* k = SystemDictionary::resolve_or_fail(sh, true, CHECK_NULL); 183 instanceKlassHandle ik (THREAD, k); 184 if (ik->should_be_initialized()) { 185 ik->initialize(CHECK_NULL); 186 } 187 // If these classes change to not be owned by the boot loader, they need 188 // to be walked to keep their class loader alive in oops_do. 189 assert(ik->class_loader() == NULL, "need to follow in oops_do"); 190 return ik(); 191 } 192 193 void Management::record_vm_startup_time(jlong begin, jlong duration) { 194 // if the performance counter is not initialized, 195 // then vm initialization failed; simply return. 196 if (_begin_vm_creation_time == NULL) return; 197 198 _begin_vm_creation_time->set_value(begin); 199 _end_vm_creation_time->set_value(begin + duration); 200 PerfMemory::set_accessible(true); 201 } 202 203 jlong Management::timestamp() { 204 TimeStamp t; 205 t.update(); 206 return t.ticks() - _stamp.ticks(); 207 } 208 209 void Management::oops_do(OopClosure* f) { 210 MemoryService::oops_do(f); 211 ThreadService::oops_do(f); 212 } 213 214 Klass* Management::java_lang_management_ThreadInfo_klass(TRAPS) { 215 if (_threadInfo_klass == NULL) { 216 _threadInfo_klass = load_and_initialize_klass(vmSymbols::java_lang_management_ThreadInfo(), CHECK_NULL); 217 } 218 return _threadInfo_klass; 219 } 220 221 Klass* Management::java_lang_management_MemoryUsage_klass(TRAPS) { 222 if (_memoryUsage_klass == NULL) { 223 _memoryUsage_klass = load_and_initialize_klass(vmSymbols::java_lang_management_MemoryUsage(), CHECK_NULL); 224 } 225 return _memoryUsage_klass; 226 } 227 228 Klass* Management::java_lang_management_MemoryPoolMXBean_klass(TRAPS) { 229 if (_memoryPoolMXBean_klass == NULL) { 230 _memoryPoolMXBean_klass = load_and_initialize_klass(vmSymbols::java_lang_management_MemoryPoolMXBean(), CHECK_NULL); 231 } 232 return _memoryPoolMXBean_klass; 233 } 234 235 Klass* Management::java_lang_management_MemoryManagerMXBean_klass(TRAPS) { 236 if (_memoryManagerMXBean_klass == NULL) { 237 _memoryManagerMXBean_klass = load_and_initialize_klass(vmSymbols::java_lang_management_MemoryManagerMXBean(), CHECK_NULL); 238 } 239 return _memoryManagerMXBean_klass; 240 } 241 242 Klass* Management::java_lang_management_GarbageCollectorMXBean_klass(TRAPS) { 243 if (_garbageCollectorMXBean_klass == NULL) { 244 _garbageCollectorMXBean_klass = load_and_initialize_klass(vmSymbols::java_lang_management_GarbageCollectorMXBean(), CHECK_NULL); 245 } 246 return _garbageCollectorMXBean_klass; 247 } 248 249 Klass* Management::sun_management_Sensor_klass(TRAPS) { 250 if (_sensor_klass == NULL) { 251 _sensor_klass = load_and_initialize_klass(vmSymbols::sun_management_Sensor(), CHECK_NULL); 252 } 253 return _sensor_klass; 254 } 255 256 Klass* Management::sun_management_ManagementFactoryHelper_klass(TRAPS) { 257 if (_managementFactoryHelper_klass == NULL) { 258 _managementFactoryHelper_klass = load_and_initialize_klass(vmSymbols::sun_management_ManagementFactoryHelper(), CHECK_NULL); 259 } 260 return _managementFactoryHelper_klass; 261 } 262 263 Klass* Management::com_sun_management_internal_GarbageCollectorExtImpl_klass(TRAPS) { 264 if (_garbageCollectorExtImpl_klass == NULL) { 265 _garbageCollectorExtImpl_klass = load_and_initialize_klass(vmSymbols::com_sun_management_internal_GarbageCollectorExtImpl(), CHECK_NULL); 266 } 267 return _garbageCollectorExtImpl_klass; 268 } 269 270 Klass* Management::com_sun_management_GcInfo_klass(TRAPS) { 271 if (_gcInfo_klass == NULL) { 272 _gcInfo_klass = load_and_initialize_klass(vmSymbols::com_sun_management_GcInfo(), CHECK_NULL); 273 } 274 return _gcInfo_klass; 275 } 276 277 Klass* Management::com_sun_management_internal_DiagnosticCommandImpl_klass(TRAPS) { 278 if (_diagnosticCommandImpl_klass == NULL) { 279 _diagnosticCommandImpl_klass = load_and_initialize_klass(vmSymbols::com_sun_management_internal_DiagnosticCommandImpl(), CHECK_NULL); 280 } 281 return _diagnosticCommandImpl_klass; 282 } 283 284 static void initialize_ThreadInfo_constructor_arguments(JavaCallArguments* args, ThreadSnapshot* snapshot, TRAPS) { 285 Handle snapshot_thread(THREAD, snapshot->threadObj()); 286 287 jlong contended_time; 288 jlong waited_time; 289 if (ThreadService::is_thread_monitoring_contention()) { 290 contended_time = Management::ticks_to_ms(snapshot->contended_enter_ticks()); 291 waited_time = Management::ticks_to_ms(snapshot->monitor_wait_ticks() + snapshot->sleep_ticks()); 292 } else { 293 // set them to -1 if thread contention monitoring is disabled. 294 contended_time = max_julong; 295 waited_time = max_julong; 296 } 297 298 int thread_status = snapshot->thread_status(); 299 assert((thread_status & JMM_THREAD_STATE_FLAG_MASK) == 0, "Flags already set in thread_status in Thread object"); 300 if (snapshot->is_ext_suspended()) { 301 thread_status |= JMM_THREAD_STATE_FLAG_SUSPENDED; 302 } 303 if (snapshot->is_in_native()) { 304 thread_status |= JMM_THREAD_STATE_FLAG_NATIVE; 305 } 306 307 ThreadStackTrace* st = snapshot->get_stack_trace(); 308 Handle stacktrace_h; 309 if (st != NULL) { 310 stacktrace_h = st->allocate_fill_stack_trace_element_array(CHECK); 311 } else { 312 stacktrace_h = Handle(); 313 } 314 315 args->push_oop(snapshot_thread); 316 args->push_int(thread_status); 317 args->push_oop(Handle(THREAD, snapshot->blocker_object())); 318 args->push_oop(Handle(THREAD, snapshot->blocker_object_owner())); 319 args->push_long(snapshot->contended_enter_count()); 320 args->push_long(contended_time); 321 args->push_long(snapshot->monitor_wait_count() + snapshot->sleep_count()); 322 args->push_long(waited_time); 323 args->push_oop(stacktrace_h); 324 } 325 326 // Helper function to construct a ThreadInfo object 327 instanceOop Management::create_thread_info_instance(ThreadSnapshot* snapshot, TRAPS) { 328 Klass* k = Management::java_lang_management_ThreadInfo_klass(CHECK_NULL); 329 instanceKlassHandle ik (THREAD, k); 330 331 JavaValue result(T_VOID); 332 JavaCallArguments args(14); 333 334 // First allocate a ThreadObj object and 335 // push the receiver as the first argument 336 Handle element = ik->allocate_instance_handle(CHECK_NULL); 337 args.push_oop(element); 338 339 // initialize the arguments for the ThreadInfo constructor 340 initialize_ThreadInfo_constructor_arguments(&args, snapshot, CHECK_NULL); 341 342 // Call ThreadInfo constructor with no locked monitors and synchronizers 343 JavaCalls::call_special(&result, 344 ik, 345 vmSymbols::object_initializer_name(), 346 vmSymbols::java_lang_management_ThreadInfo_constructor_signature(), 347 &args, 348 CHECK_NULL); 349 350 return (instanceOop) element(); 351 } 352 353 instanceOop Management::create_thread_info_instance(ThreadSnapshot* snapshot, 354 objArrayHandle monitors_array, 355 typeArrayHandle depths_array, 356 objArrayHandle synchronizers_array, 357 TRAPS) { 358 Klass* k = Management::java_lang_management_ThreadInfo_klass(CHECK_NULL); 359 instanceKlassHandle ik (THREAD, k); 360 361 JavaValue result(T_VOID); 362 JavaCallArguments args(17); 363 364 // First allocate a ThreadObj object and 365 // push the receiver as the first argument 366 Handle element = ik->allocate_instance_handle(CHECK_NULL); 367 args.push_oop(element); 368 369 // initialize the arguments for the ThreadInfo constructor 370 initialize_ThreadInfo_constructor_arguments(&args, snapshot, CHECK_NULL); 371 372 // push the locked monitors and synchronizers in the arguments 373 args.push_oop(monitors_array); 374 args.push_oop(depths_array); 375 args.push_oop(synchronizers_array); 376 377 // Call ThreadInfo constructor with locked monitors and synchronizers 378 JavaCalls::call_special(&result, 379 ik, 380 vmSymbols::object_initializer_name(), 381 vmSymbols::java_lang_management_ThreadInfo_with_locks_constructor_signature(), 382 &args, 383 CHECK_NULL); 384 385 return (instanceOop) element(); 386 } 387 388 389 static GCMemoryManager* get_gc_memory_manager_from_jobject(jobject mgr, TRAPS) { 390 if (mgr == NULL) { 391 THROW_(vmSymbols::java_lang_NullPointerException(), NULL); 392 } 393 oop mgr_obj = JNIHandles::resolve(mgr); 394 instanceHandle h(THREAD, (instanceOop) mgr_obj); 395 396 Klass* k = Management::java_lang_management_GarbageCollectorMXBean_klass(CHECK_NULL); 397 if (!h->is_a(k)) { 398 THROW_MSG_(vmSymbols::java_lang_IllegalArgumentException(), 399 "the object is not an instance of java.lang.management.GarbageCollectorMXBean class", 400 NULL); 401 } 402 403 MemoryManager* gc = MemoryService::get_memory_manager(h); 404 if (gc == NULL || !gc->is_gc_memory_manager()) { 405 THROW_MSG_(vmSymbols::java_lang_IllegalArgumentException(), 406 "Invalid GC memory manager", 407 NULL); 408 } 409 return (GCMemoryManager*) gc; 410 } 411 412 static MemoryPool* get_memory_pool_from_jobject(jobject obj, TRAPS) { 413 if (obj == NULL) { 414 THROW_(vmSymbols::java_lang_NullPointerException(), NULL); 415 } 416 417 oop pool_obj = JNIHandles::resolve(obj); 418 assert(pool_obj->is_instance(), "Should be an instanceOop"); 419 instanceHandle ph(THREAD, (instanceOop) pool_obj); 420 421 return MemoryService::get_memory_pool(ph); 422 } 423 424 #endif // INCLUDE_MANAGEMENT 425 426 static void validate_thread_id_array(typeArrayHandle ids_ah, TRAPS) { 427 int num_threads = ids_ah->length(); 428 429 // Validate input thread IDs 430 int i = 0; 431 for (i = 0; i < num_threads; i++) { 432 jlong tid = ids_ah->long_at(i); 433 if (tid <= 0) { 434 // throw exception if invalid thread id. 435 THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(), 436 "Invalid thread ID entry"); 437 } 438 } 439 } 440 441 #if INCLUDE_MANAGEMENT 442 443 static void validate_thread_info_array(objArrayHandle infoArray_h, TRAPS) { 444 // check if the element of infoArray is of type ThreadInfo class 445 Klass* threadinfo_klass = Management::java_lang_management_ThreadInfo_klass(CHECK); 446 Klass* element_klass = ObjArrayKlass::cast(infoArray_h->klass())->element_klass(); 447 if (element_klass != threadinfo_klass) { 448 THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(), 449 "infoArray element type is not ThreadInfo class"); 450 } 451 } 452 453 454 static MemoryManager* get_memory_manager_from_jobject(jobject obj, TRAPS) { 455 if (obj == NULL) { 456 THROW_(vmSymbols::java_lang_NullPointerException(), NULL); 457 } 458 459 oop mgr_obj = JNIHandles::resolve(obj); 460 assert(mgr_obj->is_instance(), "Should be an instanceOop"); 461 instanceHandle mh(THREAD, (instanceOop) mgr_obj); 462 463 return MemoryService::get_memory_manager(mh); 464 } 465 466 // Returns a version string and sets major and minor version if 467 // the input parameters are non-null. 468 JVM_LEAF(jint, jmm_GetVersion(JNIEnv *env)) 469 return JMM_VERSION; 470 JVM_END 471 472 // Gets the list of VM monitoring and management optional supports 473 // Returns 0 if succeeded; otherwise returns non-zero. 474 JVM_LEAF(jint, jmm_GetOptionalSupport(JNIEnv *env, jmmOptionalSupport* support)) 475 if (support == NULL) { 476 return -1; 477 } 478 Management::get_optional_support(support); 479 return 0; 480 JVM_END 481 482 // Returns a java.lang.String object containing the input arguments to the VM. 483 JVM_ENTRY(jobject, jmm_GetInputArguments(JNIEnv *env)) 484 ResourceMark rm(THREAD); 485 486 if (Arguments::num_jvm_args() == 0 && Arguments::num_jvm_flags() == 0) { 487 return NULL; 488 } 489 490 char** vm_flags = Arguments::jvm_flags_array(); 491 char** vm_args = Arguments::jvm_args_array(); 492 int num_flags = Arguments::num_jvm_flags(); 493 int num_args = Arguments::num_jvm_args(); 494 495 size_t length = 1; // null terminator 496 int i; 497 for (i = 0; i < num_flags; i++) { 498 length += strlen(vm_flags[i]); 499 } 500 for (i = 0; i < num_args; i++) { 501 length += strlen(vm_args[i]); 502 } 503 // add a space between each argument 504 length += num_flags + num_args - 1; 505 506 // Return the list of input arguments passed to the VM 507 // and preserve the order that the VM processes. 508 char* args = NEW_RESOURCE_ARRAY(char, length); 509 args[0] = '\0'; 510 // concatenate all jvm_flags 511 if (num_flags > 0) { 512 strcat(args, vm_flags[0]); 513 for (i = 1; i < num_flags; i++) { 514 strcat(args, " "); 515 strcat(args, vm_flags[i]); 516 } 517 } 518 519 if (num_args > 0 && num_flags > 0) { 520 // append a space if args already contains one or more jvm_flags 521 strcat(args, " "); 522 } 523 524 // concatenate all jvm_args 525 if (num_args > 0) { 526 strcat(args, vm_args[0]); 527 for (i = 1; i < num_args; i++) { 528 strcat(args, " "); 529 strcat(args, vm_args[i]); 530 } 531 } 532 533 Handle hargs = java_lang_String::create_from_platform_dependent_str(args, CHECK_NULL); 534 return JNIHandles::make_local(env, hargs()); 535 JVM_END 536 537 // Returns an array of java.lang.String object containing the input arguments to the VM. 538 JVM_ENTRY(jobjectArray, jmm_GetInputArgumentArray(JNIEnv *env)) 539 ResourceMark rm(THREAD); 540 541 if (Arguments::num_jvm_args() == 0 && Arguments::num_jvm_flags() == 0) { 542 return NULL; 543 } 544 545 char** vm_flags = Arguments::jvm_flags_array(); 546 char** vm_args = Arguments::jvm_args_array(); 547 int num_flags = Arguments::num_jvm_flags(); 548 int num_args = Arguments::num_jvm_args(); 549 550 instanceKlassHandle ik (THREAD, SystemDictionary::String_klass()); 551 objArrayOop r = oopFactory::new_objArray(ik(), num_args + num_flags, CHECK_NULL); 552 objArrayHandle result_h(THREAD, r); 553 554 int index = 0; 555 for (int j = 0; j < num_flags; j++, index++) { 556 Handle h = java_lang_String::create_from_platform_dependent_str(vm_flags[j], CHECK_NULL); 557 result_h->obj_at_put(index, h()); 558 } 559 for (int i = 0; i < num_args; i++, index++) { 560 Handle h = java_lang_String::create_from_platform_dependent_str(vm_args[i], CHECK_NULL); 561 result_h->obj_at_put(index, h()); 562 } 563 return (jobjectArray) JNIHandles::make_local(env, result_h()); 564 JVM_END 565 566 // Returns an array of java/lang/management/MemoryPoolMXBean object 567 // one for each memory pool if obj == null; otherwise returns 568 // an array of memory pools for a given memory manager if 569 // it is a valid memory manager. 570 JVM_ENTRY(jobjectArray, jmm_GetMemoryPools(JNIEnv* env, jobject obj)) 571 ResourceMark rm(THREAD); 572 573 int num_memory_pools; 574 MemoryManager* mgr = NULL; 575 if (obj == NULL) { 576 num_memory_pools = MemoryService::num_memory_pools(); 577 } else { 578 mgr = get_memory_manager_from_jobject(obj, CHECK_NULL); 579 if (mgr == NULL) { 580 return NULL; 581 } 582 num_memory_pools = mgr->num_memory_pools(); 583 } 584 585 // Allocate the resulting MemoryPoolMXBean[] object 586 Klass* k = Management::java_lang_management_MemoryPoolMXBean_klass(CHECK_NULL); 587 instanceKlassHandle ik (THREAD, k); 588 objArrayOop r = oopFactory::new_objArray(ik(), num_memory_pools, CHECK_NULL); 589 objArrayHandle poolArray(THREAD, r); 590 591 if (mgr == NULL) { 592 // Get all memory pools 593 for (int i = 0; i < num_memory_pools; i++) { 594 MemoryPool* pool = MemoryService::get_memory_pool(i); 595 instanceOop p = pool->get_memory_pool_instance(CHECK_NULL); 596 instanceHandle ph(THREAD, p); 597 poolArray->obj_at_put(i, ph()); 598 } 599 } else { 600 // Get memory pools managed by a given memory manager 601 for (int i = 0; i < num_memory_pools; i++) { 602 MemoryPool* pool = mgr->get_memory_pool(i); 603 instanceOop p = pool->get_memory_pool_instance(CHECK_NULL); 604 instanceHandle ph(THREAD, p); 605 poolArray->obj_at_put(i, ph()); 606 } 607 } 608 return (jobjectArray) JNIHandles::make_local(env, poolArray()); 609 JVM_END 610 611 // Returns an array of java/lang/management/MemoryManagerMXBean object 612 // one for each memory manager if obj == null; otherwise returns 613 // an array of memory managers for a given memory pool if 614 // it is a valid memory pool. 615 JVM_ENTRY(jobjectArray, jmm_GetMemoryManagers(JNIEnv* env, jobject obj)) 616 ResourceMark rm(THREAD); 617 618 int num_mgrs; 619 MemoryPool* pool = NULL; 620 if (obj == NULL) { 621 num_mgrs = MemoryService::num_memory_managers(); 622 } else { 623 pool = get_memory_pool_from_jobject(obj, CHECK_NULL); 624 if (pool == NULL) { 625 return NULL; 626 } 627 num_mgrs = pool->num_memory_managers(); 628 } 629 630 // Allocate the resulting MemoryManagerMXBean[] object 631 Klass* k = Management::java_lang_management_MemoryManagerMXBean_klass(CHECK_NULL); 632 instanceKlassHandle ik (THREAD, k); 633 objArrayOop r = oopFactory::new_objArray(ik(), num_mgrs, CHECK_NULL); 634 objArrayHandle mgrArray(THREAD, r); 635 636 if (pool == NULL) { 637 // Get all memory managers 638 for (int i = 0; i < num_mgrs; i++) { 639 MemoryManager* mgr = MemoryService::get_memory_manager(i); 640 instanceOop p = mgr->get_memory_manager_instance(CHECK_NULL); 641 instanceHandle ph(THREAD, p); 642 mgrArray->obj_at_put(i, ph()); 643 } 644 } else { 645 // Get memory managers for a given memory pool 646 for (int i = 0; i < num_mgrs; i++) { 647 MemoryManager* mgr = pool->get_memory_manager(i); 648 instanceOop p = mgr->get_memory_manager_instance(CHECK_NULL); 649 instanceHandle ph(THREAD, p); 650 mgrArray->obj_at_put(i, ph()); 651 } 652 } 653 return (jobjectArray) JNIHandles::make_local(env, mgrArray()); 654 JVM_END 655 656 657 // Returns a java/lang/management/MemoryUsage object containing the memory usage 658 // of a given memory pool. 659 JVM_ENTRY(jobject, jmm_GetMemoryPoolUsage(JNIEnv* env, jobject obj)) 660 ResourceMark rm(THREAD); 661 662 MemoryPool* pool = get_memory_pool_from_jobject(obj, CHECK_NULL); 663 if (pool != NULL) { 664 MemoryUsage usage = pool->get_memory_usage(); 665 Handle h = MemoryService::create_MemoryUsage_obj(usage, CHECK_NULL); 666 return JNIHandles::make_local(env, h()); 667 } else { 668 return NULL; 669 } 670 JVM_END 671 672 // Returns a java/lang/management/MemoryUsage object containing the memory usage 673 // of a given memory pool. 674 JVM_ENTRY(jobject, jmm_GetPeakMemoryPoolUsage(JNIEnv* env, jobject obj)) 675 ResourceMark rm(THREAD); 676 677 MemoryPool* pool = get_memory_pool_from_jobject(obj, CHECK_NULL); 678 if (pool != NULL) { 679 MemoryUsage usage = pool->get_peak_memory_usage(); 680 Handle h = MemoryService::create_MemoryUsage_obj(usage, CHECK_NULL); 681 return JNIHandles::make_local(env, h()); 682 } else { 683 return NULL; 684 } 685 JVM_END 686 687 // Returns a java/lang/management/MemoryUsage object containing the memory usage 688 // of a given memory pool after most recent GC. 689 JVM_ENTRY(jobject, jmm_GetPoolCollectionUsage(JNIEnv* env, jobject obj)) 690 ResourceMark rm(THREAD); 691 692 MemoryPool* pool = get_memory_pool_from_jobject(obj, CHECK_NULL); 693 if (pool != NULL && pool->is_collected_pool()) { 694 MemoryUsage usage = pool->get_last_collection_usage(); 695 Handle h = MemoryService::create_MemoryUsage_obj(usage, CHECK_NULL); 696 return JNIHandles::make_local(env, h()); 697 } else { 698 return NULL; 699 } 700 JVM_END 701 702 // Sets the memory pool sensor for a threshold type 703 JVM_ENTRY(void, jmm_SetPoolSensor(JNIEnv* env, jobject obj, jmmThresholdType type, jobject sensorObj)) 704 if (obj == NULL || sensorObj == NULL) { 705 THROW(vmSymbols::java_lang_NullPointerException()); 706 } 707 708 Klass* sensor_klass = Management::sun_management_Sensor_klass(CHECK); 709 oop s = JNIHandles::resolve(sensorObj); 710 assert(s->is_instance(), "Sensor should be an instanceOop"); 711 instanceHandle sensor_h(THREAD, (instanceOop) s); 712 if (!sensor_h->is_a(sensor_klass)) { 713 THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(), 714 "Sensor is not an instance of sun.management.Sensor class"); 715 } 716 717 MemoryPool* mpool = get_memory_pool_from_jobject(obj, CHECK); 718 assert(mpool != NULL, "MemoryPool should exist"); 719 720 switch (type) { 721 case JMM_USAGE_THRESHOLD_HIGH: 722 case JMM_USAGE_THRESHOLD_LOW: 723 // have only one sensor for threshold high and low 724 mpool->set_usage_sensor_obj(sensor_h); 725 break; 726 case JMM_COLLECTION_USAGE_THRESHOLD_HIGH: 727 case JMM_COLLECTION_USAGE_THRESHOLD_LOW: 728 // have only one sensor for threshold high and low 729 mpool->set_gc_usage_sensor_obj(sensor_h); 730 break; 731 default: 732 assert(false, "Unrecognized type"); 733 } 734 735 JVM_END 736 737 738 // Sets the threshold of a given memory pool. 739 // Returns the previous threshold. 740 // 741 // Input parameters: 742 // pool - the MemoryPoolMXBean object 743 // type - threshold type 744 // threshold - the new threshold (must not be negative) 745 // 746 JVM_ENTRY(jlong, jmm_SetPoolThreshold(JNIEnv* env, jobject obj, jmmThresholdType type, jlong threshold)) 747 if (threshold < 0) { 748 THROW_MSG_(vmSymbols::java_lang_IllegalArgumentException(), 749 "Invalid threshold value", 750 -1); 751 } 752 753 if ((size_t)threshold > max_uintx) { 754 stringStream st; 755 st.print("Invalid valid threshold value. Threshold value (" UINT64_FORMAT ") > max value of size_t (" SIZE_FORMAT ")", (size_t)threshold, max_uintx); 756 THROW_MSG_(vmSymbols::java_lang_IllegalArgumentException(), st.as_string(), -1); 757 } 758 759 MemoryPool* pool = get_memory_pool_from_jobject(obj, CHECK_(0L)); 760 assert(pool != NULL, "MemoryPool should exist"); 761 762 jlong prev = 0; 763 switch (type) { 764 case JMM_USAGE_THRESHOLD_HIGH: 765 if (!pool->usage_threshold()->is_high_threshold_supported()) { 766 return -1; 767 } 768 prev = pool->usage_threshold()->set_high_threshold((size_t) threshold); 769 break; 770 771 case JMM_USAGE_THRESHOLD_LOW: 772 if (!pool->usage_threshold()->is_low_threshold_supported()) { 773 return -1; 774 } 775 prev = pool->usage_threshold()->set_low_threshold((size_t) threshold); 776 break; 777 778 case JMM_COLLECTION_USAGE_THRESHOLD_HIGH: 779 if (!pool->gc_usage_threshold()->is_high_threshold_supported()) { 780 return -1; 781 } 782 // return and the new threshold is effective for the next GC 783 return pool->gc_usage_threshold()->set_high_threshold((size_t) threshold); 784 785 case JMM_COLLECTION_USAGE_THRESHOLD_LOW: 786 if (!pool->gc_usage_threshold()->is_low_threshold_supported()) { 787 return -1; 788 } 789 // return and the new threshold is effective for the next GC 790 return pool->gc_usage_threshold()->set_low_threshold((size_t) threshold); 791 792 default: 793 assert(false, "Unrecognized type"); 794 return -1; 795 } 796 797 // When the threshold is changed, reevaluate if the low memory 798 // detection is enabled. 799 if (prev != threshold) { 800 LowMemoryDetector::recompute_enabled_for_collected_pools(); 801 LowMemoryDetector::detect_low_memory(pool); 802 } 803 return prev; 804 JVM_END 805 806 // Returns a java/lang/management/MemoryUsage object representing 807 // the memory usage for the heap or non-heap memory. 808 JVM_ENTRY(jobject, jmm_GetMemoryUsage(JNIEnv* env, jboolean heap)) 809 ResourceMark rm(THREAD); 810 811 // Calculate the memory usage 812 size_t total_init = 0; 813 size_t total_used = 0; 814 size_t total_committed = 0; 815 size_t total_max = 0; 816 bool has_undefined_init_size = false; 817 bool has_undefined_max_size = false; 818 819 for (int i = 0; i < MemoryService::num_memory_pools(); i++) { 820 MemoryPool* pool = MemoryService::get_memory_pool(i); 821 if ((heap && pool->is_heap()) || (!heap && pool->is_non_heap())) { 822 MemoryUsage u = pool->get_memory_usage(); 823 total_used += u.used(); 824 total_committed += u.committed(); 825 826 if (u.init_size() == (size_t)-1) { 827 has_undefined_init_size = true; 828 } 829 if (!has_undefined_init_size) { 830 total_init += u.init_size(); 831 } 832 833 if (u.max_size() == (size_t)-1) { 834 has_undefined_max_size = true; 835 } 836 if (!has_undefined_max_size) { 837 total_max += u.max_size(); 838 } 839 } 840 } 841 842 // if any one of the memory pool has undefined init_size or max_size, 843 // set it to -1 844 if (has_undefined_init_size) { 845 total_init = (size_t)-1; 846 } 847 if (has_undefined_max_size) { 848 total_max = (size_t)-1; 849 } 850 851 MemoryUsage usage((heap ? InitialHeapSize : total_init), 852 total_used, 853 total_committed, 854 (heap ? Universe::heap()->max_capacity() : total_max)); 855 856 Handle obj = MemoryService::create_MemoryUsage_obj(usage, CHECK_NULL); 857 return JNIHandles::make_local(env, obj()); 858 JVM_END 859 860 // Returns the boolean value of a given attribute. 861 JVM_LEAF(jboolean, jmm_GetBoolAttribute(JNIEnv *env, jmmBoolAttribute att)) 862 switch (att) { 863 case JMM_VERBOSE_GC: 864 return MemoryService::get_verbose(); 865 case JMM_VERBOSE_CLASS: 866 return ClassLoadingService::get_verbose(); 867 case JMM_THREAD_CONTENTION_MONITORING: 868 return ThreadService::is_thread_monitoring_contention(); 869 case JMM_THREAD_CPU_TIME: 870 return ThreadService::is_thread_cpu_time_enabled(); 871 case JMM_THREAD_ALLOCATED_MEMORY: 872 return ThreadService::is_thread_allocated_memory_enabled(); 873 default: 874 assert(0, "Unrecognized attribute"); 875 return false; 876 } 877 JVM_END 878 879 // Sets the given boolean attribute and returns the previous value. 880 JVM_ENTRY(jboolean, jmm_SetBoolAttribute(JNIEnv *env, jmmBoolAttribute att, jboolean flag)) 881 switch (att) { 882 case JMM_VERBOSE_GC: 883 return MemoryService::set_verbose(flag != 0); 884 case JMM_VERBOSE_CLASS: 885 return ClassLoadingService::set_verbose(flag != 0); 886 case JMM_THREAD_CONTENTION_MONITORING: 887 return ThreadService::set_thread_monitoring_contention(flag != 0); 888 case JMM_THREAD_CPU_TIME: 889 return ThreadService::set_thread_cpu_time_enabled(flag != 0); 890 case JMM_THREAD_ALLOCATED_MEMORY: 891 return ThreadService::set_thread_allocated_memory_enabled(flag != 0); 892 default: 893 assert(0, "Unrecognized attribute"); 894 return false; 895 } 896 JVM_END 897 898 899 static jlong get_gc_attribute(GCMemoryManager* mgr, jmmLongAttribute att) { 900 switch (att) { 901 case JMM_GC_TIME_MS: 902 return mgr->gc_time_ms(); 903 904 case JMM_GC_COUNT: 905 return mgr->gc_count(); 906 907 case JMM_GC_EXT_ATTRIBUTE_INFO_SIZE: 908 // current implementation only has 1 ext attribute 909 return 1; 910 911 default: 912 assert(0, "Unrecognized GC attribute"); 913 return -1; 914 } 915 } 916 917 class VmThreadCountClosure: public ThreadClosure { 918 private: 919 int _count; 920 public: 921 VmThreadCountClosure() : _count(0) {}; 922 void do_thread(Thread* thread); 923 int count() { return _count; } 924 }; 925 926 void VmThreadCountClosure::do_thread(Thread* thread) { 927 // exclude externally visible JavaThreads 928 if (thread->is_Java_thread() && !thread->is_hidden_from_external_view()) { 929 return; 930 } 931 932 _count++; 933 } 934 935 static jint get_vm_thread_count() { 936 VmThreadCountClosure vmtcc; 937 { 938 MutexLockerEx ml(Threads_lock); 939 Threads::threads_do(&vmtcc); 940 } 941 942 return vmtcc.count(); 943 } 944 945 static jint get_num_flags() { 946 // last flag entry is always NULL, so subtract 1 947 int nFlags = (int) Flag::numFlags - 1; 948 int count = 0; 949 for (int i = 0; i < nFlags; i++) { 950 Flag* flag = &Flag::flags[i]; 951 // Exclude the locked (diagnostic, experimental) flags 952 if (flag->is_unlocked() || flag->is_unlocker()) { 953 count++; 954 } 955 } 956 return count; 957 } 958 959 static jlong get_long_attribute(jmmLongAttribute att) { 960 switch (att) { 961 case JMM_CLASS_LOADED_COUNT: 962 return ClassLoadingService::loaded_class_count(); 963 964 case JMM_CLASS_UNLOADED_COUNT: 965 return ClassLoadingService::unloaded_class_count(); 966 967 case JMM_THREAD_TOTAL_COUNT: 968 return ThreadService::get_total_thread_count(); 969 970 case JMM_THREAD_LIVE_COUNT: 971 return ThreadService::get_live_thread_count(); 972 973 case JMM_THREAD_PEAK_COUNT: 974 return ThreadService::get_peak_thread_count(); 975 976 case JMM_THREAD_DAEMON_COUNT: 977 return ThreadService::get_daemon_thread_count(); 978 979 case JMM_JVM_INIT_DONE_TIME_MS: 980 return Management::vm_init_done_time(); 981 982 case JMM_JVM_UPTIME_MS: 983 return Management::ticks_to_ms(os::elapsed_counter()); 984 985 case JMM_COMPILE_TOTAL_TIME_MS: 986 return Management::ticks_to_ms(CompileBroker::total_compilation_ticks()); 987 988 case JMM_OS_PROCESS_ID: 989 return os::current_process_id(); 990 991 // Hotspot-specific counters 992 case JMM_CLASS_LOADED_BYTES: 993 return ClassLoadingService::loaded_class_bytes(); 994 995 case JMM_CLASS_UNLOADED_BYTES: 996 return ClassLoadingService::unloaded_class_bytes(); 997 998 case JMM_SHARED_CLASS_LOADED_COUNT: 999 return ClassLoadingService::loaded_shared_class_count(); 1000 1001 case JMM_SHARED_CLASS_UNLOADED_COUNT: 1002 return ClassLoadingService::unloaded_shared_class_count(); 1003 1004 1005 case JMM_SHARED_CLASS_LOADED_BYTES: 1006 return ClassLoadingService::loaded_shared_class_bytes(); 1007 1008 case JMM_SHARED_CLASS_UNLOADED_BYTES: 1009 return ClassLoadingService::unloaded_shared_class_bytes(); 1010 1011 case JMM_TOTAL_CLASSLOAD_TIME_MS: 1012 return ClassLoader::classloader_time_ms(); 1013 1014 case JMM_VM_GLOBAL_COUNT: 1015 return get_num_flags(); 1016 1017 case JMM_SAFEPOINT_COUNT: 1018 return RuntimeService::safepoint_count(); 1019 1020 case JMM_TOTAL_SAFEPOINTSYNC_TIME_MS: 1021 return RuntimeService::safepoint_sync_time_ms(); 1022 1023 case JMM_TOTAL_STOPPED_TIME_MS: 1024 return RuntimeService::safepoint_time_ms(); 1025 1026 case JMM_TOTAL_APP_TIME_MS: 1027 return RuntimeService::application_time_ms(); 1028 1029 case JMM_VM_THREAD_COUNT: 1030 return get_vm_thread_count(); 1031 1032 case JMM_CLASS_INIT_TOTAL_COUNT: 1033 return ClassLoader::class_init_count(); 1034 1035 case JMM_CLASS_INIT_TOTAL_TIME_MS: 1036 return ClassLoader::class_init_time_ms(); 1037 1038 case JMM_CLASS_VERIFY_TOTAL_TIME_MS: 1039 return ClassLoader::class_verify_time_ms(); 1040 1041 case JMM_METHOD_DATA_SIZE_BYTES: 1042 return ClassLoadingService::class_method_data_size(); 1043 1044 case JMM_OS_MEM_TOTAL_PHYSICAL_BYTES: 1045 return os::physical_memory(); 1046 1047 default: 1048 return -1; 1049 } 1050 } 1051 1052 1053 // Returns the long value of a given attribute. 1054 JVM_ENTRY(jlong, jmm_GetLongAttribute(JNIEnv *env, jobject obj, jmmLongAttribute att)) 1055 if (obj == NULL) { 1056 return get_long_attribute(att); 1057 } else { 1058 GCMemoryManager* mgr = get_gc_memory_manager_from_jobject(obj, CHECK_(0L)); 1059 if (mgr != NULL) { 1060 return get_gc_attribute(mgr, att); 1061 } 1062 } 1063 return -1; 1064 JVM_END 1065 1066 // Gets the value of all attributes specified in the given array 1067 // and sets the value in the result array. 1068 // Returns the number of attributes found. 1069 JVM_ENTRY(jint, jmm_GetLongAttributes(JNIEnv *env, 1070 jobject obj, 1071 jmmLongAttribute* atts, 1072 jint count, 1073 jlong* result)) 1074 1075 int num_atts = 0; 1076 if (obj == NULL) { 1077 for (int i = 0; i < count; i++) { 1078 result[i] = get_long_attribute(atts[i]); 1079 if (result[i] != -1) { 1080 num_atts++; 1081 } 1082 } 1083 } else { 1084 GCMemoryManager* mgr = get_gc_memory_manager_from_jobject(obj, CHECK_0); 1085 for (int i = 0; i < count; i++) { 1086 result[i] = get_gc_attribute(mgr, atts[i]); 1087 if (result[i] != -1) { 1088 num_atts++; 1089 } 1090 } 1091 } 1092 return num_atts; 1093 JVM_END 1094 1095 // Helper function to do thread dump for a specific list of threads 1096 static void do_thread_dump(ThreadDumpResult* dump_result, 1097 typeArrayHandle ids_ah, // array of thread ID (long[]) 1098 int num_threads, 1099 int max_depth, 1100 bool with_locked_monitors, 1101 bool with_locked_synchronizers, 1102 TRAPS) { 1103 1104 // First get an array of threadObj handles. 1105 // A JavaThread may terminate before we get the stack trace. 1106 GrowableArray<instanceHandle>* thread_handle_array = new GrowableArray<instanceHandle>(num_threads); 1107 { 1108 MutexLockerEx ml(Threads_lock); 1109 for (int i = 0; i < num_threads; i++) { 1110 jlong tid = ids_ah->long_at(i); 1111 JavaThread* jt = Threads::find_java_thread_from_java_tid(tid); 1112 oop thread_obj = (jt != NULL ? jt->threadObj() : (oop)NULL); 1113 instanceHandle threadObj_h(THREAD, (instanceOop) thread_obj); 1114 thread_handle_array->append(threadObj_h); 1115 } 1116 } 1117 1118 // Obtain thread dumps and thread snapshot information 1119 VM_ThreadDump op(dump_result, 1120 thread_handle_array, 1121 num_threads, 1122 max_depth, /* stack depth */ 1123 with_locked_monitors, 1124 with_locked_synchronizers); 1125 VMThread::execute(&op); 1126 } 1127 1128 // Gets an array of ThreadInfo objects. Each element is the ThreadInfo 1129 // for the thread ID specified in the corresponding entry in 1130 // the given array of thread IDs; or NULL if the thread does not exist 1131 // or has terminated. 1132 // 1133 // Input parameters: 1134 // ids - array of thread IDs 1135 // maxDepth - the maximum depth of stack traces to be dumped: 1136 // maxDepth == -1 requests to dump entire stack trace. 1137 // maxDepth == 0 requests no stack trace. 1138 // infoArray - array of ThreadInfo objects 1139 // 1140 // QQQ - Why does this method return a value instead of void? 1141 JVM_ENTRY(jint, jmm_GetThreadInfo(JNIEnv *env, jlongArray ids, jint maxDepth, jobjectArray infoArray)) 1142 // Check if threads is null 1143 if (ids == NULL || infoArray == NULL) { 1144 THROW_(vmSymbols::java_lang_NullPointerException(), -1); 1145 } 1146 1147 if (maxDepth < -1) { 1148 THROW_MSG_(vmSymbols::java_lang_IllegalArgumentException(), 1149 "Invalid maxDepth", -1); 1150 } 1151 1152 ResourceMark rm(THREAD); 1153 typeArrayOop ta = typeArrayOop(JNIHandles::resolve_non_null(ids)); 1154 typeArrayHandle ids_ah(THREAD, ta); 1155 1156 oop infoArray_obj = JNIHandles::resolve_non_null(infoArray); 1157 objArrayOop oa = objArrayOop(infoArray_obj); 1158 objArrayHandle infoArray_h(THREAD, oa); 1159 1160 // validate the thread id array 1161 validate_thread_id_array(ids_ah, CHECK_0); 1162 1163 // validate the ThreadInfo[] parameters 1164 validate_thread_info_array(infoArray_h, CHECK_0); 1165 1166 // infoArray must be of the same length as the given array of thread IDs 1167 int num_threads = ids_ah->length(); 1168 if (num_threads != infoArray_h->length()) { 1169 THROW_MSG_(vmSymbols::java_lang_IllegalArgumentException(), 1170 "The length of the given ThreadInfo array does not match the length of the given array of thread IDs", -1); 1171 } 1172 1173 // make sure the AbstractOwnableSynchronizer klass is loaded before taking thread snapshots 1174 java_util_concurrent_locks_AbstractOwnableSynchronizer::initialize(CHECK_0); 1175 1176 // Must use ThreadDumpResult to store the ThreadSnapshot. 1177 // GC may occur after the thread snapshots are taken but before 1178 // this function returns. The threadObj and other oops kept 1179 // in the ThreadSnapshot are marked and adjusted during GC. 1180 ThreadDumpResult dump_result(num_threads); 1181 1182 if (maxDepth == 0) { 1183 // no stack trace dumped - do not need to stop the world 1184 { 1185 MutexLockerEx ml(Threads_lock); 1186 for (int i = 0; i < num_threads; i++) { 1187 jlong tid = ids_ah->long_at(i); 1188 JavaThread* jt = Threads::find_java_thread_from_java_tid(tid); 1189 ThreadSnapshot* ts; 1190 if (jt == NULL) { 1191 // if the thread does not exist or now it is terminated, 1192 // create dummy snapshot 1193 ts = new ThreadSnapshot(); 1194 } else { 1195 ts = new ThreadSnapshot(jt); 1196 } 1197 dump_result.add_thread_snapshot(ts); 1198 } 1199 } 1200 } else { 1201 // obtain thread dump with the specific list of threads with stack trace 1202 do_thread_dump(&dump_result, 1203 ids_ah, 1204 num_threads, 1205 maxDepth, 1206 false, /* no locked monitor */ 1207 false, /* no locked synchronizers */ 1208 CHECK_0); 1209 } 1210 1211 int num_snapshots = dump_result.num_snapshots(); 1212 assert(num_snapshots == num_threads, "Must match the number of thread snapshots"); 1213 int index = 0; 1214 for (ThreadSnapshot* ts = dump_result.snapshots(); ts != NULL; index++, ts = ts->next()) { 1215 // For each thread, create an java/lang/management/ThreadInfo object 1216 // and fill with the thread information 1217 1218 if (ts->threadObj() == NULL) { 1219 // if the thread does not exist or now it is terminated, set threadinfo to NULL 1220 infoArray_h->obj_at_put(index, NULL); 1221 continue; 1222 } 1223 1224 // Create java.lang.management.ThreadInfo object 1225 instanceOop info_obj = Management::create_thread_info_instance(ts, CHECK_0); 1226 infoArray_h->obj_at_put(index, info_obj); 1227 } 1228 return 0; 1229 JVM_END 1230 1231 // Dump thread info for the specified threads. 1232 // It returns an array of ThreadInfo objects. Each element is the ThreadInfo 1233 // for the thread ID specified in the corresponding entry in 1234 // the given array of thread IDs; or NULL if the thread does not exist 1235 // or has terminated. 1236 // 1237 // Input parameter: 1238 // ids - array of thread IDs; NULL indicates all live threads 1239 // locked_monitors - if true, dump locked object monitors 1240 // locked_synchronizers - if true, dump locked JSR-166 synchronizers 1241 // 1242 JVM_ENTRY(jobjectArray, jmm_DumpThreads(JNIEnv *env, jlongArray thread_ids, jboolean locked_monitors, jboolean locked_synchronizers)) 1243 ResourceMark rm(THREAD); 1244 1245 // make sure the AbstractOwnableSynchronizer klass is loaded before taking thread snapshots 1246 java_util_concurrent_locks_AbstractOwnableSynchronizer::initialize(CHECK_NULL); 1247 1248 typeArrayOop ta = typeArrayOop(JNIHandles::resolve(thread_ids)); 1249 int num_threads = (ta != NULL ? ta->length() : 0); 1250 typeArrayHandle ids_ah(THREAD, ta); 1251 1252 ThreadDumpResult dump_result(num_threads); // can safepoint 1253 1254 if (ids_ah() != NULL) { 1255 1256 // validate the thread id array 1257 validate_thread_id_array(ids_ah, CHECK_NULL); 1258 1259 // obtain thread dump of a specific list of threads 1260 do_thread_dump(&dump_result, 1261 ids_ah, 1262 num_threads, 1263 -1, /* entire stack */ 1264 (locked_monitors ? true : false), /* with locked monitors */ 1265 (locked_synchronizers ? true : false), /* with locked synchronizers */ 1266 CHECK_NULL); 1267 } else { 1268 // obtain thread dump of all threads 1269 VM_ThreadDump op(&dump_result, 1270 -1, /* entire stack */ 1271 (locked_monitors ? true : false), /* with locked monitors */ 1272 (locked_synchronizers ? true : false) /* with locked synchronizers */); 1273 VMThread::execute(&op); 1274 } 1275 1276 int num_snapshots = dump_result.num_snapshots(); 1277 1278 // create the result ThreadInfo[] object 1279 Klass* k = Management::java_lang_management_ThreadInfo_klass(CHECK_NULL); 1280 instanceKlassHandle ik (THREAD, k); 1281 objArrayOop r = oopFactory::new_objArray(ik(), num_snapshots, CHECK_NULL); 1282 objArrayHandle result_h(THREAD, r); 1283 1284 int index = 0; 1285 for (ThreadSnapshot* ts = dump_result.snapshots(); ts != NULL; ts = ts->next(), index++) { 1286 if (ts->threadObj() == NULL) { 1287 // if the thread does not exist or now it is terminated, set threadinfo to NULL 1288 result_h->obj_at_put(index, NULL); 1289 continue; 1290 } 1291 1292 ThreadStackTrace* stacktrace = ts->get_stack_trace(); 1293 assert(stacktrace != NULL, "Must have a stack trace dumped"); 1294 1295 // Create Object[] filled with locked monitors 1296 // Create int[] filled with the stack depth where a monitor was locked 1297 int num_frames = stacktrace->get_stack_depth(); 1298 int num_locked_monitors = stacktrace->num_jni_locked_monitors(); 1299 1300 // Count the total number of locked monitors 1301 for (int i = 0; i < num_frames; i++) { 1302 StackFrameInfo* frame = stacktrace->stack_frame_at(i); 1303 num_locked_monitors += frame->num_locked_monitors(); 1304 } 1305 1306 objArrayHandle monitors_array; 1307 typeArrayHandle depths_array; 1308 objArrayHandle synchronizers_array; 1309 1310 if (locked_monitors) { 1311 // Constructs Object[] and int[] to contain the object monitor and the stack depth 1312 // where the thread locked it 1313 objArrayOop array = oopFactory::new_objArray(SystemDictionary::Object_klass(), num_locked_monitors, CHECK_NULL); 1314 objArrayHandle mh(THREAD, array); 1315 monitors_array = mh; 1316 1317 typeArrayOop tarray = oopFactory::new_typeArray(T_INT, num_locked_monitors, CHECK_NULL); 1318 typeArrayHandle dh(THREAD, tarray); 1319 depths_array = dh; 1320 1321 int count = 0; 1322 int j = 0; 1323 for (int depth = 0; depth < num_frames; depth++) { 1324 StackFrameInfo* frame = stacktrace->stack_frame_at(depth); 1325 int len = frame->num_locked_monitors(); 1326 GrowableArray<oop>* locked_monitors = frame->locked_monitors(); 1327 for (j = 0; j < len; j++) { 1328 oop monitor = locked_monitors->at(j); 1329 assert(monitor != NULL, "must be a Java object"); 1330 monitors_array->obj_at_put(count, monitor); 1331 depths_array->int_at_put(count, depth); 1332 count++; 1333 } 1334 } 1335 1336 GrowableArray<oop>* jni_locked_monitors = stacktrace->jni_locked_monitors(); 1337 for (j = 0; j < jni_locked_monitors->length(); j++) { 1338 oop object = jni_locked_monitors->at(j); 1339 assert(object != NULL, "must be a Java object"); 1340 monitors_array->obj_at_put(count, object); 1341 // Monitor locked via JNI MonitorEnter call doesn't have stack depth info 1342 depths_array->int_at_put(count, -1); 1343 count++; 1344 } 1345 assert(count == num_locked_monitors, "number of locked monitors doesn't match"); 1346 } 1347 1348 if (locked_synchronizers) { 1349 // Create Object[] filled with locked JSR-166 synchronizers 1350 assert(ts->threadObj() != NULL, "Must be a valid JavaThread"); 1351 ThreadConcurrentLocks* tcl = ts->get_concurrent_locks(); 1352 GrowableArray<instanceOop>* locks = (tcl != NULL ? tcl->owned_locks() : NULL); 1353 int num_locked_synchronizers = (locks != NULL ? locks->length() : 0); 1354 1355 objArrayOop array = oopFactory::new_objArray(SystemDictionary::Object_klass(), num_locked_synchronizers, CHECK_NULL); 1356 objArrayHandle sh(THREAD, array); 1357 synchronizers_array = sh; 1358 1359 for (int k = 0; k < num_locked_synchronizers; k++) { 1360 synchronizers_array->obj_at_put(k, locks->at(k)); 1361 } 1362 } 1363 1364 // Create java.lang.management.ThreadInfo object 1365 instanceOop info_obj = Management::create_thread_info_instance(ts, 1366 monitors_array, 1367 depths_array, 1368 synchronizers_array, 1369 CHECK_NULL); 1370 result_h->obj_at_put(index, info_obj); 1371 } 1372 1373 return (jobjectArray) JNIHandles::make_local(env, result_h()); 1374 JVM_END 1375 1376 // Returns an array of Class objects. 1377 JVM_ENTRY(jobjectArray, jmm_GetLoadedClasses(JNIEnv *env)) 1378 ResourceMark rm(THREAD); 1379 1380 LoadedClassesEnumerator lce(THREAD); // Pass current Thread as parameter 1381 1382 int num_classes = lce.num_loaded_classes(); 1383 objArrayOop r = oopFactory::new_objArray(SystemDictionary::Class_klass(), num_classes, CHECK_0); 1384 objArrayHandle classes_ah(THREAD, r); 1385 1386 for (int i = 0; i < num_classes; i++) { 1387 KlassHandle kh = lce.get_klass(i); 1388 oop mirror = kh()->java_mirror(); 1389 classes_ah->obj_at_put(i, mirror); 1390 } 1391 1392 return (jobjectArray) JNIHandles::make_local(env, classes_ah()); 1393 JVM_END 1394 1395 // Reset statistic. Return true if the requested statistic is reset. 1396 // Otherwise, return false. 1397 // 1398 // Input parameters: 1399 // obj - specify which instance the statistic associated with to be reset 1400 // For PEAK_POOL_USAGE stat, obj is required to be a memory pool object. 1401 // For THREAD_CONTENTION_COUNT and TIME stat, obj is required to be a thread ID. 1402 // type - the type of statistic to be reset 1403 // 1404 JVM_ENTRY(jboolean, jmm_ResetStatistic(JNIEnv *env, jvalue obj, jmmStatisticType type)) 1405 ResourceMark rm(THREAD); 1406 1407 switch (type) { 1408 case JMM_STAT_PEAK_THREAD_COUNT: 1409 ThreadService::reset_peak_thread_count(); 1410 return true; 1411 1412 case JMM_STAT_THREAD_CONTENTION_COUNT: 1413 case JMM_STAT_THREAD_CONTENTION_TIME: { 1414 jlong tid = obj.j; 1415 if (tid < 0) { 1416 THROW_(vmSymbols::java_lang_IllegalArgumentException(), JNI_FALSE); 1417 } 1418 1419 // Look for the JavaThread of this given tid 1420 MutexLockerEx ml(Threads_lock); 1421 if (tid == 0) { 1422 // reset contention statistics for all threads if tid == 0 1423 for (JavaThread* java_thread = Threads::first(); java_thread != NULL; java_thread = java_thread->next()) { 1424 if (type == JMM_STAT_THREAD_CONTENTION_COUNT) { 1425 ThreadService::reset_contention_count_stat(java_thread); 1426 } else { 1427 ThreadService::reset_contention_time_stat(java_thread); 1428 } 1429 } 1430 } else { 1431 // reset contention statistics for a given thread 1432 JavaThread* java_thread = Threads::find_java_thread_from_java_tid(tid); 1433 if (java_thread == NULL) { 1434 return false; 1435 } 1436 1437 if (type == JMM_STAT_THREAD_CONTENTION_COUNT) { 1438 ThreadService::reset_contention_count_stat(java_thread); 1439 } else { 1440 ThreadService::reset_contention_time_stat(java_thread); 1441 } 1442 } 1443 return true; 1444 break; 1445 } 1446 case JMM_STAT_PEAK_POOL_USAGE: { 1447 jobject o = obj.l; 1448 if (o == NULL) { 1449 THROW_(vmSymbols::java_lang_NullPointerException(), JNI_FALSE); 1450 } 1451 1452 oop pool_obj = JNIHandles::resolve(o); 1453 assert(pool_obj->is_instance(), "Should be an instanceOop"); 1454 instanceHandle ph(THREAD, (instanceOop) pool_obj); 1455 1456 MemoryPool* pool = MemoryService::get_memory_pool(ph); 1457 if (pool != NULL) { 1458 pool->reset_peak_memory_usage(); 1459 return true; 1460 } 1461 break; 1462 } 1463 case JMM_STAT_GC_STAT: { 1464 jobject o = obj.l; 1465 if (o == NULL) { 1466 THROW_(vmSymbols::java_lang_NullPointerException(), JNI_FALSE); 1467 } 1468 1469 GCMemoryManager* mgr = get_gc_memory_manager_from_jobject(o, CHECK_0); 1470 if (mgr != NULL) { 1471 mgr->reset_gc_stat(); 1472 return true; 1473 } 1474 break; 1475 } 1476 default: 1477 assert(0, "Unknown Statistic Type"); 1478 } 1479 return false; 1480 JVM_END 1481 1482 // Returns the fast estimate of CPU time consumed by 1483 // a given thread (in nanoseconds). 1484 // If thread_id == 0, return CPU time for the current thread. 1485 JVM_ENTRY(jlong, jmm_GetThreadCpuTime(JNIEnv *env, jlong thread_id)) 1486 if (!os::is_thread_cpu_time_supported()) { 1487 return -1; 1488 } 1489 1490 if (thread_id < 0) { 1491 THROW_MSG_(vmSymbols::java_lang_IllegalArgumentException(), 1492 "Invalid thread ID", -1); 1493 } 1494 1495 JavaThread* java_thread = NULL; 1496 if (thread_id == 0) { 1497 // current thread 1498 return os::current_thread_cpu_time(); 1499 } else { 1500 MutexLockerEx ml(Threads_lock); 1501 java_thread = Threads::find_java_thread_from_java_tid(thread_id); 1502 if (java_thread != NULL) { 1503 return os::thread_cpu_time((Thread*) java_thread); 1504 } 1505 } 1506 return -1; 1507 JVM_END 1508 1509 // Returns a String array of all VM global flag names 1510 JVM_ENTRY(jobjectArray, jmm_GetVMGlobalNames(JNIEnv *env)) 1511 // last flag entry is always NULL, so subtract 1 1512 int nFlags = (int) Flag::numFlags - 1; 1513 // allocate a temp array 1514 objArrayOop r = oopFactory::new_objArray(SystemDictionary::String_klass(), 1515 nFlags, CHECK_0); 1516 objArrayHandle flags_ah(THREAD, r); 1517 int num_entries = 0; 1518 for (int i = 0; i < nFlags; i++) { 1519 Flag* flag = &Flag::flags[i]; 1520 // Exclude notproduct and develop flags in product builds. 1521 if (flag->is_constant_in_binary()) { 1522 continue; 1523 } 1524 // Exclude the locked (experimental, diagnostic) flags 1525 if (flag->is_unlocked() || flag->is_unlocker()) { 1526 Handle s = java_lang_String::create_from_str(flag->_name, CHECK_0); 1527 flags_ah->obj_at_put(num_entries, s()); 1528 num_entries++; 1529 } 1530 } 1531 1532 if (num_entries < nFlags) { 1533 // Return array of right length 1534 objArrayOop res = oopFactory::new_objArray(SystemDictionary::String_klass(), num_entries, CHECK_0); 1535 for(int i = 0; i < num_entries; i++) { 1536 res->obj_at_put(i, flags_ah->obj_at(i)); 1537 } 1538 return (jobjectArray)JNIHandles::make_local(env, res); 1539 } 1540 1541 return (jobjectArray)JNIHandles::make_local(env, flags_ah()); 1542 JVM_END 1543 1544 // Utility function used by jmm_GetVMGlobals. Returns false if flag type 1545 // can't be determined, true otherwise. If false is returned, then *global 1546 // will be incomplete and invalid. 1547 bool add_global_entry(JNIEnv* env, Handle name, jmmVMGlobal *global, Flag *flag, TRAPS) { 1548 Handle flag_name; 1549 if (name() == NULL) { 1550 flag_name = java_lang_String::create_from_str(flag->_name, CHECK_false); 1551 } else { 1552 flag_name = name; 1553 } 1554 global->name = (jstring)JNIHandles::make_local(env, flag_name()); 1555 1556 if (flag->is_bool()) { 1557 global->value.z = flag->get_bool() ? JNI_TRUE : JNI_FALSE; 1558 global->type = JMM_VMGLOBAL_TYPE_JBOOLEAN; 1559 } else if (flag->is_intx()) { 1560 global->value.j = (jlong)flag->get_intx(); 1561 global->type = JMM_VMGLOBAL_TYPE_JLONG; 1562 } else if (flag->is_uintx()) { 1563 global->value.j = (jlong)flag->get_uintx(); 1564 global->type = JMM_VMGLOBAL_TYPE_JLONG; 1565 } else if (flag->is_uint64_t()) { 1566 global->value.j = (jlong)flag->get_uint64_t(); 1567 global->type = JMM_VMGLOBAL_TYPE_JLONG; 1568 } else if (flag->is_double()) { 1569 global->value.d = (jdouble)flag->get_double(); 1570 global->type = JMM_VMGLOBAL_TYPE_JDOUBLE; 1571 } else if (flag->is_size_t()) { 1572 global->value.j = (jlong)flag->get_size_t(); 1573 global->type = JMM_VMGLOBAL_TYPE_JLONG; 1574 } else if (flag->is_ccstr()) { 1575 Handle str = java_lang_String::create_from_str(flag->get_ccstr(), CHECK_false); 1576 global->value.l = (jobject)JNIHandles::make_local(env, str()); 1577 global->type = JMM_VMGLOBAL_TYPE_JSTRING; 1578 } else { 1579 global->type = JMM_VMGLOBAL_TYPE_UNKNOWN; 1580 return false; 1581 } 1582 1583 global->writeable = flag->is_writeable(); 1584 global->external = flag->is_external(); 1585 switch (flag->get_origin()) { 1586 case Flag::DEFAULT: 1587 global->origin = JMM_VMGLOBAL_ORIGIN_DEFAULT; 1588 break; 1589 case Flag::COMMAND_LINE: 1590 global->origin = JMM_VMGLOBAL_ORIGIN_COMMAND_LINE; 1591 break; 1592 case Flag::ENVIRON_VAR: 1593 global->origin = JMM_VMGLOBAL_ORIGIN_ENVIRON_VAR; 1594 break; 1595 case Flag::CONFIG_FILE: 1596 global->origin = JMM_VMGLOBAL_ORIGIN_CONFIG_FILE; 1597 break; 1598 case Flag::MANAGEMENT: 1599 global->origin = JMM_VMGLOBAL_ORIGIN_MANAGEMENT; 1600 break; 1601 case Flag::ERGONOMIC: 1602 global->origin = JMM_VMGLOBAL_ORIGIN_ERGONOMIC; 1603 break; 1604 case Flag::ATTACH_ON_DEMAND: 1605 global->origin = JMM_VMGLOBAL_ORIGIN_ATTACH_ON_DEMAND; 1606 break; 1607 default: 1608 global->origin = JMM_VMGLOBAL_ORIGIN_OTHER; 1609 } 1610 1611 return true; 1612 } 1613 1614 // Fill globals array of count length with jmmVMGlobal entries 1615 // specified by names. If names == NULL, fill globals array 1616 // with all Flags. Return value is number of entries 1617 // created in globals. 1618 // If a Flag with a given name in an array element does not 1619 // exist, globals[i].name will be set to NULL. 1620 JVM_ENTRY(jint, jmm_GetVMGlobals(JNIEnv *env, 1621 jobjectArray names, 1622 jmmVMGlobal *globals, 1623 jint count)) 1624 1625 1626 if (globals == NULL) { 1627 THROW_(vmSymbols::java_lang_NullPointerException(), 0); 1628 } 1629 1630 ResourceMark rm(THREAD); 1631 1632 if (names != NULL) { 1633 // return the requested globals 1634 objArrayOop ta = objArrayOop(JNIHandles::resolve_non_null(names)); 1635 objArrayHandle names_ah(THREAD, ta); 1636 // Make sure we have a String array 1637 Klass* element_klass = ObjArrayKlass::cast(names_ah->klass())->element_klass(); 1638 if (element_klass != SystemDictionary::String_klass()) { 1639 THROW_MSG_(vmSymbols::java_lang_IllegalArgumentException(), 1640 "Array element type is not String class", 0); 1641 } 1642 1643 int names_length = names_ah->length(); 1644 int num_entries = 0; 1645 for (int i = 0; i < names_length && i < count; i++) { 1646 oop s = names_ah->obj_at(i); 1647 if (s == NULL) { 1648 THROW_(vmSymbols::java_lang_NullPointerException(), 0); 1649 } 1650 1651 Handle sh(THREAD, s); 1652 char* str = java_lang_String::as_utf8_string(s); 1653 Flag* flag = Flag::find_flag(str, strlen(str)); 1654 if (flag != NULL && 1655 add_global_entry(env, sh, &globals[i], flag, THREAD)) { 1656 num_entries++; 1657 } else { 1658 globals[i].name = NULL; 1659 } 1660 } 1661 return num_entries; 1662 } else { 1663 // return all globals if names == NULL 1664 1665 // last flag entry is always NULL, so subtract 1 1666 int nFlags = (int) Flag::numFlags - 1; 1667 Handle null_h; 1668 int num_entries = 0; 1669 for (int i = 0; i < nFlags && num_entries < count; i++) { 1670 Flag* flag = &Flag::flags[i]; 1671 // Exclude notproduct and develop flags in product builds. 1672 if (flag->is_constant_in_binary()) { 1673 continue; 1674 } 1675 // Exclude the locked (diagnostic, experimental) flags 1676 if ((flag->is_unlocked() || flag->is_unlocker()) && 1677 add_global_entry(env, null_h, &globals[num_entries], flag, THREAD)) { 1678 num_entries++; 1679 } 1680 } 1681 return num_entries; 1682 } 1683 JVM_END 1684 1685 JVM_ENTRY(void, jmm_SetVMGlobal(JNIEnv *env, jstring flag_name, jvalue new_value)) 1686 ResourceMark rm(THREAD); 1687 1688 oop fn = JNIHandles::resolve_external_guard(flag_name); 1689 if (fn == NULL) { 1690 THROW_MSG(vmSymbols::java_lang_NullPointerException(), 1691 "The flag name cannot be null."); 1692 } 1693 char* name = java_lang_String::as_utf8_string(fn); 1694 1695 FormatBuffer<80> err_msg("%s", ""); 1696 int succeed = WriteableFlags::set_flag(name, new_value, Flag::MANAGEMENT, err_msg); 1697 1698 if (succeed != WriteableFlags::SUCCESS) { 1699 if (succeed == WriteableFlags::MISSING_VALUE) { 1700 // missing value causes NPE to be thrown 1701 THROW(vmSymbols::java_lang_NullPointerException()); 1702 } else { 1703 // all the other errors are reported as IAE with the appropriate error message 1704 THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(), 1705 err_msg.buffer()); 1706 } 1707 } 1708 assert(succeed == WriteableFlags::SUCCESS, "Setting flag should succeed"); 1709 JVM_END 1710 1711 class ThreadTimesClosure: public ThreadClosure { 1712 private: 1713 objArrayHandle _names_strings; 1714 char **_names_chars; 1715 typeArrayHandle _times; 1716 int _names_len; 1717 int _times_len; 1718 int _count; 1719 1720 public: 1721 ThreadTimesClosure(objArrayHandle names, typeArrayHandle times); 1722 ~ThreadTimesClosure(); 1723 virtual void do_thread(Thread* thread); 1724 void do_unlocked(); 1725 int count() { return _count; } 1726 }; 1727 1728 ThreadTimesClosure::ThreadTimesClosure(objArrayHandle names, 1729 typeArrayHandle times) { 1730 assert(names() != NULL, "names was NULL"); 1731 assert(times() != NULL, "times was NULL"); 1732 _names_strings = names; 1733 _names_len = names->length(); 1734 _names_chars = NEW_C_HEAP_ARRAY(char*, _names_len, mtInternal); 1735 _times = times; 1736 _times_len = times->length(); 1737 _count = 0; 1738 } 1739 1740 // 1741 // Called with Threads_lock held 1742 // 1743 void ThreadTimesClosure::do_thread(Thread* thread) { 1744 assert(thread != NULL, "thread was NULL"); 1745 1746 // exclude externally visible JavaThreads 1747 if (thread->is_Java_thread() && !thread->is_hidden_from_external_view()) { 1748 return; 1749 } 1750 1751 if (_count >= _names_len || _count >= _times_len) { 1752 // skip if the result array is not big enough 1753 return; 1754 } 1755 1756 EXCEPTION_MARK; 1757 ResourceMark rm(THREAD); // thread->name() uses ResourceArea 1758 1759 assert(thread->name() != NULL, "All threads should have a name"); 1760 _names_chars[_count] = os::strdup(thread->name()); 1761 _times->long_at_put(_count, os::is_thread_cpu_time_supported() ? 1762 os::thread_cpu_time(thread) : -1); 1763 _count++; 1764 } 1765 1766 // Called without Threads_lock, we can allocate String objects. 1767 void ThreadTimesClosure::do_unlocked() { 1768 1769 EXCEPTION_MARK; 1770 for (int i = 0; i < _count; i++) { 1771 Handle s = java_lang_String::create_from_str(_names_chars[i], CHECK); 1772 _names_strings->obj_at_put(i, s()); 1773 } 1774 } 1775 1776 ThreadTimesClosure::~ThreadTimesClosure() { 1777 for (int i = 0; i < _count; i++) { 1778 os::free(_names_chars[i]); 1779 } 1780 FREE_C_HEAP_ARRAY(char *, _names_chars); 1781 } 1782 1783 // Fills names with VM internal thread names and times with the corresponding 1784 // CPU times. If names or times is NULL, a NullPointerException is thrown. 1785 // If the element type of names is not String, an IllegalArgumentException is 1786 // thrown. 1787 // If an array is not large enough to hold all the entries, only the entries 1788 // that fit will be returned. Return value is the number of VM internal 1789 // threads entries. 1790 JVM_ENTRY(jint, jmm_GetInternalThreadTimes(JNIEnv *env, 1791 jobjectArray names, 1792 jlongArray times)) 1793 if (names == NULL || times == NULL) { 1794 THROW_(vmSymbols::java_lang_NullPointerException(), 0); 1795 } 1796 objArrayOop na = objArrayOop(JNIHandles::resolve_non_null(names)); 1797 objArrayHandle names_ah(THREAD, na); 1798 1799 // Make sure we have a String array 1800 Klass* element_klass = ObjArrayKlass::cast(names_ah->klass())->element_klass(); 1801 if (element_klass != SystemDictionary::String_klass()) { 1802 THROW_MSG_(vmSymbols::java_lang_IllegalArgumentException(), 1803 "Array element type is not String class", 0); 1804 } 1805 1806 typeArrayOop ta = typeArrayOop(JNIHandles::resolve_non_null(times)); 1807 typeArrayHandle times_ah(THREAD, ta); 1808 1809 ThreadTimesClosure ttc(names_ah, times_ah); 1810 { 1811 MutexLockerEx ml(Threads_lock); 1812 Threads::threads_do(&ttc); 1813 } 1814 ttc.do_unlocked(); 1815 return ttc.count(); 1816 JVM_END 1817 1818 static Handle find_deadlocks(bool object_monitors_only, TRAPS) { 1819 ResourceMark rm(THREAD); 1820 1821 VM_FindDeadlocks op(!object_monitors_only /* also check concurrent locks? */); 1822 VMThread::execute(&op); 1823 1824 DeadlockCycle* deadlocks = op.result(); 1825 if (deadlocks == NULL) { 1826 // no deadlock found and return 1827 return Handle(); 1828 } 1829 1830 int num_threads = 0; 1831 DeadlockCycle* cycle; 1832 for (cycle = deadlocks; cycle != NULL; cycle = cycle->next()) { 1833 num_threads += cycle->num_threads(); 1834 } 1835 1836 objArrayOop r = oopFactory::new_objArray(SystemDictionary::Thread_klass(), num_threads, CHECK_NH); 1837 objArrayHandle threads_ah(THREAD, r); 1838 1839 int index = 0; 1840 for (cycle = deadlocks; cycle != NULL; cycle = cycle->next()) { 1841 GrowableArray<JavaThread*>* deadlock_threads = cycle->threads(); 1842 int len = deadlock_threads->length(); 1843 for (int i = 0; i < len; i++) { 1844 threads_ah->obj_at_put(index, deadlock_threads->at(i)->threadObj()); 1845 index++; 1846 } 1847 } 1848 return threads_ah; 1849 } 1850 1851 // Finds cycles of threads that are deadlocked involved in object monitors 1852 // and JSR-166 synchronizers. 1853 // Returns an array of Thread objects which are in deadlock, if any. 1854 // Otherwise, returns NULL. 1855 // 1856 // Input parameter: 1857 // object_monitors_only - if true, only check object monitors 1858 // 1859 JVM_ENTRY(jobjectArray, jmm_FindDeadlockedThreads(JNIEnv *env, jboolean object_monitors_only)) 1860 Handle result = find_deadlocks(object_monitors_only != 0, CHECK_0); 1861 return (jobjectArray) JNIHandles::make_local(env, result()); 1862 JVM_END 1863 1864 // Finds cycles of threads that are deadlocked on monitor locks 1865 // Returns an array of Thread objects which are in deadlock, if any. 1866 // Otherwise, returns NULL. 1867 JVM_ENTRY(jobjectArray, jmm_FindMonitorDeadlockedThreads(JNIEnv *env)) 1868 Handle result = find_deadlocks(true, CHECK_0); 1869 return (jobjectArray) JNIHandles::make_local(env, result()); 1870 JVM_END 1871 1872 // Gets the information about GC extension attributes including 1873 // the name of the attribute, its type, and a short description. 1874 // 1875 // Input parameters: 1876 // mgr - GC memory manager 1877 // info - caller allocated array of jmmExtAttributeInfo 1878 // count - number of elements of the info array 1879 // 1880 // Returns the number of GC extension attributes filled in the info array; or 1881 // -1 if info is not big enough 1882 // 1883 JVM_ENTRY(jint, jmm_GetGCExtAttributeInfo(JNIEnv *env, jobject mgr, jmmExtAttributeInfo* info, jint count)) 1884 // All GC memory managers have 1 attribute (number of GC threads) 1885 if (count == 0) { 1886 return 0; 1887 } 1888 1889 if (info == NULL) { 1890 THROW_(vmSymbols::java_lang_NullPointerException(), 0); 1891 } 1892 1893 info[0].name = "GcThreadCount"; 1894 info[0].type = 'I'; 1895 info[0].description = "Number of GC threads"; 1896 return 1; 1897 JVM_END 1898 1899 // verify the given array is an array of java/lang/management/MemoryUsage objects 1900 // of a given length and return the objArrayOop 1901 static objArrayOop get_memory_usage_objArray(jobjectArray array, int length, TRAPS) { 1902 if (array == NULL) { 1903 THROW_(vmSymbols::java_lang_NullPointerException(), 0); 1904 } 1905 1906 objArrayOop oa = objArrayOop(JNIHandles::resolve_non_null(array)); 1907 objArrayHandle array_h(THREAD, oa); 1908 1909 // array must be of the given length 1910 if (length != array_h->length()) { 1911 THROW_MSG_(vmSymbols::java_lang_IllegalArgumentException(), 1912 "The length of the given MemoryUsage array does not match the number of memory pools.", 0); 1913 } 1914 1915 // check if the element of array is of type MemoryUsage class 1916 Klass* usage_klass = Management::java_lang_management_MemoryUsage_klass(CHECK_0); 1917 Klass* element_klass = ObjArrayKlass::cast(array_h->klass())->element_klass(); 1918 if (element_klass != usage_klass) { 1919 THROW_MSG_(vmSymbols::java_lang_IllegalArgumentException(), 1920 "The element type is not MemoryUsage class", 0); 1921 } 1922 1923 return array_h(); 1924 } 1925 1926 // Gets the statistics of the last GC of a given GC memory manager. 1927 // Input parameters: 1928 // obj - GarbageCollectorMXBean object 1929 // gc_stat - caller allocated jmmGCStat where: 1930 // a. before_gc_usage - array of MemoryUsage objects 1931 // b. after_gc_usage - array of MemoryUsage objects 1932 // c. gc_ext_attributes_values_size is set to the 1933 // gc_ext_attribute_values array allocated 1934 // d. gc_ext_attribute_values is a caller allocated array of jvalue. 1935 // 1936 // On return, 1937 // gc_index == 0 indicates no GC statistics available 1938 // 1939 // before_gc_usage and after_gc_usage - filled with per memory pool 1940 // before and after GC usage in the same order as the memory pools 1941 // returned by GetMemoryPools for a given GC memory manager. 1942 // num_gc_ext_attributes indicates the number of elements in 1943 // the gc_ext_attribute_values array is filled; or 1944 // -1 if the gc_ext_attributes_values array is not big enough 1945 // 1946 JVM_ENTRY(void, jmm_GetLastGCStat(JNIEnv *env, jobject obj, jmmGCStat *gc_stat)) 1947 ResourceMark rm(THREAD); 1948 1949 if (gc_stat->gc_ext_attribute_values_size > 0 && gc_stat->gc_ext_attribute_values == NULL) { 1950 THROW(vmSymbols::java_lang_NullPointerException()); 1951 } 1952 1953 // Get the GCMemoryManager 1954 GCMemoryManager* mgr = get_gc_memory_manager_from_jobject(obj, CHECK); 1955 1956 // Make a copy of the last GC statistics 1957 // GC may occur while constructing the last GC information 1958 int num_pools = MemoryService::num_memory_pools(); 1959 GCStatInfo stat(num_pools); 1960 if (mgr->get_last_gc_stat(&stat) == 0) { 1961 gc_stat->gc_index = 0; 1962 return; 1963 } 1964 1965 gc_stat->gc_index = stat.gc_index(); 1966 gc_stat->start_time = Management::ticks_to_ms(stat.start_time()); 1967 gc_stat->end_time = Management::ticks_to_ms(stat.end_time()); 1968 1969 // Current implementation does not have GC extension attributes 1970 gc_stat->num_gc_ext_attributes = 0; 1971 1972 // Fill the arrays of MemoryUsage objects with before and after GC 1973 // per pool memory usage 1974 objArrayOop bu = get_memory_usage_objArray(gc_stat->usage_before_gc, 1975 num_pools, 1976 CHECK); 1977 objArrayHandle usage_before_gc_ah(THREAD, bu); 1978 1979 objArrayOop au = get_memory_usage_objArray(gc_stat->usage_after_gc, 1980 num_pools, 1981 CHECK); 1982 objArrayHandle usage_after_gc_ah(THREAD, au); 1983 1984 for (int i = 0; i < num_pools; i++) { 1985 Handle before_usage = MemoryService::create_MemoryUsage_obj(stat.before_gc_usage_for_pool(i), CHECK); 1986 Handle after_usage; 1987 1988 MemoryUsage u = stat.after_gc_usage_for_pool(i); 1989 if (u.max_size() == 0 && u.used() > 0) { 1990 // If max size == 0, this pool is a survivor space. 1991 // Set max size = -1 since the pools will be swapped after GC. 1992 MemoryUsage usage(u.init_size(), u.used(), u.committed(), (size_t)-1); 1993 after_usage = MemoryService::create_MemoryUsage_obj(usage, CHECK); 1994 } else { 1995 after_usage = MemoryService::create_MemoryUsage_obj(stat.after_gc_usage_for_pool(i), CHECK); 1996 } 1997 usage_before_gc_ah->obj_at_put(i, before_usage()); 1998 usage_after_gc_ah->obj_at_put(i, after_usage()); 1999 } 2000 2001 if (gc_stat->gc_ext_attribute_values_size > 0) { 2002 // Current implementation only has 1 attribute (number of GC threads) 2003 // The type is 'I' 2004 gc_stat->gc_ext_attribute_values[0].i = mgr->num_gc_threads(); 2005 } 2006 JVM_END 2007 2008 JVM_ENTRY(void, jmm_SetGCNotificationEnabled(JNIEnv *env, jobject obj, jboolean enabled)) 2009 ResourceMark rm(THREAD); 2010 // Get the GCMemoryManager 2011 GCMemoryManager* mgr = get_gc_memory_manager_from_jobject(obj, CHECK); 2012 mgr->set_notification_enabled(enabled?true:false); 2013 JVM_END 2014 2015 // Dump heap - Returns 0 if succeeds. 2016 JVM_ENTRY(jint, jmm_DumpHeap0(JNIEnv *env, jstring outputfile, jboolean live)) 2017 #if INCLUDE_SERVICES 2018 ResourceMark rm(THREAD); 2019 oop on = JNIHandles::resolve_external_guard(outputfile); 2020 if (on == NULL) { 2021 THROW_MSG_(vmSymbols::java_lang_NullPointerException(), 2022 "Output file name cannot be null.", -1); 2023 } 2024 char* name = java_lang_String::as_platform_dependent_str(on, CHECK_(-1)); 2025 if (name == NULL) { 2026 THROW_MSG_(vmSymbols::java_lang_NullPointerException(), 2027 "Output file name cannot be null.", -1); 2028 } 2029 HeapDumper dumper(live ? true : false); 2030 if (dumper.dump(name) != 0) { 2031 const char* errmsg = dumper.error_as_C_string(); 2032 THROW_MSG_(vmSymbols::java_io_IOException(), errmsg, -1); 2033 } 2034 return 0; 2035 #else // INCLUDE_SERVICES 2036 return -1; 2037 #endif // INCLUDE_SERVICES 2038 JVM_END 2039 2040 JVM_ENTRY(jobjectArray, jmm_GetDiagnosticCommands(JNIEnv *env)) 2041 ResourceMark rm(THREAD); 2042 GrowableArray<const char *>* dcmd_list = DCmdFactory::DCmd_list(DCmd_Source_MBean); 2043 objArrayOop cmd_array_oop = oopFactory::new_objArray(SystemDictionary::String_klass(), 2044 dcmd_list->length(), CHECK_NULL); 2045 objArrayHandle cmd_array(THREAD, cmd_array_oop); 2046 for (int i = 0; i < dcmd_list->length(); i++) { 2047 oop cmd_name = java_lang_String::create_oop_from_str(dcmd_list->at(i), CHECK_NULL); 2048 cmd_array->obj_at_put(i, cmd_name); 2049 } 2050 return (jobjectArray) JNIHandles::make_local(env, cmd_array()); 2051 JVM_END 2052 2053 JVM_ENTRY(void, jmm_GetDiagnosticCommandInfo(JNIEnv *env, jobjectArray cmds, 2054 dcmdInfo* infoArray)) 2055 if (cmds == NULL || infoArray == NULL) { 2056 THROW(vmSymbols::java_lang_NullPointerException()); 2057 } 2058 2059 ResourceMark rm(THREAD); 2060 2061 objArrayOop ca = objArrayOop(JNIHandles::resolve_non_null(cmds)); 2062 objArrayHandle cmds_ah(THREAD, ca); 2063 2064 // Make sure we have a String array 2065 Klass* element_klass = ObjArrayKlass::cast(cmds_ah->klass())->element_klass(); 2066 if (element_klass != SystemDictionary::String_klass()) { 2067 THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(), 2068 "Array element type is not String class"); 2069 } 2070 2071 GrowableArray<DCmdInfo *>* info_list = DCmdFactory::DCmdInfo_list(DCmd_Source_MBean); 2072 2073 int num_cmds = cmds_ah->length(); 2074 for (int i = 0; i < num_cmds; i++) { 2075 oop cmd = cmds_ah->obj_at(i); 2076 if (cmd == NULL) { 2077 THROW_MSG(vmSymbols::java_lang_NullPointerException(), 2078 "Command name cannot be null."); 2079 } 2080 char* cmd_name = java_lang_String::as_utf8_string(cmd); 2081 if (cmd_name == NULL) { 2082 THROW_MSG(vmSymbols::java_lang_NullPointerException(), 2083 "Command name cannot be null."); 2084 } 2085 int pos = info_list->find((void*)cmd_name,DCmdInfo::by_name); 2086 if (pos == -1) { 2087 THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(), 2088 "Unknown diagnostic command"); 2089 } 2090 DCmdInfo* info = info_list->at(pos); 2091 infoArray[i].name = info->name(); 2092 infoArray[i].description = info->description(); 2093 infoArray[i].impact = info->impact(); 2094 JavaPermission p = info->permission(); 2095 infoArray[i].permission_class = p._class; 2096 infoArray[i].permission_name = p._name; 2097 infoArray[i].permission_action = p._action; 2098 infoArray[i].num_arguments = info->num_arguments(); 2099 infoArray[i].enabled = info->is_enabled(); 2100 } 2101 JVM_END 2102 2103 JVM_ENTRY(void, jmm_GetDiagnosticCommandArgumentsInfo(JNIEnv *env, 2104 jstring command, dcmdArgInfo* infoArray)) 2105 ResourceMark rm(THREAD); 2106 oop cmd = JNIHandles::resolve_external_guard(command); 2107 if (cmd == NULL) { 2108 THROW_MSG(vmSymbols::java_lang_NullPointerException(), 2109 "Command line cannot be null."); 2110 } 2111 char* cmd_name = java_lang_String::as_utf8_string(cmd); 2112 if (cmd_name == NULL) { 2113 THROW_MSG(vmSymbols::java_lang_NullPointerException(), 2114 "Command line content cannot be null."); 2115 } 2116 DCmd* dcmd = NULL; 2117 DCmdFactory*factory = DCmdFactory::factory(DCmd_Source_MBean, cmd_name, 2118 strlen(cmd_name)); 2119 if (factory != NULL) { 2120 dcmd = factory->create_resource_instance(NULL); 2121 } 2122 if (dcmd == NULL) { 2123 THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(), 2124 "Unknown diagnostic command"); 2125 } 2126 DCmdMark mark(dcmd); 2127 GrowableArray<DCmdArgumentInfo*>* array = dcmd->argument_info_array(); 2128 if (array->length() == 0) { 2129 return; 2130 } 2131 for (int i = 0; i < array->length(); i++) { 2132 infoArray[i].name = array->at(i)->name(); 2133 infoArray[i].description = array->at(i)->description(); 2134 infoArray[i].type = array->at(i)->type(); 2135 infoArray[i].default_string = array->at(i)->default_string(); 2136 infoArray[i].mandatory = array->at(i)->is_mandatory(); 2137 infoArray[i].option = array->at(i)->is_option(); 2138 infoArray[i].multiple = array->at(i)->is_multiple(); 2139 infoArray[i].position = array->at(i)->position(); 2140 } 2141 return; 2142 JVM_END 2143 2144 JVM_ENTRY(jstring, jmm_ExecuteDiagnosticCommand(JNIEnv *env, jstring commandline)) 2145 ResourceMark rm(THREAD); 2146 oop cmd = JNIHandles::resolve_external_guard(commandline); 2147 if (cmd == NULL) { 2148 THROW_MSG_NULL(vmSymbols::java_lang_NullPointerException(), 2149 "Command line cannot be null."); 2150 } 2151 char* cmdline = java_lang_String::as_utf8_string(cmd); 2152 if (cmdline == NULL) { 2153 THROW_MSG_NULL(vmSymbols::java_lang_NullPointerException(), 2154 "Command line content cannot be null."); 2155 } 2156 bufferedStream output; 2157 DCmd::parse_and_execute(DCmd_Source_MBean, &output, cmdline, ' ', CHECK_NULL); 2158 oop result = java_lang_String::create_oop_from_str(output.as_string(), CHECK_NULL); 2159 return (jstring) JNIHandles::make_local(env, result); 2160 JVM_END 2161 2162 JVM_ENTRY(void, jmm_SetDiagnosticFrameworkNotificationEnabled(JNIEnv *env, jboolean enabled)) 2163 DCmdFactory::set_jmx_notification_enabled(enabled?true:false); 2164 JVM_END 2165 2166 jlong Management::ticks_to_ms(jlong ticks) { 2167 assert(os::elapsed_frequency() > 0, "Must be non-zero"); 2168 return (jlong)(((double)ticks / (double)os::elapsed_frequency()) 2169 * (double)1000.0); 2170 } 2171 #endif // INCLUDE_MANAGEMENT 2172 2173 // Gets an array containing the amount of memory allocated on the Java 2174 // heap for a set of threads (in bytes). Each element of the array is 2175 // the amount of memory allocated for the thread ID specified in the 2176 // corresponding entry in the given array of thread IDs; or -1 if the 2177 // thread does not exist or has terminated. 2178 JVM_ENTRY(void, jmm_GetThreadAllocatedMemory(JNIEnv *env, jlongArray ids, 2179 jlongArray sizeArray)) 2180 // Check if threads is null 2181 if (ids == NULL || sizeArray == NULL) { 2182 THROW(vmSymbols::java_lang_NullPointerException()); 2183 } 2184 2185 ResourceMark rm(THREAD); 2186 typeArrayOop ta = typeArrayOop(JNIHandles::resolve_non_null(ids)); 2187 typeArrayHandle ids_ah(THREAD, ta); 2188 2189 typeArrayOop sa = typeArrayOop(JNIHandles::resolve_non_null(sizeArray)); 2190 typeArrayHandle sizeArray_h(THREAD, sa); 2191 2192 // validate the thread id array 2193 validate_thread_id_array(ids_ah, CHECK); 2194 2195 // sizeArray must be of the same length as the given array of thread IDs 2196 int num_threads = ids_ah->length(); 2197 if (num_threads != sizeArray_h->length()) { 2198 THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(), 2199 "The length of the given long array does not match the length of " 2200 "the given array of thread IDs"); 2201 } 2202 2203 MutexLockerEx ml(Threads_lock); 2204 for (int i = 0; i < num_threads; i++) { 2205 JavaThread* java_thread = Threads::find_java_thread_from_java_tid(ids_ah->long_at(i)); 2206 if (java_thread != NULL) { 2207 sizeArray_h->long_at_put(i, java_thread->cooked_allocated_bytes()); 2208 } 2209 } 2210 JVM_END 2211 2212 // Returns the CPU time consumed by a given thread (in nanoseconds). 2213 // If thread_id == 0, CPU time for the current thread is returned. 2214 // If user_sys_cpu_time = true, user level and system CPU time of 2215 // a given thread is returned; otherwise, only user level CPU time 2216 // is returned. 2217 JVM_ENTRY(jlong, jmm_GetThreadCpuTimeWithKind(JNIEnv *env, jlong thread_id, jboolean user_sys_cpu_time)) 2218 if (!os::is_thread_cpu_time_supported()) { 2219 return -1; 2220 } 2221 2222 if (thread_id < 0) { 2223 THROW_MSG_(vmSymbols::java_lang_IllegalArgumentException(), 2224 "Invalid thread ID", -1); 2225 } 2226 2227 JavaThread* java_thread = NULL; 2228 if (thread_id == 0) { 2229 // current thread 2230 return os::current_thread_cpu_time(user_sys_cpu_time != 0); 2231 } else { 2232 MutexLockerEx ml(Threads_lock); 2233 java_thread = Threads::find_java_thread_from_java_tid(thread_id); 2234 if (java_thread != NULL) { 2235 return os::thread_cpu_time((Thread*) java_thread, user_sys_cpu_time != 0); 2236 } 2237 } 2238 return -1; 2239 JVM_END 2240 2241 // Gets an array containing the CPU times consumed by a set of threads 2242 // (in nanoseconds). Each element of the array is the CPU time for the 2243 // thread ID specified in the corresponding entry in the given array 2244 // of thread IDs; or -1 if the thread does not exist or has terminated. 2245 // If user_sys_cpu_time = true, the sum of user level and system CPU time 2246 // for the given thread is returned; otherwise, only user level CPU time 2247 // is returned. 2248 JVM_ENTRY(void, jmm_GetThreadCpuTimesWithKind(JNIEnv *env, jlongArray ids, 2249 jlongArray timeArray, 2250 jboolean user_sys_cpu_time)) 2251 // Check if threads is null 2252 if (ids == NULL || timeArray == NULL) { 2253 THROW(vmSymbols::java_lang_NullPointerException()); 2254 } 2255 2256 ResourceMark rm(THREAD); 2257 typeArrayOop ta = typeArrayOop(JNIHandles::resolve_non_null(ids)); 2258 typeArrayHandle ids_ah(THREAD, ta); 2259 2260 typeArrayOop tia = typeArrayOop(JNIHandles::resolve_non_null(timeArray)); 2261 typeArrayHandle timeArray_h(THREAD, tia); 2262 2263 // validate the thread id array 2264 validate_thread_id_array(ids_ah, CHECK); 2265 2266 // timeArray must be of the same length as the given array of thread IDs 2267 int num_threads = ids_ah->length(); 2268 if (num_threads != timeArray_h->length()) { 2269 THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(), 2270 "The length of the given long array does not match the length of " 2271 "the given array of thread IDs"); 2272 } 2273 2274 MutexLockerEx ml(Threads_lock); 2275 for (int i = 0; i < num_threads; i++) { 2276 JavaThread* java_thread = Threads::find_java_thread_from_java_tid(ids_ah->long_at(i)); 2277 if (java_thread != NULL) { 2278 timeArray_h->long_at_put(i, os::thread_cpu_time((Thread*)java_thread, 2279 user_sys_cpu_time != 0)); 2280 } 2281 } 2282 JVM_END 2283 2284 2285 2286 #if INCLUDE_MANAGEMENT 2287 const struct jmmInterface_1_ jmm_interface = { 2288 NULL, 2289 NULL, 2290 jmm_GetVersion, 2291 jmm_GetOptionalSupport, 2292 jmm_GetInputArguments, 2293 jmm_GetThreadInfo, 2294 jmm_GetInputArgumentArray, 2295 jmm_GetMemoryPools, 2296 jmm_GetMemoryManagers, 2297 jmm_GetMemoryPoolUsage, 2298 jmm_GetPeakMemoryPoolUsage, 2299 jmm_GetThreadAllocatedMemory, 2300 jmm_GetMemoryUsage, 2301 jmm_GetLongAttribute, 2302 jmm_GetBoolAttribute, 2303 jmm_SetBoolAttribute, 2304 jmm_GetLongAttributes, 2305 jmm_FindMonitorDeadlockedThreads, 2306 jmm_GetThreadCpuTime, 2307 jmm_GetVMGlobalNames, 2308 jmm_GetVMGlobals, 2309 jmm_GetInternalThreadTimes, 2310 jmm_ResetStatistic, 2311 jmm_SetPoolSensor, 2312 jmm_SetPoolThreshold, 2313 jmm_GetPoolCollectionUsage, 2314 jmm_GetGCExtAttributeInfo, 2315 jmm_GetLastGCStat, 2316 jmm_GetThreadCpuTimeWithKind, 2317 jmm_GetThreadCpuTimesWithKind, 2318 jmm_DumpHeap0, 2319 jmm_FindDeadlockedThreads, 2320 jmm_SetVMGlobal, 2321 NULL, 2322 jmm_DumpThreads, 2323 jmm_SetGCNotificationEnabled, 2324 jmm_GetDiagnosticCommands, 2325 jmm_GetDiagnosticCommandInfo, 2326 jmm_GetDiagnosticCommandArgumentsInfo, 2327 jmm_ExecuteDiagnosticCommand, 2328 jmm_SetDiagnosticFrameworkNotificationEnabled 2329 }; 2330 #endif // INCLUDE_MANAGEMENT 2331 2332 void* Management::get_jmm_interface(int version) { 2333 #if INCLUDE_MANAGEMENT 2334 if (version == JMM_VERSION_1_0) { 2335 return (void*) &jmm_interface; 2336 } 2337 #endif // INCLUDE_MANAGEMENT 2338 return NULL; 2339 }