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