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