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