duke@435: /* phh@2423: * Copyright (c) 2003, 2011, Oracle and/or its affiliates. All rights reserved. duke@435: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. duke@435: * duke@435: * This code is free software; you can redistribute it and/or modify it duke@435: * under the terms of the GNU General Public License version 2 only, as duke@435: * published by the Free Software Foundation. duke@435: * duke@435: * This code is distributed in the hope that it will be useful, but WITHOUT duke@435: * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or duke@435: * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License duke@435: * version 2 for more details (a copy is included in the LICENSE file that duke@435: * accompanied this code). duke@435: * duke@435: * You should have received a copy of the GNU General Public License version duke@435: * 2 along with this work; if not, write to the Free Software Foundation, duke@435: * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. duke@435: * trims@1907: * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA trims@1907: * or visit www.oracle.com if you need additional information or have any trims@1907: * questions. duke@435: * duke@435: */ duke@435: stefank@2314: #include "precompiled.hpp" stefank@2314: #include "classfile/systemDictionary.hpp" stefank@2314: #include "compiler/compileBroker.hpp" stefank@2314: #include "memory/iterator.hpp" stefank@2314: #include "memory/oopFactory.hpp" stefank@2314: #include "memory/resourceArea.hpp" stefank@2314: #include "oops/klass.hpp" stefank@2314: #include "oops/klassOop.hpp" stefank@2314: #include "oops/objArrayKlass.hpp" stefank@2314: #include "oops/oop.inline.hpp" stefank@2314: #include "runtime/arguments.hpp" phh@3342: #include "runtime/globals.hpp" stefank@2314: #include "runtime/handles.inline.hpp" stefank@2314: #include "runtime/interfaceSupport.hpp" stefank@2314: #include "runtime/javaCalls.hpp" stefank@2314: #include "runtime/jniHandles.hpp" stefank@2314: #include "runtime/os.hpp" kamg@2511: #include "runtime/serviceThread.hpp" stefank@2314: #include "services/classLoadingService.hpp" fparain@3329: #include "services/diagnosticCommand.hpp" fparain@3329: #include "services/diagnosticFramework.hpp" stefank@2314: #include "services/heapDumper.hpp" fparain@3329: #include "services/jmm.h" stefank@2314: #include "services/lowMemoryDetector.hpp" fparain@2888: #include "services/gcNotifier.hpp" stefank@2314: #include "services/management.hpp" stefank@2314: #include "services/memoryManager.hpp" stefank@2314: #include "services/memoryPool.hpp" stefank@2314: #include "services/memoryService.hpp" stefank@2314: #include "services/runtimeService.hpp" stefank@2314: #include "services/threadService.hpp" duke@435: duke@435: PerfVariable* Management::_begin_vm_creation_time = NULL; duke@435: PerfVariable* Management::_end_vm_creation_time = NULL; duke@435: PerfVariable* Management::_vm_init_done_time = NULL; duke@435: duke@435: klassOop Management::_sensor_klass = NULL; duke@435: klassOop Management::_threadInfo_klass = NULL; duke@435: klassOop Management::_memoryUsage_klass = NULL; duke@435: klassOop Management::_memoryPoolMXBean_klass = NULL; duke@435: klassOop Management::_memoryManagerMXBean_klass = NULL; duke@435: klassOop Management::_garbageCollectorMXBean_klass = NULL; duke@435: klassOop Management::_managementFactory_klass = NULL; fparain@2888: klassOop Management::_garbageCollectorImpl_klass = NULL; fparain@2888: klassOop Management::_gcInfo_klass = NULL; duke@435: duke@435: jmmOptionalSupport Management::_optional_support = {0}; duke@435: TimeStamp Management::_stamp; duke@435: duke@435: void management_init() { duke@435: Management::init(); duke@435: ThreadService::init(); duke@435: RuntimeService::init(); duke@435: ClassLoadingService::init(); duke@435: } duke@435: duke@435: void Management::init() { duke@435: EXCEPTION_MARK; duke@435: duke@435: // These counters are for java.lang.management API support. duke@435: // They are created even if -XX:-UsePerfData is set and in duke@435: // that case, they will be allocated on C heap. duke@435: duke@435: _begin_vm_creation_time = duke@435: PerfDataManager::create_variable(SUN_RT, "createVmBeginTime", duke@435: PerfData::U_None, CHECK); duke@435: duke@435: _end_vm_creation_time = duke@435: PerfDataManager::create_variable(SUN_RT, "createVmEndTime", duke@435: PerfData::U_None, CHECK); duke@435: duke@435: _vm_init_done_time = duke@435: PerfDataManager::create_variable(SUN_RT, "vmInitDoneTime", duke@435: PerfData::U_None, CHECK); duke@435: duke@435: // Initialize optional support duke@435: _optional_support.isLowMemoryDetectionSupported = 1; duke@435: _optional_support.isCompilationTimeMonitoringSupported = 1; duke@435: _optional_support.isThreadContentionMonitoringSupported = 1; duke@435: duke@435: if (os::is_thread_cpu_time_supported()) { duke@435: _optional_support.isCurrentThreadCpuTimeSupported = 1; duke@435: _optional_support.isOtherThreadCpuTimeSupported = 1; duke@435: } else { duke@435: _optional_support.isCurrentThreadCpuTimeSupported = 0; duke@435: _optional_support.isOtherThreadCpuTimeSupported = 0; duke@435: } phh@2423: duke@435: _optional_support.isBootClassPathSupported = 1; duke@435: _optional_support.isObjectMonitorUsageSupported = 1; duke@435: #ifndef SERVICES_KERNEL duke@435: // This depends on the heap inspector duke@435: _optional_support.isSynchronizerUsageSupported = 1; duke@435: #endif // SERVICES_KERNEL phh@2423: _optional_support.isThreadAllocatedMemorySupported = 1; fparain@3329: fparain@3402: // Registration of the diagnostic commands fparain@3402: // First boolean argument specifies if the command is enabled fparain@3402: // Second boolean argument specifies if the command is hidden fparain@3329: DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl(true, false)); fparain@3329: DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl(true, false)); fparain@3402: DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl(true, false)); fparain@3402: DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl(true, false)); fparain@3402: DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl(true, false)); fparain@3402: DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl(true, false)); fparain@3402: DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl(true, false)); fparain@3402: DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl(true, false)); fparain@3402: #ifndef SERVICES_KERNEL // Heap dumping not supported fparain@3402: DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl(true, false)); fparain@3402: #endif // SERVICES_KERNEL fparain@3402: DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl(true, false)); fparain@3402: DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl(true, false)); duke@435: } duke@435: duke@435: void Management::initialize(TRAPS) { kamg@2511: // Start the service thread kamg@2511: ServiceThread::initialize(); duke@435: duke@435: if (ManagementServer) { duke@435: ResourceMark rm(THREAD); duke@435: HandleMark hm(THREAD); duke@435: duke@435: // Load and initialize the sun.management.Agent class duke@435: // invoke startAgent method to start the management server duke@435: Handle loader = Handle(THREAD, SystemDictionary::java_system_loader()); coleenp@2497: klassOop k = SystemDictionary::resolve_or_fail(vmSymbols::sun_management_Agent(), duke@435: loader, duke@435: Handle(), duke@435: true, duke@435: CHECK); duke@435: instanceKlassHandle ik (THREAD, k); duke@435: duke@435: JavaValue result(T_VOID); duke@435: JavaCalls::call_static(&result, duke@435: ik, coleenp@2497: vmSymbols::startAgent_name(), coleenp@2497: vmSymbols::void_method_signature(), duke@435: CHECK); duke@435: } duke@435: } duke@435: duke@435: void Management::get_optional_support(jmmOptionalSupport* support) { duke@435: memcpy(support, &_optional_support, sizeof(jmmOptionalSupport)); duke@435: } duke@435: coleenp@2497: klassOop Management::load_and_initialize_klass(Symbol* sh, TRAPS) { duke@435: klassOop k = SystemDictionary::resolve_or_fail(sh, true, CHECK_NULL); duke@435: instanceKlassHandle ik (THREAD, k); duke@435: if (ik->should_be_initialized()) { duke@435: ik->initialize(CHECK_NULL); duke@435: } duke@435: return ik(); duke@435: } duke@435: duke@435: void Management::record_vm_startup_time(jlong begin, jlong duration) { duke@435: // if the performance counter is not initialized, duke@435: // then vm initialization failed; simply return. duke@435: if (_begin_vm_creation_time == NULL) return; duke@435: duke@435: _begin_vm_creation_time->set_value(begin); duke@435: _end_vm_creation_time->set_value(begin + duration); duke@435: PerfMemory::set_accessible(true); duke@435: } duke@435: duke@435: jlong Management::timestamp() { duke@435: TimeStamp t; duke@435: t.update(); duke@435: return t.ticks() - _stamp.ticks(); duke@435: } duke@435: duke@435: void Management::oops_do(OopClosure* f) { duke@435: MemoryService::oops_do(f); duke@435: ThreadService::oops_do(f); duke@435: duke@435: f->do_oop((oop*) &_sensor_klass); duke@435: f->do_oop((oop*) &_threadInfo_klass); duke@435: f->do_oop((oop*) &_memoryUsage_klass); duke@435: f->do_oop((oop*) &_memoryPoolMXBean_klass); duke@435: f->do_oop((oop*) &_memoryManagerMXBean_klass); duke@435: f->do_oop((oop*) &_garbageCollectorMXBean_klass); duke@435: f->do_oop((oop*) &_managementFactory_klass); fparain@2888: f->do_oop((oop*) &_garbageCollectorImpl_klass); fparain@2888: f->do_oop((oop*) &_gcInfo_klass); duke@435: } duke@435: duke@435: klassOop Management::java_lang_management_ThreadInfo_klass(TRAPS) { duke@435: if (_threadInfo_klass == NULL) { coleenp@2497: _threadInfo_klass = load_and_initialize_klass(vmSymbols::java_lang_management_ThreadInfo(), CHECK_NULL); duke@435: } duke@435: return _threadInfo_klass; duke@435: } duke@435: duke@435: klassOop Management::java_lang_management_MemoryUsage_klass(TRAPS) { duke@435: if (_memoryUsage_klass == NULL) { coleenp@2497: _memoryUsage_klass = load_and_initialize_klass(vmSymbols::java_lang_management_MemoryUsage(), CHECK_NULL); duke@435: } duke@435: return _memoryUsage_klass; duke@435: } duke@435: duke@435: klassOop Management::java_lang_management_MemoryPoolMXBean_klass(TRAPS) { duke@435: if (_memoryPoolMXBean_klass == NULL) { coleenp@2497: _memoryPoolMXBean_klass = load_and_initialize_klass(vmSymbols::java_lang_management_MemoryPoolMXBean(), CHECK_NULL); duke@435: } duke@435: return _memoryPoolMXBean_klass; duke@435: } duke@435: duke@435: klassOop Management::java_lang_management_MemoryManagerMXBean_klass(TRAPS) { duke@435: if (_memoryManagerMXBean_klass == NULL) { coleenp@2497: _memoryManagerMXBean_klass = load_and_initialize_klass(vmSymbols::java_lang_management_MemoryManagerMXBean(), CHECK_NULL); duke@435: } duke@435: return _memoryManagerMXBean_klass; duke@435: } duke@435: duke@435: klassOop Management::java_lang_management_GarbageCollectorMXBean_klass(TRAPS) { duke@435: if (_garbageCollectorMXBean_klass == NULL) { coleenp@2497: _garbageCollectorMXBean_klass = load_and_initialize_klass(vmSymbols::java_lang_management_GarbageCollectorMXBean(), CHECK_NULL); duke@435: } duke@435: return _garbageCollectorMXBean_klass; duke@435: } duke@435: duke@435: klassOop Management::sun_management_Sensor_klass(TRAPS) { duke@435: if (_sensor_klass == NULL) { coleenp@2497: _sensor_klass = load_and_initialize_klass(vmSymbols::sun_management_Sensor(), CHECK_NULL); duke@435: } duke@435: return _sensor_klass; duke@435: } duke@435: duke@435: klassOop Management::sun_management_ManagementFactory_klass(TRAPS) { duke@435: if (_managementFactory_klass == NULL) { coleenp@2497: _managementFactory_klass = load_and_initialize_klass(vmSymbols::sun_management_ManagementFactory(), CHECK_NULL); duke@435: } duke@435: return _managementFactory_klass; duke@435: } duke@435: fparain@2888: klassOop Management::sun_management_GarbageCollectorImpl_klass(TRAPS) { fparain@2888: if (_garbageCollectorImpl_klass == NULL) { fparain@2888: _garbageCollectorImpl_klass = load_and_initialize_klass(vmSymbols::sun_management_GarbageCollectorImpl(), CHECK_NULL); fparain@2888: } fparain@2888: return _garbageCollectorImpl_klass; fparain@2888: } fparain@2888: fparain@2888: klassOop Management::com_sun_management_GcInfo_klass(TRAPS) { fparain@2888: if (_gcInfo_klass == NULL) { fparain@2888: _gcInfo_klass = load_and_initialize_klass(vmSymbols::com_sun_management_GcInfo(), CHECK_NULL); fparain@2888: } fparain@2888: return _gcInfo_klass; fparain@2888: } fparain@2888: duke@435: static void initialize_ThreadInfo_constructor_arguments(JavaCallArguments* args, ThreadSnapshot* snapshot, TRAPS) { duke@435: Handle snapshot_thread(THREAD, snapshot->threadObj()); duke@435: duke@435: jlong contended_time; duke@435: jlong waited_time; duke@435: if (ThreadService::is_thread_monitoring_contention()) { duke@435: contended_time = Management::ticks_to_ms(snapshot->contended_enter_ticks()); duke@435: waited_time = Management::ticks_to_ms(snapshot->monitor_wait_ticks() + snapshot->sleep_ticks()); duke@435: } else { duke@435: // set them to -1 if thread contention monitoring is disabled. duke@435: contended_time = max_julong; duke@435: waited_time = max_julong; duke@435: } duke@435: duke@435: int thread_status = snapshot->thread_status(); duke@435: assert((thread_status & JMM_THREAD_STATE_FLAG_MASK) == 0, "Flags already set in thread_status in Thread object"); duke@435: if (snapshot->is_ext_suspended()) { duke@435: thread_status |= JMM_THREAD_STATE_FLAG_SUSPENDED; duke@435: } duke@435: if (snapshot->is_in_native()) { duke@435: thread_status |= JMM_THREAD_STATE_FLAG_NATIVE; duke@435: } duke@435: duke@435: ThreadStackTrace* st = snapshot->get_stack_trace(); duke@435: Handle stacktrace_h; duke@435: if (st != NULL) { duke@435: stacktrace_h = st->allocate_fill_stack_trace_element_array(CHECK); duke@435: } else { duke@435: stacktrace_h = Handle(); duke@435: } duke@435: duke@435: args->push_oop(snapshot_thread); duke@435: args->push_int(thread_status); duke@435: args->push_oop(Handle(THREAD, snapshot->blocker_object())); duke@435: args->push_oop(Handle(THREAD, snapshot->blocker_object_owner())); duke@435: args->push_long(snapshot->contended_enter_count()); duke@435: args->push_long(contended_time); duke@435: args->push_long(snapshot->monitor_wait_count() + snapshot->sleep_count()); duke@435: args->push_long(waited_time); duke@435: args->push_oop(stacktrace_h); duke@435: } duke@435: duke@435: // Helper function to construct a ThreadInfo object duke@435: instanceOop Management::create_thread_info_instance(ThreadSnapshot* snapshot, TRAPS) { duke@435: klassOop k = Management::java_lang_management_ThreadInfo_klass(CHECK_NULL); duke@435: instanceKlassHandle ik (THREAD, k); duke@435: duke@435: JavaValue result(T_VOID); duke@435: JavaCallArguments args(14); duke@435: duke@435: // First allocate a ThreadObj object and duke@435: // push the receiver as the first argument duke@435: Handle element = ik->allocate_instance_handle(CHECK_NULL); duke@435: args.push_oop(element); duke@435: duke@435: // initialize the arguments for the ThreadInfo constructor duke@435: initialize_ThreadInfo_constructor_arguments(&args, snapshot, CHECK_NULL); duke@435: duke@435: // Call ThreadInfo constructor with no locked monitors and synchronizers duke@435: JavaCalls::call_special(&result, duke@435: ik, coleenp@2497: vmSymbols::object_initializer_name(), coleenp@2497: vmSymbols::java_lang_management_ThreadInfo_constructor_signature(), duke@435: &args, duke@435: CHECK_NULL); duke@435: duke@435: return (instanceOop) element(); duke@435: } duke@435: duke@435: instanceOop Management::create_thread_info_instance(ThreadSnapshot* snapshot, duke@435: objArrayHandle monitors_array, duke@435: typeArrayHandle depths_array, duke@435: objArrayHandle synchronizers_array, duke@435: TRAPS) { duke@435: klassOop k = Management::java_lang_management_ThreadInfo_klass(CHECK_NULL); duke@435: instanceKlassHandle ik (THREAD, k); duke@435: duke@435: JavaValue result(T_VOID); duke@435: JavaCallArguments args(17); duke@435: duke@435: // First allocate a ThreadObj object and duke@435: // push the receiver as the first argument duke@435: Handle element = ik->allocate_instance_handle(CHECK_NULL); duke@435: args.push_oop(element); duke@435: duke@435: // initialize the arguments for the ThreadInfo constructor duke@435: initialize_ThreadInfo_constructor_arguments(&args, snapshot, CHECK_NULL); duke@435: duke@435: // push the locked monitors and synchronizers in the arguments duke@435: args.push_oop(monitors_array); duke@435: args.push_oop(depths_array); duke@435: args.push_oop(synchronizers_array); duke@435: duke@435: // Call ThreadInfo constructor with locked monitors and synchronizers duke@435: JavaCalls::call_special(&result, duke@435: ik, coleenp@2497: vmSymbols::object_initializer_name(), coleenp@2497: vmSymbols::java_lang_management_ThreadInfo_with_locks_constructor_signature(), duke@435: &args, duke@435: CHECK_NULL); duke@435: duke@435: return (instanceOop) element(); duke@435: } duke@435: duke@435: // Helper functions duke@435: static JavaThread* find_java_thread_from_id(jlong thread_id) { duke@435: assert(Threads_lock->owned_by_self(), "Must hold Threads_lock"); duke@435: duke@435: JavaThread* java_thread = NULL; duke@435: // Sequential search for now. Need to do better optimization later. duke@435: for (JavaThread* thread = Threads::first(); thread != NULL; thread = thread->next()) { duke@435: oop tobj = thread->threadObj(); duke@435: if (!thread->is_exiting() && duke@435: tobj != NULL && duke@435: thread_id == java_lang_Thread::thread_id(tobj)) { duke@435: java_thread = thread; duke@435: break; duke@435: } duke@435: } duke@435: return java_thread; duke@435: } duke@435: duke@435: static GCMemoryManager* get_gc_memory_manager_from_jobject(jobject mgr, TRAPS) { duke@435: if (mgr == NULL) { duke@435: THROW_(vmSymbols::java_lang_NullPointerException(), NULL); duke@435: } duke@435: oop mgr_obj = JNIHandles::resolve(mgr); duke@435: instanceHandle h(THREAD, (instanceOop) mgr_obj); duke@435: duke@435: klassOop k = Management::java_lang_management_GarbageCollectorMXBean_klass(CHECK_NULL); duke@435: if (!h->is_a(k)) { duke@435: THROW_MSG_(vmSymbols::java_lang_IllegalArgumentException(), duke@435: "the object is not an instance of java.lang.management.GarbageCollectorMXBean class", duke@435: NULL); duke@435: } duke@435: duke@435: MemoryManager* gc = MemoryService::get_memory_manager(h); duke@435: if (gc == NULL || !gc->is_gc_memory_manager()) { duke@435: THROW_MSG_(vmSymbols::java_lang_IllegalArgumentException(), duke@435: "Invalid GC memory manager", duke@435: NULL); duke@435: } duke@435: return (GCMemoryManager*) gc; duke@435: } duke@435: duke@435: static MemoryPool* get_memory_pool_from_jobject(jobject obj, TRAPS) { duke@435: if (obj == NULL) { duke@435: THROW_(vmSymbols::java_lang_NullPointerException(), NULL); duke@435: } duke@435: duke@435: oop pool_obj = JNIHandles::resolve(obj); duke@435: assert(pool_obj->is_instance(), "Should be an instanceOop"); duke@435: instanceHandle ph(THREAD, (instanceOop) pool_obj); duke@435: duke@435: return MemoryService::get_memory_pool(ph); duke@435: } duke@435: duke@435: static void validate_thread_id_array(typeArrayHandle ids_ah, TRAPS) { duke@435: int num_threads = ids_ah->length(); duke@435: duke@435: // Validate input thread IDs duke@435: int i = 0; duke@435: for (i = 0; i < num_threads; i++) { duke@435: jlong tid = ids_ah->long_at(i); duke@435: if (tid <= 0) { duke@435: // throw exception if invalid thread id. duke@435: THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(), duke@435: "Invalid thread ID entry"); duke@435: } duke@435: } duke@435: } duke@435: duke@435: static void validate_thread_info_array(objArrayHandle infoArray_h, TRAPS) { duke@435: // check if the element of infoArray is of type ThreadInfo class duke@435: klassOop threadinfo_klass = Management::java_lang_management_ThreadInfo_klass(CHECK); duke@435: klassOop element_klass = objArrayKlass::cast(infoArray_h->klass())->element_klass(); duke@435: if (element_klass != threadinfo_klass) { duke@435: THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(), duke@435: "infoArray element type is not ThreadInfo class"); duke@435: } duke@435: } duke@435: duke@435: duke@435: static MemoryManager* get_memory_manager_from_jobject(jobject obj, TRAPS) { duke@435: if (obj == NULL) { duke@435: THROW_(vmSymbols::java_lang_NullPointerException(), NULL); duke@435: } duke@435: duke@435: oop mgr_obj = JNIHandles::resolve(obj); duke@435: assert(mgr_obj->is_instance(), "Should be an instanceOop"); duke@435: instanceHandle mh(THREAD, (instanceOop) mgr_obj); duke@435: duke@435: return MemoryService::get_memory_manager(mh); duke@435: } duke@435: duke@435: // Returns a version string and sets major and minor version if duke@435: // the input parameters are non-null. duke@435: JVM_LEAF(jint, jmm_GetVersion(JNIEnv *env)) duke@435: return JMM_VERSION; duke@435: JVM_END duke@435: duke@435: // Gets the list of VM monitoring and management optional supports duke@435: // Returns 0 if succeeded; otherwise returns non-zero. duke@435: JVM_LEAF(jint, jmm_GetOptionalSupport(JNIEnv *env, jmmOptionalSupport* support)) duke@435: if (support == NULL) { duke@435: return -1; duke@435: } duke@435: Management::get_optional_support(support); duke@435: return 0; duke@435: JVM_END duke@435: duke@435: // Returns a java.lang.String object containing the input arguments to the VM. duke@435: JVM_ENTRY(jobject, jmm_GetInputArguments(JNIEnv *env)) duke@435: ResourceMark rm(THREAD); duke@435: duke@435: if (Arguments::num_jvm_args() == 0 && Arguments::num_jvm_flags() == 0) { duke@435: return NULL; duke@435: } duke@435: duke@435: char** vm_flags = Arguments::jvm_flags_array(); duke@435: char** vm_args = Arguments::jvm_args_array(); duke@435: int num_flags = Arguments::num_jvm_flags(); duke@435: int num_args = Arguments::num_jvm_args(); duke@435: duke@435: size_t length = 1; // null terminator duke@435: int i; duke@435: for (i = 0; i < num_flags; i++) { duke@435: length += strlen(vm_flags[i]); duke@435: } duke@435: for (i = 0; i < num_args; i++) { duke@435: length += strlen(vm_args[i]); duke@435: } duke@435: // add a space between each argument duke@435: length += num_flags + num_args - 1; duke@435: duke@435: // Return the list of input arguments passed to the VM duke@435: // and preserve the order that the VM processes. duke@435: char* args = NEW_RESOURCE_ARRAY(char, length); duke@435: args[0] = '\0'; duke@435: // concatenate all jvm_flags duke@435: if (num_flags > 0) { duke@435: strcat(args, vm_flags[0]); duke@435: for (i = 1; i < num_flags; i++) { duke@435: strcat(args, " "); duke@435: strcat(args, vm_flags[i]); duke@435: } duke@435: } duke@435: duke@435: if (num_args > 0 && num_flags > 0) { duke@435: // append a space if args already contains one or more jvm_flags duke@435: strcat(args, " "); duke@435: } duke@435: duke@435: // concatenate all jvm_args duke@435: if (num_args > 0) { duke@435: strcat(args, vm_args[0]); duke@435: for (i = 1; i < num_args; i++) { duke@435: strcat(args, " "); duke@435: strcat(args, vm_args[i]); duke@435: } duke@435: } duke@435: duke@435: Handle hargs = java_lang_String::create_from_platform_dependent_str(args, CHECK_NULL); duke@435: return JNIHandles::make_local(env, hargs()); duke@435: JVM_END duke@435: duke@435: // Returns an array of java.lang.String object containing the input arguments to the VM. duke@435: JVM_ENTRY(jobjectArray, jmm_GetInputArgumentArray(JNIEnv *env)) duke@435: ResourceMark rm(THREAD); duke@435: duke@435: if (Arguments::num_jvm_args() == 0 && Arguments::num_jvm_flags() == 0) { duke@435: return NULL; duke@435: } duke@435: duke@435: char** vm_flags = Arguments::jvm_flags_array(); duke@435: char** vm_args = Arguments::jvm_args_array(); duke@435: int num_flags = Arguments::num_jvm_flags(); duke@435: int num_args = Arguments::num_jvm_args(); duke@435: never@1577: instanceKlassHandle ik (THREAD, SystemDictionary::String_klass()); duke@435: objArrayOop r = oopFactory::new_objArray(ik(), num_args + num_flags, CHECK_NULL); duke@435: objArrayHandle result_h(THREAD, r); duke@435: duke@435: int index = 0; duke@435: for (int j = 0; j < num_flags; j++, index++) { duke@435: Handle h = java_lang_String::create_from_platform_dependent_str(vm_flags[j], CHECK_NULL); duke@435: result_h->obj_at_put(index, h()); duke@435: } duke@435: for (int i = 0; i < num_args; i++, index++) { duke@435: Handle h = java_lang_String::create_from_platform_dependent_str(vm_args[i], CHECK_NULL); duke@435: result_h->obj_at_put(index, h()); duke@435: } duke@435: return (jobjectArray) JNIHandles::make_local(env, result_h()); duke@435: JVM_END duke@435: duke@435: // Returns an array of java/lang/management/MemoryPoolMXBean object duke@435: // one for each memory pool if obj == null; otherwise returns duke@435: // an array of memory pools for a given memory manager if duke@435: // it is a valid memory manager. duke@435: JVM_ENTRY(jobjectArray, jmm_GetMemoryPools(JNIEnv* env, jobject obj)) duke@435: ResourceMark rm(THREAD); duke@435: duke@435: int num_memory_pools; duke@435: MemoryManager* mgr = NULL; duke@435: if (obj == NULL) { duke@435: num_memory_pools = MemoryService::num_memory_pools(); duke@435: } else { duke@435: mgr = get_memory_manager_from_jobject(obj, CHECK_NULL); duke@435: if (mgr == NULL) { duke@435: return NULL; duke@435: } duke@435: num_memory_pools = mgr->num_memory_pools(); duke@435: } duke@435: duke@435: // Allocate the resulting MemoryPoolMXBean[] object duke@435: klassOop k = Management::java_lang_management_MemoryPoolMXBean_klass(CHECK_NULL); duke@435: instanceKlassHandle ik (THREAD, k); duke@435: objArrayOop r = oopFactory::new_objArray(ik(), num_memory_pools, CHECK_NULL); duke@435: objArrayHandle poolArray(THREAD, r); duke@435: duke@435: if (mgr == NULL) { duke@435: // Get all memory pools duke@435: for (int i = 0; i < num_memory_pools; i++) { duke@435: MemoryPool* pool = MemoryService::get_memory_pool(i); duke@435: instanceOop p = pool->get_memory_pool_instance(CHECK_NULL); duke@435: instanceHandle ph(THREAD, p); duke@435: poolArray->obj_at_put(i, ph()); duke@435: } duke@435: } else { duke@435: // Get memory pools managed by a given memory manager duke@435: for (int i = 0; i < num_memory_pools; i++) { duke@435: MemoryPool* pool = mgr->get_memory_pool(i); duke@435: instanceOop p = pool->get_memory_pool_instance(CHECK_NULL); duke@435: instanceHandle ph(THREAD, p); duke@435: poolArray->obj_at_put(i, ph()); duke@435: } duke@435: } duke@435: return (jobjectArray) JNIHandles::make_local(env, poolArray()); duke@435: JVM_END duke@435: duke@435: // Returns an array of java/lang/management/MemoryManagerMXBean object duke@435: // one for each memory manager if obj == null; otherwise returns duke@435: // an array of memory managers for a given memory pool if duke@435: // it is a valid memory pool. duke@435: JVM_ENTRY(jobjectArray, jmm_GetMemoryManagers(JNIEnv* env, jobject obj)) duke@435: ResourceMark rm(THREAD); duke@435: duke@435: int num_mgrs; duke@435: MemoryPool* pool = NULL; duke@435: if (obj == NULL) { duke@435: num_mgrs = MemoryService::num_memory_managers(); duke@435: } else { duke@435: pool = get_memory_pool_from_jobject(obj, CHECK_NULL); duke@435: if (pool == NULL) { duke@435: return NULL; duke@435: } duke@435: num_mgrs = pool->num_memory_managers(); duke@435: } duke@435: duke@435: // Allocate the resulting MemoryManagerMXBean[] object duke@435: klassOop k = Management::java_lang_management_MemoryManagerMXBean_klass(CHECK_NULL); duke@435: instanceKlassHandle ik (THREAD, k); duke@435: objArrayOop r = oopFactory::new_objArray(ik(), num_mgrs, CHECK_NULL); duke@435: objArrayHandle mgrArray(THREAD, r); duke@435: duke@435: if (pool == NULL) { duke@435: // Get all memory managers duke@435: for (int i = 0; i < num_mgrs; i++) { duke@435: MemoryManager* mgr = MemoryService::get_memory_manager(i); duke@435: instanceOop p = mgr->get_memory_manager_instance(CHECK_NULL); duke@435: instanceHandle ph(THREAD, p); duke@435: mgrArray->obj_at_put(i, ph()); duke@435: } duke@435: } else { duke@435: // Get memory managers for a given memory pool duke@435: for (int i = 0; i < num_mgrs; i++) { duke@435: MemoryManager* mgr = pool->get_memory_manager(i); duke@435: instanceOop p = mgr->get_memory_manager_instance(CHECK_NULL); duke@435: instanceHandle ph(THREAD, p); duke@435: mgrArray->obj_at_put(i, ph()); duke@435: } duke@435: } duke@435: return (jobjectArray) JNIHandles::make_local(env, mgrArray()); duke@435: JVM_END duke@435: duke@435: duke@435: // Returns a java/lang/management/MemoryUsage object containing the memory usage duke@435: // of a given memory pool. duke@435: JVM_ENTRY(jobject, jmm_GetMemoryPoolUsage(JNIEnv* env, jobject obj)) duke@435: ResourceMark rm(THREAD); duke@435: duke@435: MemoryPool* pool = get_memory_pool_from_jobject(obj, CHECK_NULL); duke@435: if (pool != NULL) { duke@435: MemoryUsage usage = pool->get_memory_usage(); duke@435: Handle h = MemoryService::create_MemoryUsage_obj(usage, CHECK_NULL); duke@435: return JNIHandles::make_local(env, h()); duke@435: } else { duke@435: return NULL; duke@435: } duke@435: JVM_END duke@435: duke@435: // Returns a java/lang/management/MemoryUsage object containing the memory usage duke@435: // of a given memory pool. duke@435: JVM_ENTRY(jobject, jmm_GetPeakMemoryPoolUsage(JNIEnv* env, jobject obj)) duke@435: ResourceMark rm(THREAD); duke@435: duke@435: MemoryPool* pool = get_memory_pool_from_jobject(obj, CHECK_NULL); duke@435: if (pool != NULL) { duke@435: MemoryUsage usage = pool->get_peak_memory_usage(); duke@435: Handle h = MemoryService::create_MemoryUsage_obj(usage, CHECK_NULL); duke@435: return JNIHandles::make_local(env, h()); duke@435: } else { duke@435: return NULL; duke@435: } duke@435: JVM_END duke@435: duke@435: // Returns a java/lang/management/MemoryUsage object containing the memory usage duke@435: // of a given memory pool after most recent GC. duke@435: JVM_ENTRY(jobject, jmm_GetPoolCollectionUsage(JNIEnv* env, jobject obj)) duke@435: ResourceMark rm(THREAD); duke@435: duke@435: MemoryPool* pool = get_memory_pool_from_jobject(obj, CHECK_NULL); duke@435: if (pool != NULL && pool->is_collected_pool()) { duke@435: MemoryUsage usage = pool->get_last_collection_usage(); duke@435: Handle h = MemoryService::create_MemoryUsage_obj(usage, CHECK_NULL); duke@435: return JNIHandles::make_local(env, h()); duke@435: } else { duke@435: return NULL; duke@435: } duke@435: JVM_END duke@435: duke@435: // Sets the memory pool sensor for a threshold type duke@435: JVM_ENTRY(void, jmm_SetPoolSensor(JNIEnv* env, jobject obj, jmmThresholdType type, jobject sensorObj)) duke@435: if (obj == NULL || sensorObj == NULL) { duke@435: THROW(vmSymbols::java_lang_NullPointerException()); duke@435: } duke@435: duke@435: klassOop sensor_klass = Management::sun_management_Sensor_klass(CHECK); duke@435: oop s = JNIHandles::resolve(sensorObj); duke@435: assert(s->is_instance(), "Sensor should be an instanceOop"); duke@435: instanceHandle sensor_h(THREAD, (instanceOop) s); duke@435: if (!sensor_h->is_a(sensor_klass)) { duke@435: THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(), duke@435: "Sensor is not an instance of sun.management.Sensor class"); duke@435: } duke@435: duke@435: MemoryPool* mpool = get_memory_pool_from_jobject(obj, CHECK); duke@435: assert(mpool != NULL, "MemoryPool should exist"); duke@435: duke@435: switch (type) { duke@435: case JMM_USAGE_THRESHOLD_HIGH: duke@435: case JMM_USAGE_THRESHOLD_LOW: duke@435: // have only one sensor for threshold high and low duke@435: mpool->set_usage_sensor_obj(sensor_h); duke@435: break; duke@435: case JMM_COLLECTION_USAGE_THRESHOLD_HIGH: duke@435: case JMM_COLLECTION_USAGE_THRESHOLD_LOW: duke@435: // have only one sensor for threshold high and low duke@435: mpool->set_gc_usage_sensor_obj(sensor_h); duke@435: break; duke@435: default: duke@435: assert(false, "Unrecognized type"); duke@435: } duke@435: duke@435: JVM_END duke@435: duke@435: duke@435: // Sets the threshold of a given memory pool. duke@435: // Returns the previous threshold. duke@435: // duke@435: // Input parameters: duke@435: // pool - the MemoryPoolMXBean object duke@435: // type - threshold type duke@435: // threshold - the new threshold (must not be negative) duke@435: // duke@435: JVM_ENTRY(jlong, jmm_SetPoolThreshold(JNIEnv* env, jobject obj, jmmThresholdType type, jlong threshold)) duke@435: if (threshold < 0) { duke@435: THROW_MSG_(vmSymbols::java_lang_IllegalArgumentException(), duke@435: "Invalid threshold value", duke@435: -1); duke@435: } duke@435: swamyv@924: if ((size_t)threshold > max_uintx) { swamyv@924: stringStream st; swamyv@924: st.print("Invalid valid threshold value. Threshold value (" UINT64_FORMAT ") > max value of size_t (" SIZE_FORMAT ")", (size_t)threshold, max_uintx); swamyv@924: THROW_MSG_(vmSymbols::java_lang_IllegalArgumentException(), st.as_string(), -1); duke@435: } duke@435: duke@435: MemoryPool* pool = get_memory_pool_from_jobject(obj, CHECK_(0L)); duke@435: assert(pool != NULL, "MemoryPool should exist"); duke@435: duke@435: jlong prev = 0; duke@435: switch (type) { duke@435: case JMM_USAGE_THRESHOLD_HIGH: duke@435: if (!pool->usage_threshold()->is_high_threshold_supported()) { duke@435: return -1; duke@435: } duke@435: prev = pool->usage_threshold()->set_high_threshold((size_t) threshold); duke@435: break; duke@435: duke@435: case JMM_USAGE_THRESHOLD_LOW: duke@435: if (!pool->usage_threshold()->is_low_threshold_supported()) { duke@435: return -1; duke@435: } duke@435: prev = pool->usage_threshold()->set_low_threshold((size_t) threshold); duke@435: break; duke@435: duke@435: case JMM_COLLECTION_USAGE_THRESHOLD_HIGH: duke@435: if (!pool->gc_usage_threshold()->is_high_threshold_supported()) { duke@435: return -1; duke@435: } duke@435: // return and the new threshold is effective for the next GC duke@435: return pool->gc_usage_threshold()->set_high_threshold((size_t) threshold); duke@435: duke@435: case JMM_COLLECTION_USAGE_THRESHOLD_LOW: duke@435: if (!pool->gc_usage_threshold()->is_low_threshold_supported()) { duke@435: return -1; duke@435: } duke@435: // return and the new threshold is effective for the next GC duke@435: return pool->gc_usage_threshold()->set_low_threshold((size_t) threshold); duke@435: duke@435: default: duke@435: assert(false, "Unrecognized type"); duke@435: return -1; duke@435: } duke@435: duke@435: // When the threshold is changed, reevaluate if the low memory duke@435: // detection is enabled. duke@435: if (prev != threshold) { duke@435: LowMemoryDetector::recompute_enabled_for_collected_pools(); duke@435: LowMemoryDetector::detect_low_memory(pool); duke@435: } duke@435: return prev; duke@435: JVM_END duke@435: phh@2423: // Gets an array containing the amount of memory allocated on the Java phh@2423: // heap for a set of threads (in bytes). Each element of the array is phh@2423: // the amount of memory allocated for the thread ID specified in the phh@2423: // corresponding entry in the given array of thread IDs; or -1 if the phh@2423: // thread does not exist or has terminated. phh@2423: JVM_ENTRY(void, jmm_GetThreadAllocatedMemory(JNIEnv *env, jlongArray ids, phh@2423: jlongArray sizeArray)) phh@2423: // Check if threads is null phh@2423: if (ids == NULL || sizeArray == NULL) { phh@2423: THROW(vmSymbols::java_lang_NullPointerException()); phh@2423: } phh@2423: phh@2423: ResourceMark rm(THREAD); phh@2423: typeArrayOop ta = typeArrayOop(JNIHandles::resolve_non_null(ids)); phh@2423: typeArrayHandle ids_ah(THREAD, ta); phh@2423: phh@2423: typeArrayOop sa = typeArrayOop(JNIHandles::resolve_non_null(sizeArray)); phh@2423: typeArrayHandle sizeArray_h(THREAD, sa); phh@2423: phh@2423: // validate the thread id array phh@2423: validate_thread_id_array(ids_ah, CHECK); phh@2423: phh@2423: // sizeArray must be of the same length as the given array of thread IDs phh@2423: int num_threads = ids_ah->length(); phh@2423: if (num_threads != sizeArray_h->length()) { phh@2423: THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(), phh@2423: "The length of the given long array does not match the length of " phh@2423: "the given array of thread IDs"); phh@2423: } phh@2423: phh@2423: MutexLockerEx ml(Threads_lock); phh@2423: for (int i = 0; i < num_threads; i++) { phh@2423: JavaThread* java_thread = find_java_thread_from_id(ids_ah->long_at(i)); phh@2423: if (java_thread != NULL) { phh@2423: sizeArray_h->long_at_put(i, java_thread->cooked_allocated_bytes()); phh@2423: } phh@2423: } phh@2423: JVM_END phh@2423: duke@435: // Returns a java/lang/management/MemoryUsage object representing duke@435: // the memory usage for the heap or non-heap memory. duke@435: JVM_ENTRY(jobject, jmm_GetMemoryUsage(JNIEnv* env, jboolean heap)) duke@435: ResourceMark rm(THREAD); duke@435: duke@435: // Calculate the memory usage duke@435: size_t total_init = 0; duke@435: size_t total_used = 0; duke@435: size_t total_committed = 0; duke@435: size_t total_max = 0; duke@435: bool has_undefined_init_size = false; duke@435: bool has_undefined_max_size = false; duke@435: duke@435: for (int i = 0; i < MemoryService::num_memory_pools(); i++) { duke@435: MemoryPool* pool = MemoryService::get_memory_pool(i); duke@435: if ((heap && pool->is_heap()) || (!heap && pool->is_non_heap())) { duke@435: MemoryUsage u = pool->get_memory_usage(); duke@435: total_used += u.used(); duke@435: total_committed += u.committed(); duke@435: duke@435: // if any one of the memory pool has undefined init_size or max_size, duke@435: // set it to -1 duke@435: if (u.init_size() == (size_t)-1) { duke@435: has_undefined_init_size = true; duke@435: } duke@435: if (!has_undefined_init_size) { duke@435: total_init += u.init_size(); duke@435: } duke@435: duke@435: if (u.max_size() == (size_t)-1) { duke@435: has_undefined_max_size = true; duke@435: } duke@435: if (!has_undefined_max_size) { duke@435: total_max += u.max_size(); duke@435: } duke@435: } duke@435: } duke@435: tonyp@2112: // In our current implementation, we make sure that all non-heap tonyp@2112: // pools have defined init and max sizes. Heap pools do not matter, tonyp@2112: // as we never use total_init and total_max for them. tonyp@2112: assert(heap || !has_undefined_init_size, "Undefined init size"); tonyp@2112: assert(heap || !has_undefined_max_size, "Undefined max size"); duke@435: phh@1499: MemoryUsage usage((heap ? InitialHeapSize : total_init), duke@435: total_used, duke@435: total_committed, duke@435: (heap ? Universe::heap()->max_capacity() : total_max)); duke@435: duke@435: Handle obj = MemoryService::create_MemoryUsage_obj(usage, CHECK_NULL); duke@435: return JNIHandles::make_local(env, obj()); duke@435: JVM_END duke@435: duke@435: // Returns the boolean value of a given attribute. duke@435: JVM_LEAF(jboolean, jmm_GetBoolAttribute(JNIEnv *env, jmmBoolAttribute att)) duke@435: switch (att) { duke@435: case JMM_VERBOSE_GC: duke@435: return MemoryService::get_verbose(); duke@435: case JMM_VERBOSE_CLASS: duke@435: return ClassLoadingService::get_verbose(); duke@435: case JMM_THREAD_CONTENTION_MONITORING: duke@435: return ThreadService::is_thread_monitoring_contention(); duke@435: case JMM_THREAD_CPU_TIME: duke@435: return ThreadService::is_thread_cpu_time_enabled(); phh@2423: case JMM_THREAD_ALLOCATED_MEMORY: phh@2423: return ThreadService::is_thread_allocated_memory_enabled(); duke@435: default: duke@435: assert(0, "Unrecognized attribute"); duke@435: return false; duke@435: } duke@435: JVM_END duke@435: duke@435: // Sets the given boolean attribute and returns the previous value. duke@435: JVM_ENTRY(jboolean, jmm_SetBoolAttribute(JNIEnv *env, jmmBoolAttribute att, jboolean flag)) duke@435: switch (att) { duke@435: case JMM_VERBOSE_GC: duke@435: return MemoryService::set_verbose(flag != 0); duke@435: case JMM_VERBOSE_CLASS: duke@435: return ClassLoadingService::set_verbose(flag != 0); duke@435: case JMM_THREAD_CONTENTION_MONITORING: duke@435: return ThreadService::set_thread_monitoring_contention(flag != 0); duke@435: case JMM_THREAD_CPU_TIME: duke@435: return ThreadService::set_thread_cpu_time_enabled(flag != 0); phh@2423: case JMM_THREAD_ALLOCATED_MEMORY: phh@2423: return ThreadService::set_thread_allocated_memory_enabled(flag != 0); duke@435: default: duke@435: assert(0, "Unrecognized attribute"); duke@435: return false; duke@435: } duke@435: JVM_END duke@435: duke@435: duke@435: static jlong get_gc_attribute(GCMemoryManager* mgr, jmmLongAttribute att) { duke@435: switch (att) { duke@435: case JMM_GC_TIME_MS: duke@435: return mgr->gc_time_ms(); duke@435: duke@435: case JMM_GC_COUNT: duke@435: return mgr->gc_count(); duke@435: duke@435: case JMM_GC_EXT_ATTRIBUTE_INFO_SIZE: duke@435: // current implementation only has 1 ext attribute duke@435: return 1; duke@435: duke@435: default: duke@435: assert(0, "Unrecognized GC attribute"); duke@435: return -1; duke@435: } duke@435: } duke@435: duke@435: class VmThreadCountClosure: public ThreadClosure { duke@435: private: duke@435: int _count; duke@435: public: duke@435: VmThreadCountClosure() : _count(0) {}; duke@435: void do_thread(Thread* thread); duke@435: int count() { return _count; } duke@435: }; duke@435: duke@435: void VmThreadCountClosure::do_thread(Thread* thread) { duke@435: // exclude externally visible JavaThreads duke@435: if (thread->is_Java_thread() && !thread->is_hidden_from_external_view()) { duke@435: return; duke@435: } duke@435: duke@435: _count++; duke@435: } duke@435: duke@435: static jint get_vm_thread_count() { duke@435: VmThreadCountClosure vmtcc; duke@435: { duke@435: MutexLockerEx ml(Threads_lock); duke@435: Threads::threads_do(&vmtcc); duke@435: } duke@435: duke@435: return vmtcc.count(); duke@435: } duke@435: duke@435: static jint get_num_flags() { duke@435: // last flag entry is always NULL, so subtract 1 duke@435: int nFlags = (int) Flag::numFlags - 1; duke@435: int count = 0; duke@435: for (int i = 0; i < nFlags; i++) { duke@435: Flag* flag = &Flag::flags[i]; ysr@785: // Exclude the locked (diagnostic, experimental) flags duke@435: if (flag->is_unlocked() || flag->is_unlocker()) { duke@435: count++; duke@435: } duke@435: } duke@435: return count; duke@435: } duke@435: duke@435: static jlong get_long_attribute(jmmLongAttribute att) { duke@435: switch (att) { duke@435: case JMM_CLASS_LOADED_COUNT: duke@435: return ClassLoadingService::loaded_class_count(); duke@435: duke@435: case JMM_CLASS_UNLOADED_COUNT: duke@435: return ClassLoadingService::unloaded_class_count(); duke@435: duke@435: case JMM_THREAD_TOTAL_COUNT: duke@435: return ThreadService::get_total_thread_count(); duke@435: duke@435: case JMM_THREAD_LIVE_COUNT: duke@435: return ThreadService::get_live_thread_count(); duke@435: duke@435: case JMM_THREAD_PEAK_COUNT: duke@435: return ThreadService::get_peak_thread_count(); duke@435: duke@435: case JMM_THREAD_DAEMON_COUNT: duke@435: return ThreadService::get_daemon_thread_count(); duke@435: duke@435: case JMM_JVM_INIT_DONE_TIME_MS: duke@435: return Management::vm_init_done_time(); duke@435: duke@435: case JMM_COMPILE_TOTAL_TIME_MS: duke@435: return Management::ticks_to_ms(CompileBroker::total_compilation_ticks()); duke@435: duke@435: case JMM_OS_PROCESS_ID: duke@435: return os::current_process_id(); duke@435: duke@435: // Hotspot-specific counters duke@435: case JMM_CLASS_LOADED_BYTES: duke@435: return ClassLoadingService::loaded_class_bytes(); duke@435: duke@435: case JMM_CLASS_UNLOADED_BYTES: duke@435: return ClassLoadingService::unloaded_class_bytes(); duke@435: duke@435: case JMM_SHARED_CLASS_LOADED_COUNT: duke@435: return ClassLoadingService::loaded_shared_class_count(); duke@435: duke@435: case JMM_SHARED_CLASS_UNLOADED_COUNT: duke@435: return ClassLoadingService::unloaded_shared_class_count(); duke@435: duke@435: duke@435: case JMM_SHARED_CLASS_LOADED_BYTES: duke@435: return ClassLoadingService::loaded_shared_class_bytes(); duke@435: duke@435: case JMM_SHARED_CLASS_UNLOADED_BYTES: duke@435: return ClassLoadingService::unloaded_shared_class_bytes(); duke@435: duke@435: case JMM_TOTAL_CLASSLOAD_TIME_MS: duke@435: return ClassLoader::classloader_time_ms(); duke@435: duke@435: case JMM_VM_GLOBAL_COUNT: duke@435: return get_num_flags(); duke@435: duke@435: case JMM_SAFEPOINT_COUNT: duke@435: return RuntimeService::safepoint_count(); duke@435: duke@435: case JMM_TOTAL_SAFEPOINTSYNC_TIME_MS: duke@435: return RuntimeService::safepoint_sync_time_ms(); duke@435: duke@435: case JMM_TOTAL_STOPPED_TIME_MS: duke@435: return RuntimeService::safepoint_time_ms(); duke@435: duke@435: case JMM_TOTAL_APP_TIME_MS: duke@435: return RuntimeService::application_time_ms(); duke@435: duke@435: case JMM_VM_THREAD_COUNT: duke@435: return get_vm_thread_count(); duke@435: duke@435: case JMM_CLASS_INIT_TOTAL_COUNT: duke@435: return ClassLoader::class_init_count(); duke@435: duke@435: case JMM_CLASS_INIT_TOTAL_TIME_MS: duke@435: return ClassLoader::class_init_time_ms(); duke@435: duke@435: case JMM_CLASS_VERIFY_TOTAL_TIME_MS: duke@435: return ClassLoader::class_verify_time_ms(); duke@435: duke@435: case JMM_METHOD_DATA_SIZE_BYTES: duke@435: return ClassLoadingService::class_method_data_size(); duke@435: duke@435: case JMM_OS_MEM_TOTAL_PHYSICAL_BYTES: duke@435: return os::physical_memory(); duke@435: duke@435: default: duke@435: return -1; duke@435: } duke@435: } duke@435: duke@435: duke@435: // Returns the long value of a given attribute. duke@435: JVM_ENTRY(jlong, jmm_GetLongAttribute(JNIEnv *env, jobject obj, jmmLongAttribute att)) duke@435: if (obj == NULL) { duke@435: return get_long_attribute(att); duke@435: } else { duke@435: GCMemoryManager* mgr = get_gc_memory_manager_from_jobject(obj, CHECK_(0L)); duke@435: if (mgr != NULL) { duke@435: return get_gc_attribute(mgr, att); duke@435: } duke@435: } duke@435: return -1; duke@435: JVM_END duke@435: duke@435: // Gets the value of all attributes specified in the given array duke@435: // and sets the value in the result array. duke@435: // Returns the number of attributes found. duke@435: JVM_ENTRY(jint, jmm_GetLongAttributes(JNIEnv *env, duke@435: jobject obj, duke@435: jmmLongAttribute* atts, duke@435: jint count, duke@435: jlong* result)) duke@435: duke@435: int num_atts = 0; duke@435: if (obj == NULL) { duke@435: for (int i = 0; i < count; i++) { duke@435: result[i] = get_long_attribute(atts[i]); duke@435: if (result[i] != -1) { duke@435: num_atts++; duke@435: } duke@435: } duke@435: } else { duke@435: GCMemoryManager* mgr = get_gc_memory_manager_from_jobject(obj, CHECK_0); duke@435: for (int i = 0; i < count; i++) { duke@435: result[i] = get_gc_attribute(mgr, atts[i]); duke@435: if (result[i] != -1) { duke@435: num_atts++; duke@435: } duke@435: } duke@435: } duke@435: return num_atts; duke@435: JVM_END duke@435: duke@435: // Helper function to do thread dump for a specific list of threads duke@435: static void do_thread_dump(ThreadDumpResult* dump_result, duke@435: typeArrayHandle ids_ah, // array of thread ID (long[]) duke@435: int num_threads, duke@435: int max_depth, duke@435: bool with_locked_monitors, duke@435: bool with_locked_synchronizers, duke@435: TRAPS) { duke@435: duke@435: // First get an array of threadObj handles. duke@435: // A JavaThread may terminate before we get the stack trace. duke@435: GrowableArray* thread_handle_array = new GrowableArray(num_threads); duke@435: { duke@435: MutexLockerEx ml(Threads_lock); duke@435: for (int i = 0; i < num_threads; i++) { duke@435: jlong tid = ids_ah->long_at(i); duke@435: JavaThread* jt = find_java_thread_from_id(tid); duke@435: oop thread_obj = (jt != NULL ? jt->threadObj() : (oop)NULL); duke@435: instanceHandle threadObj_h(THREAD, (instanceOop) thread_obj); duke@435: thread_handle_array->append(threadObj_h); duke@435: } duke@435: } duke@435: duke@435: // Obtain thread dumps and thread snapshot information duke@435: VM_ThreadDump op(dump_result, duke@435: thread_handle_array, duke@435: num_threads, duke@435: max_depth, /* stack depth */ duke@435: with_locked_monitors, duke@435: with_locked_synchronizers); duke@435: VMThread::execute(&op); duke@435: } duke@435: duke@435: // Gets an array of ThreadInfo objects. Each element is the ThreadInfo duke@435: // for the thread ID specified in the corresponding entry in duke@435: // the given array of thread IDs; or NULL if the thread does not exist duke@435: // or has terminated. duke@435: // duke@435: // Input parameters: duke@435: // ids - array of thread IDs duke@435: // maxDepth - the maximum depth of stack traces to be dumped: duke@435: // maxDepth == -1 requests to dump entire stack trace. duke@435: // maxDepth == 0 requests no stack trace. duke@435: // infoArray - array of ThreadInfo objects duke@435: // phh@2423: // QQQ - Why does this method return a value instead of void? duke@435: JVM_ENTRY(jint, jmm_GetThreadInfo(JNIEnv *env, jlongArray ids, jint maxDepth, jobjectArray infoArray)) duke@435: // Check if threads is null duke@435: if (ids == NULL || infoArray == NULL) { duke@435: THROW_(vmSymbols::java_lang_NullPointerException(), -1); duke@435: } duke@435: duke@435: if (maxDepth < -1) { duke@435: THROW_MSG_(vmSymbols::java_lang_IllegalArgumentException(), duke@435: "Invalid maxDepth", -1); duke@435: } duke@435: duke@435: ResourceMark rm(THREAD); duke@435: typeArrayOop ta = typeArrayOop(JNIHandles::resolve_non_null(ids)); duke@435: typeArrayHandle ids_ah(THREAD, ta); duke@435: duke@435: oop infoArray_obj = JNIHandles::resolve_non_null(infoArray); duke@435: objArrayOop oa = objArrayOop(infoArray_obj); duke@435: objArrayHandle infoArray_h(THREAD, oa); duke@435: duke@435: // validate the thread id array duke@435: validate_thread_id_array(ids_ah, CHECK_0); duke@435: duke@435: // validate the ThreadInfo[] parameters duke@435: validate_thread_info_array(infoArray_h, CHECK_0); duke@435: duke@435: // infoArray must be of the same length as the given array of thread IDs duke@435: int num_threads = ids_ah->length(); duke@435: if (num_threads != infoArray_h->length()) { duke@435: THROW_MSG_(vmSymbols::java_lang_IllegalArgumentException(), duke@435: "The length of the given ThreadInfo array does not match the length of the given array of thread IDs", -1); duke@435: } duke@435: duke@435: if (JDK_Version::is_gte_jdk16x_version()) { duke@435: // make sure the AbstractOwnableSynchronizer klass is loaded before taking thread snapshots duke@435: java_util_concurrent_locks_AbstractOwnableSynchronizer::initialize(CHECK_0); duke@435: } duke@435: duke@435: // Must use ThreadDumpResult to store the ThreadSnapshot. duke@435: // GC may occur after the thread snapshots are taken but before duke@435: // this function returns. The threadObj and other oops kept duke@435: // in the ThreadSnapshot are marked and adjusted during GC. duke@435: ThreadDumpResult dump_result(num_threads); duke@435: duke@435: if (maxDepth == 0) { duke@435: // no stack trace dumped - do not need to stop the world duke@435: { duke@435: MutexLockerEx ml(Threads_lock); duke@435: for (int i = 0; i < num_threads; i++) { duke@435: jlong tid = ids_ah->long_at(i); duke@435: JavaThread* jt = find_java_thread_from_id(tid); duke@435: ThreadSnapshot* ts; duke@435: if (jt == NULL) { duke@435: // if the thread does not exist or now it is terminated, duke@435: // create dummy snapshot duke@435: ts = new ThreadSnapshot(); duke@435: } else { duke@435: ts = new ThreadSnapshot(jt); duke@435: } duke@435: dump_result.add_thread_snapshot(ts); duke@435: } duke@435: } duke@435: } else { duke@435: // obtain thread dump with the specific list of threads with stack trace duke@435: do_thread_dump(&dump_result, duke@435: ids_ah, duke@435: num_threads, duke@435: maxDepth, duke@435: false, /* no locked monitor */ duke@435: false, /* no locked synchronizers */ duke@435: CHECK_0); duke@435: } duke@435: duke@435: int num_snapshots = dump_result.num_snapshots(); duke@435: assert(num_snapshots == num_threads, "Must match the number of thread snapshots"); duke@435: int index = 0; duke@435: for (ThreadSnapshot* ts = dump_result.snapshots(); ts != NULL; index++, ts = ts->next()) { duke@435: // For each thread, create an java/lang/management/ThreadInfo object duke@435: // and fill with the thread information duke@435: duke@435: if (ts->threadObj() == NULL) { duke@435: // if the thread does not exist or now it is terminated, set threadinfo to NULL duke@435: infoArray_h->obj_at_put(index, NULL); duke@435: continue; duke@435: } duke@435: duke@435: // Create java.lang.management.ThreadInfo object duke@435: instanceOop info_obj = Management::create_thread_info_instance(ts, CHECK_0); duke@435: infoArray_h->obj_at_put(index, info_obj); duke@435: } duke@435: return 0; duke@435: JVM_END duke@435: duke@435: // Dump thread info for the specified threads. duke@435: // It returns an array of ThreadInfo objects. Each element is the ThreadInfo duke@435: // for the thread ID specified in the corresponding entry in duke@435: // the given array of thread IDs; or NULL if the thread does not exist duke@435: // or has terminated. duke@435: // duke@435: // Input parameter: duke@435: // ids - array of thread IDs; NULL indicates all live threads duke@435: // locked_monitors - if true, dump locked object monitors duke@435: // locked_synchronizers - if true, dump locked JSR-166 synchronizers duke@435: // duke@435: JVM_ENTRY(jobjectArray, jmm_DumpThreads(JNIEnv *env, jlongArray thread_ids, jboolean locked_monitors, jboolean locked_synchronizers)) duke@435: ResourceMark rm(THREAD); duke@435: duke@435: if (JDK_Version::is_gte_jdk16x_version()) { duke@435: // make sure the AbstractOwnableSynchronizer klass is loaded before taking thread snapshots duke@435: java_util_concurrent_locks_AbstractOwnableSynchronizer::initialize(CHECK_NULL); duke@435: } duke@435: duke@435: typeArrayOop ta = typeArrayOop(JNIHandles::resolve(thread_ids)); duke@435: int num_threads = (ta != NULL ? ta->length() : 0); duke@435: typeArrayHandle ids_ah(THREAD, ta); duke@435: duke@435: ThreadDumpResult dump_result(num_threads); // can safepoint duke@435: duke@435: if (ids_ah() != NULL) { duke@435: duke@435: // validate the thread id array duke@435: validate_thread_id_array(ids_ah, CHECK_NULL); duke@435: duke@435: // obtain thread dump of a specific list of threads duke@435: do_thread_dump(&dump_result, duke@435: ids_ah, duke@435: num_threads, duke@435: -1, /* entire stack */ duke@435: (locked_monitors ? true : false), /* with locked monitors */ duke@435: (locked_synchronizers ? true : false), /* with locked synchronizers */ duke@435: CHECK_NULL); duke@435: } else { duke@435: // obtain thread dump of all threads duke@435: VM_ThreadDump op(&dump_result, duke@435: -1, /* entire stack */ duke@435: (locked_monitors ? true : false), /* with locked monitors */ duke@435: (locked_synchronizers ? true : false) /* with locked synchronizers */); duke@435: VMThread::execute(&op); duke@435: } duke@435: duke@435: int num_snapshots = dump_result.num_snapshots(); duke@435: duke@435: // create the result ThreadInfo[] object duke@435: klassOop k = Management::java_lang_management_ThreadInfo_klass(CHECK_NULL); duke@435: instanceKlassHandle ik (THREAD, k); duke@435: objArrayOop r = oopFactory::new_objArray(ik(), num_snapshots, CHECK_NULL); duke@435: objArrayHandle result_h(THREAD, r); duke@435: duke@435: int index = 0; duke@435: for (ThreadSnapshot* ts = dump_result.snapshots(); ts != NULL; ts = ts->next(), index++) { duke@435: if (ts->threadObj() == NULL) { duke@435: // if the thread does not exist or now it is terminated, set threadinfo to NULL duke@435: result_h->obj_at_put(index, NULL); duke@435: continue; duke@435: } duke@435: duke@435: ThreadStackTrace* stacktrace = ts->get_stack_trace(); duke@435: assert(stacktrace != NULL, "Must have a stack trace dumped"); duke@435: duke@435: // Create Object[] filled with locked monitors duke@435: // Create int[] filled with the stack depth where a monitor was locked duke@435: int num_frames = stacktrace->get_stack_depth(); duke@435: int num_locked_monitors = stacktrace->num_jni_locked_monitors(); duke@435: duke@435: // Count the total number of locked monitors duke@435: for (int i = 0; i < num_frames; i++) { duke@435: StackFrameInfo* frame = stacktrace->stack_frame_at(i); duke@435: num_locked_monitors += frame->num_locked_monitors(); duke@435: } duke@435: duke@435: objArrayHandle monitors_array; duke@435: typeArrayHandle depths_array; duke@435: objArrayHandle synchronizers_array; duke@435: duke@435: if (locked_monitors) { duke@435: // Constructs Object[] and int[] to contain the object monitor and the stack depth duke@435: // where the thread locked it stefank@2574: objArrayOop array = oopFactory::new_objArray(SystemDictionary::Object_klass(), num_locked_monitors, CHECK_NULL); duke@435: objArrayHandle mh(THREAD, array); duke@435: monitors_array = mh; duke@435: duke@435: typeArrayOop tarray = oopFactory::new_typeArray(T_INT, num_locked_monitors, CHECK_NULL); duke@435: typeArrayHandle dh(THREAD, tarray); duke@435: depths_array = dh; duke@435: duke@435: int count = 0; duke@435: int j = 0; duke@435: for (int depth = 0; depth < num_frames; depth++) { duke@435: StackFrameInfo* frame = stacktrace->stack_frame_at(depth); duke@435: int len = frame->num_locked_monitors(); duke@435: GrowableArray* locked_monitors = frame->locked_monitors(); duke@435: for (j = 0; j < len; j++) { duke@435: oop monitor = locked_monitors->at(j); duke@435: assert(monitor != NULL && monitor->is_instance(), "must be a Java object"); duke@435: monitors_array->obj_at_put(count, monitor); duke@435: depths_array->int_at_put(count, depth); duke@435: count++; duke@435: } duke@435: } duke@435: duke@435: GrowableArray* jni_locked_monitors = stacktrace->jni_locked_monitors(); duke@435: for (j = 0; j < jni_locked_monitors->length(); j++) { duke@435: oop object = jni_locked_monitors->at(j); duke@435: assert(object != NULL && object->is_instance(), "must be a Java object"); duke@435: monitors_array->obj_at_put(count, object); duke@435: // Monitor locked via JNI MonitorEnter call doesn't have stack depth info duke@435: depths_array->int_at_put(count, -1); duke@435: count++; duke@435: } duke@435: assert(count == num_locked_monitors, "number of locked monitors doesn't match"); duke@435: } duke@435: duke@435: if (locked_synchronizers) { duke@435: // Create Object[] filled with locked JSR-166 synchronizers duke@435: assert(ts->threadObj() != NULL, "Must be a valid JavaThread"); duke@435: ThreadConcurrentLocks* tcl = ts->get_concurrent_locks(); duke@435: GrowableArray* locks = (tcl != NULL ? tcl->owned_locks() : NULL); duke@435: int num_locked_synchronizers = (locks != NULL ? locks->length() : 0); duke@435: stefank@2574: objArrayOop array = oopFactory::new_objArray(SystemDictionary::Object_klass(), num_locked_synchronizers, CHECK_NULL); duke@435: objArrayHandle sh(THREAD, array); duke@435: synchronizers_array = sh; duke@435: duke@435: for (int k = 0; k < num_locked_synchronizers; k++) { duke@435: synchronizers_array->obj_at_put(k, locks->at(k)); duke@435: } duke@435: } duke@435: duke@435: // Create java.lang.management.ThreadInfo object duke@435: instanceOop info_obj = Management::create_thread_info_instance(ts, duke@435: monitors_array, duke@435: depths_array, duke@435: synchronizers_array, duke@435: CHECK_NULL); duke@435: result_h->obj_at_put(index, info_obj); duke@435: } duke@435: duke@435: return (jobjectArray) JNIHandles::make_local(env, result_h()); duke@435: JVM_END duke@435: duke@435: // Returns an array of Class objects. duke@435: JVM_ENTRY(jobjectArray, jmm_GetLoadedClasses(JNIEnv *env)) duke@435: ResourceMark rm(THREAD); duke@435: duke@435: LoadedClassesEnumerator lce(THREAD); // Pass current Thread as parameter duke@435: duke@435: int num_classes = lce.num_loaded_classes(); never@1577: objArrayOop r = oopFactory::new_objArray(SystemDictionary::Class_klass(), num_classes, CHECK_0); duke@435: objArrayHandle classes_ah(THREAD, r); duke@435: duke@435: for (int i = 0; i < num_classes; i++) { duke@435: KlassHandle kh = lce.get_klass(i); duke@435: oop mirror = Klass::cast(kh())->java_mirror(); duke@435: classes_ah->obj_at_put(i, mirror); duke@435: } duke@435: duke@435: return (jobjectArray) JNIHandles::make_local(env, classes_ah()); duke@435: JVM_END duke@435: duke@435: // Reset statistic. Return true if the requested statistic is reset. duke@435: // Otherwise, return false. duke@435: // duke@435: // Input parameters: duke@435: // obj - specify which instance the statistic associated with to be reset duke@435: // For PEAK_POOL_USAGE stat, obj is required to be a memory pool object. duke@435: // For THREAD_CONTENTION_COUNT and TIME stat, obj is required to be a thread ID. duke@435: // type - the type of statistic to be reset duke@435: // duke@435: JVM_ENTRY(jboolean, jmm_ResetStatistic(JNIEnv *env, jvalue obj, jmmStatisticType type)) duke@435: ResourceMark rm(THREAD); duke@435: duke@435: switch (type) { duke@435: case JMM_STAT_PEAK_THREAD_COUNT: duke@435: ThreadService::reset_peak_thread_count(); duke@435: return true; duke@435: duke@435: case JMM_STAT_THREAD_CONTENTION_COUNT: duke@435: case JMM_STAT_THREAD_CONTENTION_TIME: { duke@435: jlong tid = obj.j; duke@435: if (tid < 0) { duke@435: THROW_(vmSymbols::java_lang_IllegalArgumentException(), JNI_FALSE); duke@435: } duke@435: duke@435: // Look for the JavaThread of this given tid duke@435: MutexLockerEx ml(Threads_lock); duke@435: if (tid == 0) { duke@435: // reset contention statistics for all threads if tid == 0 duke@435: for (JavaThread* java_thread = Threads::first(); java_thread != NULL; java_thread = java_thread->next()) { duke@435: if (type == JMM_STAT_THREAD_CONTENTION_COUNT) { duke@435: ThreadService::reset_contention_count_stat(java_thread); duke@435: } else { duke@435: ThreadService::reset_contention_time_stat(java_thread); duke@435: } duke@435: } duke@435: } else { duke@435: // reset contention statistics for a given thread duke@435: JavaThread* java_thread = find_java_thread_from_id(tid); duke@435: if (java_thread == NULL) { duke@435: return false; duke@435: } duke@435: duke@435: if (type == JMM_STAT_THREAD_CONTENTION_COUNT) { duke@435: ThreadService::reset_contention_count_stat(java_thread); duke@435: } else { duke@435: ThreadService::reset_contention_time_stat(java_thread); duke@435: } duke@435: } duke@435: return true; duke@435: break; duke@435: } duke@435: case JMM_STAT_PEAK_POOL_USAGE: { duke@435: jobject o = obj.l; duke@435: if (o == NULL) { duke@435: THROW_(vmSymbols::java_lang_NullPointerException(), JNI_FALSE); duke@435: } duke@435: duke@435: oop pool_obj = JNIHandles::resolve(o); duke@435: assert(pool_obj->is_instance(), "Should be an instanceOop"); duke@435: instanceHandle ph(THREAD, (instanceOop) pool_obj); duke@435: duke@435: MemoryPool* pool = MemoryService::get_memory_pool(ph); duke@435: if (pool != NULL) { duke@435: pool->reset_peak_memory_usage(); duke@435: return true; duke@435: } duke@435: break; duke@435: } duke@435: case JMM_STAT_GC_STAT: { duke@435: jobject o = obj.l; duke@435: if (o == NULL) { duke@435: THROW_(vmSymbols::java_lang_NullPointerException(), JNI_FALSE); duke@435: } duke@435: duke@435: GCMemoryManager* mgr = get_gc_memory_manager_from_jobject(o, CHECK_0); duke@435: if (mgr != NULL) { duke@435: mgr->reset_gc_stat(); duke@435: return true; duke@435: } duke@435: break; duke@435: } duke@435: default: duke@435: assert(0, "Unknown Statistic Type"); duke@435: } duke@435: return false; duke@435: JVM_END duke@435: duke@435: // Returns the fast estimate of CPU time consumed by duke@435: // a given thread (in nanoseconds). duke@435: // If thread_id == 0, return CPU time for the current thread. duke@435: JVM_ENTRY(jlong, jmm_GetThreadCpuTime(JNIEnv *env, jlong thread_id)) duke@435: if (!os::is_thread_cpu_time_supported()) { duke@435: return -1; duke@435: } duke@435: duke@435: if (thread_id < 0) { duke@435: THROW_MSG_(vmSymbols::java_lang_IllegalArgumentException(), duke@435: "Invalid thread ID", -1); duke@435: } duke@435: duke@435: JavaThread* java_thread = NULL; duke@435: if (thread_id == 0) { duke@435: // current thread duke@435: return os::current_thread_cpu_time(); duke@435: } else { duke@435: MutexLockerEx ml(Threads_lock); duke@435: java_thread = find_java_thread_from_id(thread_id); duke@435: if (java_thread != NULL) { duke@435: return os::thread_cpu_time((Thread*) java_thread); duke@435: } duke@435: } duke@435: return -1; duke@435: JVM_END duke@435: duke@435: // Returns the CPU time consumed by a given thread (in nanoseconds). duke@435: // If thread_id == 0, CPU time for the current thread is returned. duke@435: // If user_sys_cpu_time = true, user level and system CPU time of duke@435: // a given thread is returned; otherwise, only user level CPU time duke@435: // is returned. duke@435: JVM_ENTRY(jlong, jmm_GetThreadCpuTimeWithKind(JNIEnv *env, jlong thread_id, jboolean user_sys_cpu_time)) duke@435: if (!os::is_thread_cpu_time_supported()) { duke@435: return -1; duke@435: } duke@435: duke@435: if (thread_id < 0) { duke@435: THROW_MSG_(vmSymbols::java_lang_IllegalArgumentException(), duke@435: "Invalid thread ID", -1); duke@435: } duke@435: duke@435: JavaThread* java_thread = NULL; duke@435: if (thread_id == 0) { duke@435: // current thread duke@435: return os::current_thread_cpu_time(user_sys_cpu_time != 0); duke@435: } else { duke@435: MutexLockerEx ml(Threads_lock); duke@435: java_thread = find_java_thread_from_id(thread_id); duke@435: if (java_thread != NULL) { duke@435: return os::thread_cpu_time((Thread*) java_thread, user_sys_cpu_time != 0); duke@435: } duke@435: } duke@435: return -1; duke@435: JVM_END duke@435: phh@2423: // Gets an array containing the CPU times consumed by a set of threads phh@2423: // (in nanoseconds). Each element of the array is the CPU time for the phh@2423: // thread ID specified in the corresponding entry in the given array phh@2423: // of thread IDs; or -1 if the thread does not exist or has terminated. phh@2423: // If user_sys_cpu_time = true, the sum of user level and system CPU time phh@2423: // for the given thread is returned; otherwise, only user level CPU time phh@2423: // is returned. phh@2423: JVM_ENTRY(void, jmm_GetThreadCpuTimesWithKind(JNIEnv *env, jlongArray ids, phh@2423: jlongArray timeArray, phh@2423: jboolean user_sys_cpu_time)) phh@2423: // Check if threads is null phh@2423: if (ids == NULL || timeArray == NULL) { phh@2423: THROW(vmSymbols::java_lang_NullPointerException()); phh@2423: } phh@2423: phh@2423: ResourceMark rm(THREAD); phh@2423: typeArrayOop ta = typeArrayOop(JNIHandles::resolve_non_null(ids)); phh@2423: typeArrayHandle ids_ah(THREAD, ta); phh@2423: phh@2423: typeArrayOop tia = typeArrayOop(JNIHandles::resolve_non_null(timeArray)); phh@2423: typeArrayHandle timeArray_h(THREAD, tia); phh@2423: phh@2423: // validate the thread id array phh@2423: validate_thread_id_array(ids_ah, CHECK); phh@2423: phh@2423: // timeArray must be of the same length as the given array of thread IDs phh@2423: int num_threads = ids_ah->length(); phh@2423: if (num_threads != timeArray_h->length()) { phh@2423: THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(), phh@2423: "The length of the given long array does not match the length of " phh@2423: "the given array of thread IDs"); phh@2423: } phh@2423: phh@2423: MutexLockerEx ml(Threads_lock); phh@2423: for (int i = 0; i < num_threads; i++) { phh@2423: JavaThread* java_thread = find_java_thread_from_id(ids_ah->long_at(i)); phh@2423: if (java_thread != NULL) { phh@2423: timeArray_h->long_at_put(i, os::thread_cpu_time((Thread*)java_thread, phh@2423: user_sys_cpu_time != 0)); phh@2423: } phh@2423: } phh@2423: JVM_END phh@2423: duke@435: // Returns a String array of all VM global flag names duke@435: JVM_ENTRY(jobjectArray, jmm_GetVMGlobalNames(JNIEnv *env)) duke@435: // last flag entry is always NULL, so subtract 1 duke@435: int nFlags = (int) Flag::numFlags - 1; duke@435: // allocate a temp array never@1577: objArrayOop r = oopFactory::new_objArray(SystemDictionary::String_klass(), duke@435: nFlags, CHECK_0); duke@435: objArrayHandle flags_ah(THREAD, r); duke@435: int num_entries = 0; duke@435: for (int i = 0; i < nFlags; i++) { duke@435: Flag* flag = &Flag::flags[i]; ysr@785: // Exclude the locked (experimental, diagnostic) flags duke@435: if (flag->is_unlocked() || flag->is_unlocker()) { duke@435: Handle s = java_lang_String::create_from_str(flag->name, CHECK_0); duke@435: flags_ah->obj_at_put(num_entries, s()); duke@435: num_entries++; duke@435: } duke@435: } duke@435: duke@435: if (num_entries < nFlags) { duke@435: // Return array of right length never@1577: objArrayOop res = oopFactory::new_objArray(SystemDictionary::String_klass(), num_entries, CHECK_0); duke@435: for(int i = 0; i < num_entries; i++) { duke@435: res->obj_at_put(i, flags_ah->obj_at(i)); duke@435: } duke@435: return (jobjectArray)JNIHandles::make_local(env, res); duke@435: } duke@435: duke@435: return (jobjectArray)JNIHandles::make_local(env, flags_ah()); duke@435: JVM_END duke@435: phh@1502: // Utility function used by jmm_GetVMGlobals. Returns false if flag type phh@1502: // can't be determined, true otherwise. If false is returned, then *global phh@1502: // will be incomplete and invalid. phh@1502: bool add_global_entry(JNIEnv* env, Handle name, jmmVMGlobal *global, Flag *flag, TRAPS) { duke@435: Handle flag_name; duke@435: if (name() == NULL) { phh@1502: flag_name = java_lang_String::create_from_str(flag->name, CHECK_false); duke@435: } else { duke@435: flag_name = name; duke@435: } duke@435: global->name = (jstring)JNIHandles::make_local(env, flag_name()); duke@435: duke@435: if (flag->is_bool()) { duke@435: global->value.z = flag->get_bool() ? JNI_TRUE : JNI_FALSE; duke@435: global->type = JMM_VMGLOBAL_TYPE_JBOOLEAN; duke@435: } else if (flag->is_intx()) { duke@435: global->value.j = (jlong)flag->get_intx(); duke@435: global->type = JMM_VMGLOBAL_TYPE_JLONG; duke@435: } else if (flag->is_uintx()) { duke@435: global->value.j = (jlong)flag->get_uintx(); duke@435: global->type = JMM_VMGLOBAL_TYPE_JLONG; phh@1502: } else if (flag->is_uint64_t()) { phh@1502: global->value.j = (jlong)flag->get_uint64_t(); phh@1502: global->type = JMM_VMGLOBAL_TYPE_JLONG; duke@435: } else if (flag->is_ccstr()) { phh@1502: Handle str = java_lang_String::create_from_str(flag->get_ccstr(), CHECK_false); duke@435: global->value.l = (jobject)JNIHandles::make_local(env, str()); duke@435: global->type = JMM_VMGLOBAL_TYPE_JSTRING; phh@1502: } else { phh@1502: global->type = JMM_VMGLOBAL_TYPE_UNKNOWN; phh@1502: return false; duke@435: } duke@435: duke@435: global->writeable = flag->is_writeable(); duke@435: global->external = flag->is_external(); duke@435: switch (flag->origin) { duke@435: case DEFAULT: duke@435: global->origin = JMM_VMGLOBAL_ORIGIN_DEFAULT; duke@435: break; duke@435: case COMMAND_LINE: duke@435: global->origin = JMM_VMGLOBAL_ORIGIN_COMMAND_LINE; duke@435: break; duke@435: case ENVIRON_VAR: duke@435: global->origin = JMM_VMGLOBAL_ORIGIN_ENVIRON_VAR; duke@435: break; duke@435: case CONFIG_FILE: duke@435: global->origin = JMM_VMGLOBAL_ORIGIN_CONFIG_FILE; duke@435: break; duke@435: case MANAGEMENT: duke@435: global->origin = JMM_VMGLOBAL_ORIGIN_MANAGEMENT; duke@435: break; duke@435: case ERGONOMIC: duke@435: global->origin = JMM_VMGLOBAL_ORIGIN_ERGONOMIC; duke@435: break; duke@435: default: duke@435: global->origin = JMM_VMGLOBAL_ORIGIN_OTHER; duke@435: } phh@1502: phh@1502: return true; duke@435: } duke@435: duke@435: // Fill globals array of count length with jmmVMGlobal entries duke@435: // specified by names. If names == NULL, fill globals array duke@435: // with all Flags. Return value is number of entries duke@435: // created in globals. duke@435: // If a Flag with a given name in an array element does not duke@435: // exist, globals[i].name will be set to NULL. duke@435: JVM_ENTRY(jint, jmm_GetVMGlobals(JNIEnv *env, duke@435: jobjectArray names, duke@435: jmmVMGlobal *globals, duke@435: jint count)) duke@435: duke@435: duke@435: if (globals == NULL) { duke@435: THROW_(vmSymbols::java_lang_NullPointerException(), 0); duke@435: } duke@435: duke@435: ResourceMark rm(THREAD); duke@435: duke@435: if (names != NULL) { duke@435: // return the requested globals duke@435: objArrayOop ta = objArrayOop(JNIHandles::resolve_non_null(names)); duke@435: objArrayHandle names_ah(THREAD, ta); duke@435: // Make sure we have a String array duke@435: klassOop element_klass = objArrayKlass::cast(names_ah->klass())->element_klass(); never@1577: if (element_klass != SystemDictionary::String_klass()) { duke@435: THROW_MSG_(vmSymbols::java_lang_IllegalArgumentException(), duke@435: "Array element type is not String class", 0); duke@435: } duke@435: duke@435: int names_length = names_ah->length(); duke@435: int num_entries = 0; duke@435: for (int i = 0; i < names_length && i < count; i++) { duke@435: oop s = names_ah->obj_at(i); duke@435: if (s == NULL) { duke@435: THROW_(vmSymbols::java_lang_NullPointerException(), 0); duke@435: } duke@435: duke@435: Handle sh(THREAD, s); duke@435: char* str = java_lang_String::as_utf8_string(s); duke@435: Flag* flag = Flag::find_flag(str, strlen(str)); phh@1502: if (flag != NULL && phh@1502: add_global_entry(env, sh, &globals[i], flag, THREAD)) { duke@435: num_entries++; duke@435: } else { duke@435: globals[i].name = NULL; duke@435: } duke@435: } duke@435: return num_entries; duke@435: } else { duke@435: // return all globals if names == NULL duke@435: duke@435: // last flag entry is always NULL, so subtract 1 duke@435: int nFlags = (int) Flag::numFlags - 1; duke@435: Handle null_h; duke@435: int num_entries = 0; duke@435: for (int i = 0; i < nFlags && num_entries < count; i++) { duke@435: Flag* flag = &Flag::flags[i]; ysr@785: // Exclude the locked (diagnostic, experimental) flags phh@1502: if ((flag->is_unlocked() || flag->is_unlocker()) && phh@1502: add_global_entry(env, null_h, &globals[num_entries], flag, THREAD)) { duke@435: num_entries++; duke@435: } duke@435: } duke@435: return num_entries; duke@435: } duke@435: JVM_END duke@435: duke@435: JVM_ENTRY(void, jmm_SetVMGlobal(JNIEnv *env, jstring flag_name, jvalue new_value)) duke@435: ResourceMark rm(THREAD); duke@435: duke@435: oop fn = JNIHandles::resolve_external_guard(flag_name); duke@435: if (fn == NULL) { duke@435: THROW_MSG(vmSymbols::java_lang_NullPointerException(), duke@435: "The flag name cannot be null."); duke@435: } duke@435: char* name = java_lang_String::as_utf8_string(fn); duke@435: Flag* flag = Flag::find_flag(name, strlen(name)); duke@435: if (flag == NULL) { duke@435: THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(), duke@435: "Flag does not exist."); duke@435: } duke@435: if (!flag->is_writeable()) { duke@435: THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(), duke@435: "This flag is not writeable."); duke@435: } duke@435: duke@435: bool succeed; duke@435: if (flag->is_bool()) { duke@435: bool bvalue = (new_value.z == JNI_TRUE ? true : false); duke@435: succeed = CommandLineFlags::boolAtPut(name, &bvalue, MANAGEMENT); duke@435: } else if (flag->is_intx()) { phh@1502: intx ivalue = (intx)new_value.j; duke@435: succeed = CommandLineFlags::intxAtPut(name, &ivalue, MANAGEMENT); duke@435: } else if (flag->is_uintx()) { phh@1502: uintx uvalue = (uintx)new_value.j; duke@435: succeed = CommandLineFlags::uintxAtPut(name, &uvalue, MANAGEMENT); phh@1502: } else if (flag->is_uint64_t()) { phh@1502: uint64_t uvalue = (uint64_t)new_value.j; phh@1502: succeed = CommandLineFlags::uint64_tAtPut(name, &uvalue, MANAGEMENT); duke@435: } else if (flag->is_ccstr()) { duke@435: oop str = JNIHandles::resolve_external_guard(new_value.l); duke@435: if (str == NULL) { duke@435: THROW(vmSymbols::java_lang_NullPointerException()); duke@435: } duke@435: ccstr svalue = java_lang_String::as_utf8_string(str); duke@435: succeed = CommandLineFlags::ccstrAtPut(name, &svalue, MANAGEMENT); duke@435: } duke@435: assert(succeed, "Setting flag should succeed"); duke@435: JVM_END duke@435: duke@435: class ThreadTimesClosure: public ThreadClosure { duke@435: private: duke@435: objArrayOop _names; duke@435: typeArrayOop _times; duke@435: int _names_len; duke@435: int _times_len; duke@435: int _count; duke@435: duke@435: public: duke@435: ThreadTimesClosure(objArrayOop names, typeArrayOop times); duke@435: virtual void do_thread(Thread* thread); duke@435: int count() { return _count; } duke@435: }; duke@435: duke@435: ThreadTimesClosure::ThreadTimesClosure(objArrayOop names, duke@435: typeArrayOop times) { duke@435: assert(names != NULL, "names was NULL"); duke@435: assert(times != NULL, "times was NULL"); duke@435: _names = names; duke@435: _names_len = names->length(); duke@435: _times = times; duke@435: _times_len = times->length(); duke@435: _count = 0; duke@435: } duke@435: duke@435: void ThreadTimesClosure::do_thread(Thread* thread) { duke@435: Handle s; duke@435: assert(thread != NULL, "thread was NULL"); duke@435: duke@435: // exclude externally visible JavaThreads duke@435: if (thread->is_Java_thread() && !thread->is_hidden_from_external_view()) { duke@435: return; duke@435: } duke@435: duke@435: if (_count >= _names_len || _count >= _times_len) { duke@435: // skip if the result array is not big enough duke@435: return; duke@435: } duke@435: duke@435: EXCEPTION_MARK; duke@435: duke@435: assert(thread->name() != NULL, "All threads should have a name"); duke@435: s = java_lang_String::create_from_str(thread->name(), CHECK); duke@435: _names->obj_at_put(_count, s()); duke@435: duke@435: _times->long_at_put(_count, os::is_thread_cpu_time_supported() ? duke@435: os::thread_cpu_time(thread) : -1); duke@435: _count++; duke@435: } duke@435: duke@435: // Fills names with VM internal thread names and times with the corresponding duke@435: // CPU times. If names or times is NULL, a NullPointerException is thrown. duke@435: // If the element type of names is not String, an IllegalArgumentException is duke@435: // thrown. duke@435: // If an array is not large enough to hold all the entries, only the entries duke@435: // that fit will be returned. Return value is the number of VM internal duke@435: // threads entries. duke@435: JVM_ENTRY(jint, jmm_GetInternalThreadTimes(JNIEnv *env, duke@435: jobjectArray names, duke@435: jlongArray times)) duke@435: if (names == NULL || times == NULL) { duke@435: THROW_(vmSymbols::java_lang_NullPointerException(), 0); duke@435: } duke@435: objArrayOop na = objArrayOop(JNIHandles::resolve_non_null(names)); duke@435: objArrayHandle names_ah(THREAD, na); duke@435: duke@435: // Make sure we have a String array duke@435: klassOop element_klass = objArrayKlass::cast(names_ah->klass())->element_klass(); never@1577: if (element_klass != SystemDictionary::String_klass()) { duke@435: THROW_MSG_(vmSymbols::java_lang_IllegalArgumentException(), duke@435: "Array element type is not String class", 0); duke@435: } duke@435: duke@435: typeArrayOop ta = typeArrayOop(JNIHandles::resolve_non_null(times)); duke@435: typeArrayHandle times_ah(THREAD, ta); duke@435: duke@435: ThreadTimesClosure ttc(names_ah(), times_ah()); duke@435: { duke@435: MutexLockerEx ml(Threads_lock); duke@435: Threads::threads_do(&ttc); duke@435: } duke@435: duke@435: return ttc.count(); duke@435: JVM_END duke@435: duke@435: static Handle find_deadlocks(bool object_monitors_only, TRAPS) { duke@435: ResourceMark rm(THREAD); duke@435: duke@435: VM_FindDeadlocks op(!object_monitors_only /* also check concurrent locks? */); duke@435: VMThread::execute(&op); duke@435: duke@435: DeadlockCycle* deadlocks = op.result(); duke@435: if (deadlocks == NULL) { duke@435: // no deadlock found and return duke@435: return Handle(); duke@435: } duke@435: duke@435: int num_threads = 0; duke@435: DeadlockCycle* cycle; duke@435: for (cycle = deadlocks; cycle != NULL; cycle = cycle->next()) { duke@435: num_threads += cycle->num_threads(); duke@435: } duke@435: never@1577: objArrayOop r = oopFactory::new_objArray(SystemDictionary::Thread_klass(), num_threads, CHECK_NH); duke@435: objArrayHandle threads_ah(THREAD, r); duke@435: duke@435: int index = 0; duke@435: for (cycle = deadlocks; cycle != NULL; cycle = cycle->next()) { duke@435: GrowableArray* deadlock_threads = cycle->threads(); duke@435: int len = deadlock_threads->length(); duke@435: for (int i = 0; i < len; i++) { duke@435: threads_ah->obj_at_put(index, deadlock_threads->at(i)->threadObj()); duke@435: index++; duke@435: } duke@435: } duke@435: return threads_ah; duke@435: } duke@435: duke@435: // Finds cycles of threads that are deadlocked involved in object monitors duke@435: // and JSR-166 synchronizers. duke@435: // Returns an array of Thread objects which are in deadlock, if any. duke@435: // Otherwise, returns NULL. duke@435: // duke@435: // Input parameter: duke@435: // object_monitors_only - if true, only check object monitors duke@435: // duke@435: JVM_ENTRY(jobjectArray, jmm_FindDeadlockedThreads(JNIEnv *env, jboolean object_monitors_only)) duke@435: Handle result = find_deadlocks(object_monitors_only != 0, CHECK_0); duke@435: return (jobjectArray) JNIHandles::make_local(env, result()); duke@435: JVM_END duke@435: duke@435: // Finds cycles of threads that are deadlocked on monitor locks duke@435: // Returns an array of Thread objects which are in deadlock, if any. duke@435: // Otherwise, returns NULL. duke@435: JVM_ENTRY(jobjectArray, jmm_FindMonitorDeadlockedThreads(JNIEnv *env)) duke@435: Handle result = find_deadlocks(true, CHECK_0); duke@435: return (jobjectArray) JNIHandles::make_local(env, result()); duke@435: JVM_END duke@435: duke@435: // Gets the information about GC extension attributes including duke@435: // the name of the attribute, its type, and a short description. duke@435: // duke@435: // Input parameters: duke@435: // mgr - GC memory manager duke@435: // info - caller allocated array of jmmExtAttributeInfo duke@435: // count - number of elements of the info array duke@435: // duke@435: // Returns the number of GC extension attributes filled in the info array; or duke@435: // -1 if info is not big enough duke@435: // duke@435: JVM_ENTRY(jint, jmm_GetGCExtAttributeInfo(JNIEnv *env, jobject mgr, jmmExtAttributeInfo* info, jint count)) duke@435: // All GC memory managers have 1 attribute (number of GC threads) duke@435: if (count == 0) { duke@435: return 0; duke@435: } duke@435: duke@435: if (info == NULL) { duke@435: THROW_(vmSymbols::java_lang_NullPointerException(), 0); duke@435: } duke@435: duke@435: info[0].name = "GcThreadCount"; duke@435: info[0].type = 'I'; duke@435: info[0].description = "Number of GC threads"; duke@435: return 1; duke@435: JVM_END duke@435: duke@435: // verify the given array is an array of java/lang/management/MemoryUsage objects duke@435: // of a given length and return the objArrayOop duke@435: static objArrayOop get_memory_usage_objArray(jobjectArray array, int length, TRAPS) { duke@435: if (array == NULL) { duke@435: THROW_(vmSymbols::java_lang_NullPointerException(), 0); duke@435: } duke@435: duke@435: objArrayOop oa = objArrayOop(JNIHandles::resolve_non_null(array)); duke@435: objArrayHandle array_h(THREAD, oa); duke@435: duke@435: // array must be of the given length duke@435: if (length != array_h->length()) { duke@435: THROW_MSG_(vmSymbols::java_lang_IllegalArgumentException(), duke@435: "The length of the given MemoryUsage array does not match the number of memory pools.", 0); duke@435: } duke@435: duke@435: // check if the element of array is of type MemoryUsage class duke@435: klassOop usage_klass = Management::java_lang_management_MemoryUsage_klass(CHECK_0); duke@435: klassOop element_klass = objArrayKlass::cast(array_h->klass())->element_klass(); duke@435: if (element_klass != usage_klass) { duke@435: THROW_MSG_(vmSymbols::java_lang_IllegalArgumentException(), duke@435: "The element type is not MemoryUsage class", 0); duke@435: } duke@435: duke@435: return array_h(); duke@435: } duke@435: duke@435: // Gets the statistics of the last GC of a given GC memory manager. duke@435: // Input parameters: duke@435: // obj - GarbageCollectorMXBean object duke@435: // gc_stat - caller allocated jmmGCStat where: duke@435: // a. before_gc_usage - array of MemoryUsage objects duke@435: // b. after_gc_usage - array of MemoryUsage objects duke@435: // c. gc_ext_attributes_values_size is set to the duke@435: // gc_ext_attribute_values array allocated duke@435: // d. gc_ext_attribute_values is a caller allocated array of jvalue. duke@435: // duke@435: // On return, duke@435: // gc_index == 0 indicates no GC statistics available duke@435: // duke@435: // before_gc_usage and after_gc_usage - filled with per memory pool duke@435: // before and after GC usage in the same order as the memory pools duke@435: // returned by GetMemoryPools for a given GC memory manager. duke@435: // num_gc_ext_attributes indicates the number of elements in duke@435: // the gc_ext_attribute_values array is filled; or duke@435: // -1 if the gc_ext_attributes_values array is not big enough duke@435: // duke@435: JVM_ENTRY(void, jmm_GetLastGCStat(JNIEnv *env, jobject obj, jmmGCStat *gc_stat)) duke@435: ResourceMark rm(THREAD); duke@435: duke@435: if (gc_stat->gc_ext_attribute_values_size > 0 && gc_stat->gc_ext_attribute_values == NULL) { duke@435: THROW(vmSymbols::java_lang_NullPointerException()); duke@435: } duke@435: duke@435: // Get the GCMemoryManager duke@435: GCMemoryManager* mgr = get_gc_memory_manager_from_jobject(obj, CHECK); duke@435: duke@435: // Make a copy of the last GC statistics duke@435: // GC may occur while constructing the last GC information duke@435: int num_pools = MemoryService::num_memory_pools(); duke@435: GCStatInfo* stat = new GCStatInfo(num_pools); kevinw@2058: if (mgr->get_last_gc_stat(stat) == 0) { kevinw@2058: gc_stat->gc_index = 0; kevinw@2058: return; kevinw@2058: } duke@435: duke@435: gc_stat->gc_index = stat->gc_index(); duke@435: gc_stat->start_time = Management::ticks_to_ms(stat->start_time()); duke@435: gc_stat->end_time = Management::ticks_to_ms(stat->end_time()); duke@435: duke@435: // Current implementation does not have GC extension attributes duke@435: gc_stat->num_gc_ext_attributes = 0; duke@435: duke@435: // Fill the arrays of MemoryUsage objects with before and after GC duke@435: // per pool memory usage duke@435: objArrayOop bu = get_memory_usage_objArray(gc_stat->usage_before_gc, duke@435: num_pools, duke@435: CHECK); duke@435: objArrayHandle usage_before_gc_ah(THREAD, bu); duke@435: duke@435: objArrayOop au = get_memory_usage_objArray(gc_stat->usage_after_gc, duke@435: num_pools, duke@435: CHECK); duke@435: objArrayHandle usage_after_gc_ah(THREAD, au); duke@435: duke@435: for (int i = 0; i < num_pools; i++) { duke@435: Handle before_usage = MemoryService::create_MemoryUsage_obj(stat->before_gc_usage_for_pool(i), CHECK); duke@435: Handle after_usage; duke@435: duke@435: MemoryUsage u = stat->after_gc_usage_for_pool(i); duke@435: if (u.max_size() == 0 && u.used() > 0) { duke@435: // If max size == 0, this pool is a survivor space. duke@435: // Set max size = -1 since the pools will be swapped after GC. duke@435: MemoryUsage usage(u.init_size(), u.used(), u.committed(), (size_t)-1); duke@435: after_usage = MemoryService::create_MemoryUsage_obj(usage, CHECK); duke@435: } else { duke@435: after_usage = MemoryService::create_MemoryUsage_obj(stat->after_gc_usage_for_pool(i), CHECK); duke@435: } duke@435: usage_before_gc_ah->obj_at_put(i, before_usage()); duke@435: usage_after_gc_ah->obj_at_put(i, after_usage()); duke@435: } duke@435: duke@435: if (gc_stat->gc_ext_attribute_values_size > 0) { duke@435: // Current implementation only has 1 attribute (number of GC threads) duke@435: // The type is 'I' duke@435: gc_stat->gc_ext_attribute_values[0].i = mgr->num_gc_threads(); duke@435: } duke@435: JVM_END duke@435: fparain@2888: JVM_ENTRY(void, jmm_SetGCNotificationEnabled(JNIEnv *env, jobject obj, jboolean enabled)) fparain@2888: ResourceMark rm(THREAD); fparain@2888: // Get the GCMemoryManager fparain@2888: GCMemoryManager* mgr = get_gc_memory_manager_from_jobject(obj, CHECK); fparain@2888: mgr->set_notification_enabled(enabled?true:false); fparain@2888: JVM_END fparain@2888: duke@435: // Dump heap - Returns 0 if succeeds. duke@435: JVM_ENTRY(jint, jmm_DumpHeap0(JNIEnv *env, jstring outputfile, jboolean live)) duke@435: #ifndef SERVICES_KERNEL duke@435: ResourceMark rm(THREAD); duke@435: oop on = JNIHandles::resolve_external_guard(outputfile); duke@435: if (on == NULL) { duke@435: THROW_MSG_(vmSymbols::java_lang_NullPointerException(), duke@435: "Output file name cannot be null.", -1); duke@435: } duke@435: char* name = java_lang_String::as_utf8_string(on); duke@435: if (name == NULL) { duke@435: THROW_MSG_(vmSymbols::java_lang_NullPointerException(), duke@435: "Output file name cannot be null.", -1); duke@435: } duke@435: HeapDumper dumper(live ? true : false); duke@435: if (dumper.dump(name) != 0) { duke@435: const char* errmsg = dumper.error_as_C_string(); duke@435: THROW_MSG_(vmSymbols::java_io_IOException(), errmsg, -1); duke@435: } duke@435: return 0; duke@435: #else // SERVICES_KERNEL duke@435: return -1; duke@435: #endif // SERVICES_KERNEL duke@435: JVM_END duke@435: fparain@3329: JVM_ENTRY(jobjectArray, jmm_GetDiagnosticCommands(JNIEnv *env)) fparain@3329: ResourceMark rm(THREAD); fparain@3329: GrowableArray* dcmd_list = DCmdFactory::DCmd_list(); fparain@3329: objArrayOop cmd_array_oop = oopFactory::new_objArray(SystemDictionary::String_klass(), fparain@3329: dcmd_list->length(), CHECK_NULL); fparain@3329: objArrayHandle cmd_array(THREAD, cmd_array_oop); fparain@3329: for (int i = 0; i < dcmd_list->length(); i++) { fparain@3329: oop cmd_name = java_lang_String::create_oop_from_str(dcmd_list->at(i), CHECK_NULL); fparain@3329: cmd_array->obj_at_put(i, cmd_name); fparain@3329: } fparain@3329: return (jobjectArray) JNIHandles::make_local(env, cmd_array()); fparain@3329: JVM_END fparain@3329: fparain@3329: JVM_ENTRY(void, jmm_GetDiagnosticCommandInfo(JNIEnv *env, jobjectArray cmds, fparain@3329: dcmdInfo* infoArray)) fparain@3329: if (cmds == NULL || infoArray == NULL) { fparain@3329: THROW(vmSymbols::java_lang_NullPointerException()); fparain@3329: } fparain@3329: fparain@3329: ResourceMark rm(THREAD); fparain@3329: fparain@3329: objArrayOop ca = objArrayOop(JNIHandles::resolve_non_null(cmds)); fparain@3329: objArrayHandle cmds_ah(THREAD, ca); fparain@3329: fparain@3329: // Make sure we have a String array fparain@3329: klassOop element_klass = objArrayKlass::cast(cmds_ah->klass())->element_klass(); fparain@3329: if (element_klass != SystemDictionary::String_klass()) { fparain@3329: THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(), fparain@3329: "Array element type is not String class"); fparain@3329: } fparain@3329: fparain@3329: GrowableArray* info_list = DCmdFactory::DCmdInfo_list(); fparain@3329: fparain@3329: int num_cmds = cmds_ah->length(); fparain@3329: for (int i = 0; i < num_cmds; i++) { fparain@3329: oop cmd = cmds_ah->obj_at(i); fparain@3329: if (cmd == NULL) { fparain@3329: THROW_MSG(vmSymbols::java_lang_NullPointerException(), fparain@3329: "Command name cannot be null."); fparain@3329: } fparain@3329: char* cmd_name = java_lang_String::as_utf8_string(cmd); fparain@3329: if (cmd_name == NULL) { fparain@3329: THROW_MSG(vmSymbols::java_lang_NullPointerException(), fparain@3329: "Command name cannot be null."); fparain@3329: } fparain@3329: int pos = info_list->find((void*)cmd_name,DCmdInfo::by_name); fparain@3329: if (pos == -1) { fparain@3329: THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(), fparain@3329: "Unknown diagnostic command"); fparain@3329: } fparain@3329: DCmdInfo* info = info_list->at(pos); fparain@3329: infoArray[i].name = info->name(); fparain@3329: infoArray[i].description = info->description(); fparain@3329: infoArray[i].impact = info->impact(); fparain@3329: infoArray[i].num_arguments = info->num_arguments(); fparain@3329: infoArray[i].enabled = info->is_enabled(); fparain@3329: } fparain@3329: JVM_END fparain@3329: fparain@3329: JVM_ENTRY(void, jmm_GetDiagnosticCommandArgumentsInfo(JNIEnv *env, fparain@3329: jstring command, dcmdArgInfo* infoArray)) fparain@3329: ResourceMark rm(THREAD); fparain@3329: oop cmd = JNIHandles::resolve_external_guard(command); fparain@3329: if (cmd == NULL) { fparain@3329: THROW_MSG(vmSymbols::java_lang_NullPointerException(), fparain@3329: "Command line cannot be null."); fparain@3329: } fparain@3329: char* cmd_name = java_lang_String::as_utf8_string(cmd); fparain@3329: if (cmd_name == NULL) { fparain@3329: THROW_MSG(vmSymbols::java_lang_NullPointerException(), fparain@3329: "Command line content cannot be null."); fparain@3329: } fparain@3329: DCmd* dcmd = NULL; fparain@3329: DCmdFactory*factory = DCmdFactory::factory(cmd_name, strlen(cmd_name)); fparain@3329: if (factory != NULL) { fparain@3329: dcmd = factory->create_resource_instance(NULL); fparain@3329: } fparain@3329: if (dcmd == NULL) { fparain@3329: THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(), fparain@3329: "Unknown diagnostic command"); fparain@3329: } fparain@3329: DCmdMark mark(dcmd); fparain@3329: GrowableArray* array = dcmd->argument_info_array(); fparain@3329: if (array->length() == 0) { fparain@3329: return; fparain@3329: } fparain@3329: for (int i = 0; i < array->length(); i++) { fparain@3329: infoArray[i].name = array->at(i)->name(); fparain@3329: infoArray[i].description = array->at(i)->description(); fparain@3329: infoArray[i].type = array->at(i)->type(); fparain@3329: infoArray[i].default_string = array->at(i)->default_string(); fparain@3329: infoArray[i].mandatory = array->at(i)->is_mandatory(); fparain@3329: infoArray[i].option = array->at(i)->is_option(); fparain@3329: infoArray[i].position = array->at(i)->position(); fparain@3329: } fparain@3329: return; fparain@3329: JVM_END fparain@3329: fparain@3329: JVM_ENTRY(jstring, jmm_ExecuteDiagnosticCommand(JNIEnv *env, jstring commandline)) fparain@3329: ResourceMark rm(THREAD); fparain@3329: oop cmd = JNIHandles::resolve_external_guard(commandline); fparain@3329: if (cmd == NULL) { fparain@3329: THROW_MSG_NULL(vmSymbols::java_lang_NullPointerException(), fparain@3329: "Command line cannot be null."); fparain@3329: } fparain@3329: char* cmdline = java_lang_String::as_utf8_string(cmd); fparain@3329: if (cmdline == NULL) { fparain@3329: THROW_MSG_NULL(vmSymbols::java_lang_NullPointerException(), fparain@3329: "Command line content cannot be null."); fparain@3329: } fparain@3329: bufferedStream output; fparain@3329: DCmd::parse_and_execute(&output, cmdline, ' ', CHECK_NULL); fparain@3329: oop result = java_lang_String::create_oop_from_str(output.as_string(), CHECK_NULL); fparain@3329: return (jstring) JNIHandles::make_local(env, result); fparain@3329: JVM_END fparain@3329: duke@435: jlong Management::ticks_to_ms(jlong ticks) { duke@435: assert(os::elapsed_frequency() > 0, "Must be non-zero"); duke@435: return (jlong)(((double)ticks / (double)os::elapsed_frequency()) duke@435: * (double)1000.0); duke@435: } duke@435: duke@435: const struct jmmInterface_1_ jmm_interface = { duke@435: NULL, duke@435: NULL, duke@435: jmm_GetVersion, duke@435: jmm_GetOptionalSupport, duke@435: jmm_GetInputArguments, duke@435: jmm_GetThreadInfo, duke@435: jmm_GetInputArgumentArray, duke@435: jmm_GetMemoryPools, duke@435: jmm_GetMemoryManagers, duke@435: jmm_GetMemoryPoolUsage, duke@435: jmm_GetPeakMemoryPoolUsage, phh@2423: jmm_GetThreadAllocatedMemory, duke@435: jmm_GetMemoryUsage, duke@435: jmm_GetLongAttribute, duke@435: jmm_GetBoolAttribute, duke@435: jmm_SetBoolAttribute, duke@435: jmm_GetLongAttributes, duke@435: jmm_FindMonitorDeadlockedThreads, duke@435: jmm_GetThreadCpuTime, duke@435: jmm_GetVMGlobalNames, duke@435: jmm_GetVMGlobals, duke@435: jmm_GetInternalThreadTimes, duke@435: jmm_ResetStatistic, duke@435: jmm_SetPoolSensor, duke@435: jmm_SetPoolThreshold, duke@435: jmm_GetPoolCollectionUsage, duke@435: jmm_GetGCExtAttributeInfo, duke@435: jmm_GetLastGCStat, duke@435: jmm_GetThreadCpuTimeWithKind, phh@2423: jmm_GetThreadCpuTimesWithKind, duke@435: jmm_DumpHeap0, duke@435: jmm_FindDeadlockedThreads, duke@435: jmm_SetVMGlobal, duke@435: NULL, fparain@2888: jmm_DumpThreads, fparain@3329: jmm_SetGCNotificationEnabled, fparain@3329: jmm_GetDiagnosticCommands, fparain@3329: jmm_GetDiagnosticCommandInfo, fparain@3329: jmm_GetDiagnosticCommandArgumentsInfo, fparain@3329: jmm_ExecuteDiagnosticCommand duke@435: }; duke@435: duke@435: void* Management::get_jmm_interface(int version) { duke@435: if (version == JMM_VERSION_1_0) { duke@435: return (void*) &jmm_interface; duke@435: } duke@435: return NULL; duke@435: }