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