24
25 #include "precompiled.hpp"
26 #include "classfile/systemDictionary.hpp"
27 #include "compiler/compileBroker.hpp"
28 #include "memory/iterator.hpp"
29 #include "memory/oopFactory.hpp"
30 #include "memory/resourceArea.hpp"
31 #include "oops/klass.hpp"
32 #include "oops/objArrayKlass.hpp"
33 #include "oops/objArrayOop.inline.hpp"
34 #include "oops/oop.inline.hpp"
35 #include "runtime/arguments.hpp"
36 #include "runtime/globals.hpp"
37 #include "runtime/handles.inline.hpp"
38 #include "runtime/interfaceSupport.hpp"
39 #include "runtime/javaCalls.hpp"
40 #include "runtime/jniHandles.hpp"
41 #include "runtime/os.hpp"
42 #include "runtime/serviceThread.hpp"
43 #include "runtime/thread.inline.hpp"
44 #include "services/classLoadingService.hpp"
45 #include "services/diagnosticCommand.hpp"
46 #include "services/diagnosticFramework.hpp"
47 #include "services/writeableFlags.hpp"
48 #include "services/heapDumper.hpp"
49 #include "services/jmm.h"
50 #include "services/lowMemoryDetector.hpp"
51 #include "services/gcNotifier.hpp"
52 #include "services/nmtDCmd.hpp"
53 #include "services/management.hpp"
54 #include "services/memoryManager.hpp"
55 #include "services/memoryPool.hpp"
56 #include "services/memoryService.hpp"
57 #include "services/runtimeService.hpp"
58 #include "services/threadService.hpp"
59 #include "utilities/debug.hpp"
60 #include "utilities/formatBuffer.hpp"
61 #include "utilities/macros.hpp"
62
63 PerfVariable* Management::_begin_vm_creation_time = NULL;
1008 }
1009 }
1010 }
1011 return num_atts;
1012 JVM_END
1013
1014 // Helper function to do thread dump for a specific list of threads
1015 static void do_thread_dump(ThreadDumpResult* dump_result,
1016 typeArrayHandle ids_ah, // array of thread ID (long[])
1017 int num_threads,
1018 int max_depth,
1019 bool with_locked_monitors,
1020 bool with_locked_synchronizers,
1021 TRAPS) {
1022 // no need to actually perform thread dump if no TIDs are specified
1023 if (num_threads == 0) return;
1024
1025 // First get an array of threadObj handles.
1026 // A JavaThread may terminate before we get the stack trace.
1027 GrowableArray<instanceHandle>* thread_handle_array = new GrowableArray<instanceHandle>(num_threads);
1028 {
1029 MutexLockerEx ml(Threads_lock);
1030 for (int i = 0; i < num_threads; i++) {
1031 jlong tid = ids_ah->long_at(i);
1032 JavaThread* jt = Threads::find_java_thread_from_java_tid(tid);
1033 oop thread_obj = (jt != NULL ? jt->threadObj() : (oop)NULL);
1034 instanceHandle threadObj_h(THREAD, (instanceOop) thread_obj);
1035 thread_handle_array->append(threadObj_h);
1036 }
1037 }
1038
1039 // Obtain thread dumps and thread snapshot information
1040 VM_ThreadDump op(dump_result,
1041 thread_handle_array,
1042 num_threads,
1043 max_depth, /* stack depth */
1044 with_locked_monitors,
1045 with_locked_synchronizers);
1046 VMThread::execute(&op);
1047 }
1048
1049 // Gets an array of ThreadInfo objects. Each element is the ThreadInfo
1050 // for the thread ID specified in the corresponding entry in
1051 // the given array of thread IDs; or NULL if the thread does not exist
1052 // or has terminated.
1084 // validate the ThreadInfo[] parameters
1085 validate_thread_info_array(infoArray_h, CHECK_0);
1086
1087 // infoArray must be of the same length as the given array of thread IDs
1088 int num_threads = ids_ah->length();
1089 if (num_threads != infoArray_h->length()) {
1090 THROW_MSG_(vmSymbols::java_lang_IllegalArgumentException(),
1091 "The length of the given ThreadInfo array does not match the length of the given array of thread IDs", -1);
1092 }
1093
1094 // make sure the AbstractOwnableSynchronizer klass is loaded before taking thread snapshots
1095 java_util_concurrent_locks_AbstractOwnableSynchronizer::initialize(CHECK_0);
1096
1097 // Must use ThreadDumpResult to store the ThreadSnapshot.
1098 // GC may occur after the thread snapshots are taken but before
1099 // this function returns. The threadObj and other oops kept
1100 // in the ThreadSnapshot are marked and adjusted during GC.
1101 ThreadDumpResult dump_result(num_threads);
1102
1103 if (maxDepth == 0) {
1104 // no stack trace dumped - do not need to stop the world
1105 {
1106 MutexLockerEx ml(Threads_lock);
1107 for (int i = 0; i < num_threads; i++) {
1108 jlong tid = ids_ah->long_at(i);
1109 JavaThread* jt = Threads::find_java_thread_from_java_tid(tid);
1110 ThreadSnapshot* ts;
1111 if (jt == NULL) {
1112 // if the thread does not exist or now it is terminated,
1113 // create dummy snapshot
1114 ts = new ThreadSnapshot();
1115 } else {
1116 ts = new ThreadSnapshot(jt);
1117 }
1118 dump_result.add_thread_snapshot(ts);
1119 }
1120 }
1121 } else {
1122 // obtain thread dump with the specific list of threads with stack trace
1123 do_thread_dump(&dump_result,
1124 ids_ah,
1125 num_threads,
1126 maxDepth,
1127 false, /* no locked monitor */
1128 false, /* no locked synchronizers */
1129 CHECK_0);
1130 }
1131
1132 int num_snapshots = dump_result.num_snapshots();
1133 assert(num_snapshots == num_threads, "Must match the number of thread snapshots");
1134 int index = 0;
1135 for (ThreadSnapshot* ts = dump_result.snapshots(); ts != NULL; index++, ts = ts->next()) {
1136 // For each thread, create an java/lang/management/ThreadInfo object
1137 // and fill with the thread information
1138
1139 if (ts->threadObj() == NULL) {
1140 // if the thread does not exist or now it is terminated, set threadinfo to NULL
1141 infoArray_h->obj_at_put(index, NULL);
1142 continue;
1143 }
1144
1145 // Create java.lang.management.ThreadInfo object
1146 instanceOop info_obj = Management::create_thread_info_instance(ts, CHECK_0);
1147 infoArray_h->obj_at_put(index, info_obj);
1148 }
1149 return 0;
1150 JVM_END
1151
1152 // Dump thread info for the specified threads.
1153 // It returns an array of ThreadInfo objects. Each element is the ThreadInfo
1178 validate_thread_id_array(ids_ah, CHECK_NULL);
1179
1180 // obtain thread dump of a specific list of threads
1181 do_thread_dump(&dump_result,
1182 ids_ah,
1183 num_threads,
1184 -1, /* entire stack */
1185 (locked_monitors ? true : false), /* with locked monitors */
1186 (locked_synchronizers ? true : false), /* with locked synchronizers */
1187 CHECK_NULL);
1188 } else {
1189 // obtain thread dump of all threads
1190 VM_ThreadDump op(&dump_result,
1191 -1, /* entire stack */
1192 (locked_monitors ? true : false), /* with locked monitors */
1193 (locked_synchronizers ? true : false) /* with locked synchronizers */);
1194 VMThread::execute(&op);
1195 }
1196
1197 int num_snapshots = dump_result.num_snapshots();
1198
1199 // create the result ThreadInfo[] object
1200 InstanceKlass* ik = Management::java_lang_management_ThreadInfo_klass(CHECK_NULL);
1201 objArrayOop r = oopFactory::new_objArray(ik, num_snapshots, CHECK_NULL);
1202 objArrayHandle result_h(THREAD, r);
1203
1204 int index = 0;
1205 for (ThreadSnapshot* ts = dump_result.snapshots(); ts != NULL; ts = ts->next(), index++) {
1206 if (ts->threadObj() == NULL) {
1207 // if the thread does not exist or now it is terminated, set threadinfo to NULL
1208 result_h->obj_at_put(index, NULL);
1209 continue;
1210 }
1211
1212 ThreadStackTrace* stacktrace = ts->get_stack_trace();
1213 assert(stacktrace != NULL, "Must have a stack trace dumped");
1214
1215 // Create Object[] filled with locked monitors
1216 // Create int[] filled with the stack depth where a monitor was locked
1217 int num_frames = stacktrace->get_stack_depth();
1301 // For PEAK_POOL_USAGE stat, obj is required to be a memory pool object.
1302 // For THREAD_CONTENTION_COUNT and TIME stat, obj is required to be a thread ID.
1303 // type - the type of statistic to be reset
1304 //
1305 JVM_ENTRY(jboolean, jmm_ResetStatistic(JNIEnv *env, jvalue obj, jmmStatisticType type))
1306 ResourceMark rm(THREAD);
1307
1308 switch (type) {
1309 case JMM_STAT_PEAK_THREAD_COUNT:
1310 ThreadService::reset_peak_thread_count();
1311 return true;
1312
1313 case JMM_STAT_THREAD_CONTENTION_COUNT:
1314 case JMM_STAT_THREAD_CONTENTION_TIME: {
1315 jlong tid = obj.j;
1316 if (tid < 0) {
1317 THROW_(vmSymbols::java_lang_IllegalArgumentException(), JNI_FALSE);
1318 }
1319
1320 // Look for the JavaThread of this given tid
1321 MutexLockerEx ml(Threads_lock);
1322 if (tid == 0) {
1323 // reset contention statistics for all threads if tid == 0
1324 for (JavaThread* java_thread = Threads::first(); java_thread != NULL; java_thread = java_thread->next()) {
1325 if (type == JMM_STAT_THREAD_CONTENTION_COUNT) {
1326 ThreadService::reset_contention_count_stat(java_thread);
1327 } else {
1328 ThreadService::reset_contention_time_stat(java_thread);
1329 }
1330 }
1331 } else {
1332 // reset contention statistics for a given thread
1333 JavaThread* java_thread = Threads::find_java_thread_from_java_tid(tid);
1334 if (java_thread == NULL) {
1335 return false;
1336 }
1337
1338 if (type == JMM_STAT_THREAD_CONTENTION_COUNT) {
1339 ThreadService::reset_contention_count_stat(java_thread);
1340 } else {
1341 ThreadService::reset_contention_time_stat(java_thread);
1342 }
1343 }
1344 return true;
1345 break;
1346 }
1347 case JMM_STAT_PEAK_POOL_USAGE: {
1348 jobject o = obj.l;
1349 if (o == NULL) {
1350 THROW_(vmSymbols::java_lang_NullPointerException(), JNI_FALSE);
1351 }
1352
1353 oop pool_obj = JNIHandles::resolve(o);
1381 JVM_END
1382
1383 // Returns the fast estimate of CPU time consumed by
1384 // a given thread (in nanoseconds).
1385 // If thread_id == 0, return CPU time for the current thread.
1386 JVM_ENTRY(jlong, jmm_GetThreadCpuTime(JNIEnv *env, jlong thread_id))
1387 if (!os::is_thread_cpu_time_supported()) {
1388 return -1;
1389 }
1390
1391 if (thread_id < 0) {
1392 THROW_MSG_(vmSymbols::java_lang_IllegalArgumentException(),
1393 "Invalid thread ID", -1);
1394 }
1395
1396 JavaThread* java_thread = NULL;
1397 if (thread_id == 0) {
1398 // current thread
1399 return os::current_thread_cpu_time();
1400 } else {
1401 MutexLockerEx ml(Threads_lock);
1402 java_thread = Threads::find_java_thread_from_java_tid(thread_id);
1403 if (java_thread != NULL) {
1404 return os::thread_cpu_time((Thread*) java_thread);
1405 }
1406 }
1407 return -1;
1408 JVM_END
1409
1410 // Returns a String array of all VM global flag names
1411 JVM_ENTRY(jobjectArray, jmm_GetVMGlobalNames(JNIEnv *env))
1412 // last flag entry is always NULL, so subtract 1
1413 int nFlags = (int) Flag::numFlags - 1;
1414 // allocate a temp array
1415 objArrayOop r = oopFactory::new_objArray(SystemDictionary::String_klass(),
1416 nFlags, CHECK_0);
1417 objArrayHandle flags_ah(THREAD, r);
1418 int num_entries = 0;
1419 for (int i = 0; i < nFlags; i++) {
1420 Flag* flag = &Flag::flags[i];
1421 // Exclude notproduct and develop flags in product builds.
1422 if (flag->is_constant_in_binary()) {
1631 void do_unlocked();
1632 int count() { return _count; }
1633 };
1634
1635 ThreadTimesClosure::ThreadTimesClosure(objArrayHandle names,
1636 typeArrayHandle times) {
1637 assert(names() != NULL, "names was NULL");
1638 assert(times() != NULL, "times was NULL");
1639 _names_strings = names;
1640 _names_len = names->length();
1641 _names_chars = NEW_C_HEAP_ARRAY(char*, _names_len, mtInternal);
1642 _times = times;
1643 _times_len = times->length();
1644 _count = 0;
1645 }
1646
1647 //
1648 // Called with Threads_lock held
1649 //
1650 void ThreadTimesClosure::do_thread(Thread* thread) {
1651 assert(thread != NULL, "thread was NULL");
1652
1653 // exclude externally visible JavaThreads
1654 if (thread->is_Java_thread() && !thread->is_hidden_from_external_view()) {
1655 return;
1656 }
1657
1658 if (_count >= _names_len || _count >= _times_len) {
1659 // skip if the result array is not big enough
1660 return;
1661 }
1662
1663 EXCEPTION_MARK;
1664 ResourceMark rm(THREAD); // thread->name() uses ResourceArea
1665
1666 assert(thread->name() != NULL, "All threads should have a name");
1667 _names_chars[_count] = os::strdup(thread->name());
1668 _times->long_at_put(_count, os::is_thread_cpu_time_supported() ?
1669 os::thread_cpu_time(thread) : -1);
1670 _count++;
2091 }
2092
2093 ResourceMark rm(THREAD);
2094 typeArrayOop ta = typeArrayOop(JNIHandles::resolve_non_null(ids));
2095 typeArrayHandle ids_ah(THREAD, ta);
2096
2097 typeArrayOop sa = typeArrayOop(JNIHandles::resolve_non_null(sizeArray));
2098 typeArrayHandle sizeArray_h(THREAD, sa);
2099
2100 // validate the thread id array
2101 validate_thread_id_array(ids_ah, CHECK);
2102
2103 // sizeArray must be of the same length as the given array of thread IDs
2104 int num_threads = ids_ah->length();
2105 if (num_threads != sizeArray_h->length()) {
2106 THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(),
2107 "The length of the given long array does not match the length of "
2108 "the given array of thread IDs");
2109 }
2110
2111 MutexLockerEx ml(Threads_lock);
2112 for (int i = 0; i < num_threads; i++) {
2113 JavaThread* java_thread = Threads::find_java_thread_from_java_tid(ids_ah->long_at(i));
2114 if (java_thread != NULL) {
2115 sizeArray_h->long_at_put(i, java_thread->cooked_allocated_bytes());
2116 }
2117 }
2118 JVM_END
2119
2120 // Returns the CPU time consumed by a given thread (in nanoseconds).
2121 // If thread_id == 0, CPU time for the current thread is returned.
2122 // If user_sys_cpu_time = true, user level and system CPU time of
2123 // a given thread is returned; otherwise, only user level CPU time
2124 // is returned.
2125 JVM_ENTRY(jlong, jmm_GetThreadCpuTimeWithKind(JNIEnv *env, jlong thread_id, jboolean user_sys_cpu_time))
2126 if (!os::is_thread_cpu_time_supported()) {
2127 return -1;
2128 }
2129
2130 if (thread_id < 0) {
2131 THROW_MSG_(vmSymbols::java_lang_IllegalArgumentException(),
2132 "Invalid thread ID", -1);
2133 }
2134
2135 JavaThread* java_thread = NULL;
2136 if (thread_id == 0) {
2137 // current thread
2138 return os::current_thread_cpu_time(user_sys_cpu_time != 0);
2139 } else {
2140 MutexLockerEx ml(Threads_lock);
2141 java_thread = Threads::find_java_thread_from_java_tid(thread_id);
2142 if (java_thread != NULL) {
2143 return os::thread_cpu_time((Thread*) java_thread, user_sys_cpu_time != 0);
2144 }
2145 }
2146 return -1;
2147 JVM_END
2148
2149 // Gets an array containing the CPU times consumed by a set of threads
2150 // (in nanoseconds). Each element of the array is the CPU time for the
2151 // thread ID specified in the corresponding entry in the given array
2152 // of thread IDs; or -1 if the thread does not exist or has terminated.
2153 // If user_sys_cpu_time = true, the sum of user level and system CPU time
2154 // for the given thread is returned; otherwise, only user level CPU time
2155 // is returned.
2156 JVM_ENTRY(void, jmm_GetThreadCpuTimesWithKind(JNIEnv *env, jlongArray ids,
2157 jlongArray timeArray,
2158 jboolean user_sys_cpu_time))
2159 // Check if threads is null
2160 if (ids == NULL || timeArray == NULL) {
2161 THROW(vmSymbols::java_lang_NullPointerException());
2162 }
2163
2164 ResourceMark rm(THREAD);
2165 typeArrayOop ta = typeArrayOop(JNIHandles::resolve_non_null(ids));
2166 typeArrayHandle ids_ah(THREAD, ta);
2167
2168 typeArrayOop tia = typeArrayOop(JNIHandles::resolve_non_null(timeArray));
2169 typeArrayHandle timeArray_h(THREAD, tia);
2170
2171 // validate the thread id array
2172 validate_thread_id_array(ids_ah, CHECK);
2173
2174 // timeArray must be of the same length as the given array of thread IDs
2175 int num_threads = ids_ah->length();
2176 if (num_threads != timeArray_h->length()) {
2177 THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(),
2178 "The length of the given long array does not match the length of "
2179 "the given array of thread IDs");
2180 }
2181
2182 MutexLockerEx ml(Threads_lock);
2183 for (int i = 0; i < num_threads; i++) {
2184 JavaThread* java_thread = Threads::find_java_thread_from_java_tid(ids_ah->long_at(i));
2185 if (java_thread != NULL) {
2186 timeArray_h->long_at_put(i, os::thread_cpu_time((Thread*)java_thread,
2187 user_sys_cpu_time != 0));
2188 }
2189 }
2190 JVM_END
2191
2192
2193
2194 #if INCLUDE_MANAGEMENT
2195 const struct jmmInterface_1_ jmm_interface = {
2196 NULL,
2197 NULL,
2198 jmm_GetVersion,
2199 jmm_GetOptionalSupport,
2200 jmm_GetThreadInfo,
2201 jmm_GetMemoryPools,
2202 jmm_GetMemoryManagers,
2203 jmm_GetMemoryPoolUsage,
2204 jmm_GetPeakMemoryPoolUsage,
|
24
25 #include "precompiled.hpp"
26 #include "classfile/systemDictionary.hpp"
27 #include "compiler/compileBroker.hpp"
28 #include "memory/iterator.hpp"
29 #include "memory/oopFactory.hpp"
30 #include "memory/resourceArea.hpp"
31 #include "oops/klass.hpp"
32 #include "oops/objArrayKlass.hpp"
33 #include "oops/objArrayOop.inline.hpp"
34 #include "oops/oop.inline.hpp"
35 #include "runtime/arguments.hpp"
36 #include "runtime/globals.hpp"
37 #include "runtime/handles.inline.hpp"
38 #include "runtime/interfaceSupport.hpp"
39 #include "runtime/javaCalls.hpp"
40 #include "runtime/jniHandles.hpp"
41 #include "runtime/os.hpp"
42 #include "runtime/serviceThread.hpp"
43 #include "runtime/thread.inline.hpp"
44 #include "runtime/threadSMR.hpp"
45 #include "services/classLoadingService.hpp"
46 #include "services/diagnosticCommand.hpp"
47 #include "services/diagnosticFramework.hpp"
48 #include "services/writeableFlags.hpp"
49 #include "services/heapDumper.hpp"
50 #include "services/jmm.h"
51 #include "services/lowMemoryDetector.hpp"
52 #include "services/gcNotifier.hpp"
53 #include "services/nmtDCmd.hpp"
54 #include "services/management.hpp"
55 #include "services/memoryManager.hpp"
56 #include "services/memoryPool.hpp"
57 #include "services/memoryService.hpp"
58 #include "services/runtimeService.hpp"
59 #include "services/threadService.hpp"
60 #include "utilities/debug.hpp"
61 #include "utilities/formatBuffer.hpp"
62 #include "utilities/macros.hpp"
63
64 PerfVariable* Management::_begin_vm_creation_time = NULL;
1009 }
1010 }
1011 }
1012 return num_atts;
1013 JVM_END
1014
1015 // Helper function to do thread dump for a specific list of threads
1016 static void do_thread_dump(ThreadDumpResult* dump_result,
1017 typeArrayHandle ids_ah, // array of thread ID (long[])
1018 int num_threads,
1019 int max_depth,
1020 bool with_locked_monitors,
1021 bool with_locked_synchronizers,
1022 TRAPS) {
1023 // no need to actually perform thread dump if no TIDs are specified
1024 if (num_threads == 0) return;
1025
1026 // First get an array of threadObj handles.
1027 // A JavaThread may terminate before we get the stack trace.
1028 GrowableArray<instanceHandle>* thread_handle_array = new GrowableArray<instanceHandle>(num_threads);
1029
1030 {
1031 // Need this ThreadsListHandle for converting Java thread IDs into
1032 // threadObj handles; dump_result->set_t_list() is called in the
1033 // VM op below so we can't use it yet.
1034 ThreadsListHandle tlh;
1035 for (int i = 0; i < num_threads; i++) {
1036 jlong tid = ids_ah->long_at(i);
1037 JavaThread* jt = tlh.list()->find_JavaThread_from_java_tid(tid);
1038 oop thread_obj = (jt != NULL ? jt->threadObj() : (oop)NULL);
1039 instanceHandle threadObj_h(THREAD, (instanceOop) thread_obj);
1040 thread_handle_array->append(threadObj_h);
1041 }
1042 }
1043
1044 // Obtain thread dumps and thread snapshot information
1045 VM_ThreadDump op(dump_result,
1046 thread_handle_array,
1047 num_threads,
1048 max_depth, /* stack depth */
1049 with_locked_monitors,
1050 with_locked_synchronizers);
1051 VMThread::execute(&op);
1052 }
1053
1054 // Gets an array of ThreadInfo objects. Each element is the ThreadInfo
1055 // for the thread ID specified in the corresponding entry in
1056 // the given array of thread IDs; or NULL if the thread does not exist
1057 // or has terminated.
1089 // validate the ThreadInfo[] parameters
1090 validate_thread_info_array(infoArray_h, CHECK_0);
1091
1092 // infoArray must be of the same length as the given array of thread IDs
1093 int num_threads = ids_ah->length();
1094 if (num_threads != infoArray_h->length()) {
1095 THROW_MSG_(vmSymbols::java_lang_IllegalArgumentException(),
1096 "The length of the given ThreadInfo array does not match the length of the given array of thread IDs", -1);
1097 }
1098
1099 // make sure the AbstractOwnableSynchronizer klass is loaded before taking thread snapshots
1100 java_util_concurrent_locks_AbstractOwnableSynchronizer::initialize(CHECK_0);
1101
1102 // Must use ThreadDumpResult to store the ThreadSnapshot.
1103 // GC may occur after the thread snapshots are taken but before
1104 // this function returns. The threadObj and other oops kept
1105 // in the ThreadSnapshot are marked and adjusted during GC.
1106 ThreadDumpResult dump_result(num_threads);
1107
1108 if (maxDepth == 0) {
1109 // No stack trace to dump so we do not need to stop the world.
1110 // Since we never do the VM op here we must set the threads list.
1111 dump_result.set_t_list();
1112 for (int i = 0; i < num_threads; i++) {
1113 jlong tid = ids_ah->long_at(i);
1114 JavaThread* jt = dump_result.t_list()->find_JavaThread_from_java_tid(tid);
1115 ThreadSnapshot* ts;
1116 if (jt == NULL) {
1117 // if the thread does not exist or now it is terminated,
1118 // create dummy snapshot
1119 ts = new ThreadSnapshot();
1120 } else {
1121 ts = new ThreadSnapshot(dump_result.t_list(), jt);
1122 }
1123 dump_result.add_thread_snapshot(ts);
1124 }
1125 } else {
1126 // obtain thread dump with the specific list of threads with stack trace
1127 do_thread_dump(&dump_result,
1128 ids_ah,
1129 num_threads,
1130 maxDepth,
1131 false, /* no locked monitor */
1132 false, /* no locked synchronizers */
1133 CHECK_0);
1134 }
1135
1136 int num_snapshots = dump_result.num_snapshots();
1137 assert(num_snapshots == num_threads, "Must match the number of thread snapshots");
1138 assert(num_snapshots == 0 || dump_result.t_list_has_been_set(), "ThreadsList must have been set if we have a snapshot");
1139 int index = 0;
1140 for (ThreadSnapshot* ts = dump_result.snapshots(); ts != NULL; index++, ts = ts->next()) {
1141 // For each thread, create an java/lang/management/ThreadInfo object
1142 // and fill with the thread information
1143
1144 if (ts->threadObj() == NULL) {
1145 // if the thread does not exist or now it is terminated, set threadinfo to NULL
1146 infoArray_h->obj_at_put(index, NULL);
1147 continue;
1148 }
1149
1150 // Create java.lang.management.ThreadInfo object
1151 instanceOop info_obj = Management::create_thread_info_instance(ts, CHECK_0);
1152 infoArray_h->obj_at_put(index, info_obj);
1153 }
1154 return 0;
1155 JVM_END
1156
1157 // Dump thread info for the specified threads.
1158 // It returns an array of ThreadInfo objects. Each element is the ThreadInfo
1183 validate_thread_id_array(ids_ah, CHECK_NULL);
1184
1185 // obtain thread dump of a specific list of threads
1186 do_thread_dump(&dump_result,
1187 ids_ah,
1188 num_threads,
1189 -1, /* entire stack */
1190 (locked_monitors ? true : false), /* with locked monitors */
1191 (locked_synchronizers ? true : false), /* with locked synchronizers */
1192 CHECK_NULL);
1193 } else {
1194 // obtain thread dump of all threads
1195 VM_ThreadDump op(&dump_result,
1196 -1, /* entire stack */
1197 (locked_monitors ? true : false), /* with locked monitors */
1198 (locked_synchronizers ? true : false) /* with locked synchronizers */);
1199 VMThread::execute(&op);
1200 }
1201
1202 int num_snapshots = dump_result.num_snapshots();
1203 assert(num_snapshots == 0 || dump_result.t_list_has_been_set(), "ThreadsList must have been set if we have a snapshot");
1204
1205 // create the result ThreadInfo[] object
1206 InstanceKlass* ik = Management::java_lang_management_ThreadInfo_klass(CHECK_NULL);
1207 objArrayOop r = oopFactory::new_objArray(ik, num_snapshots, CHECK_NULL);
1208 objArrayHandle result_h(THREAD, r);
1209
1210 int index = 0;
1211 for (ThreadSnapshot* ts = dump_result.snapshots(); ts != NULL; ts = ts->next(), index++) {
1212 if (ts->threadObj() == NULL) {
1213 // if the thread does not exist or now it is terminated, set threadinfo to NULL
1214 result_h->obj_at_put(index, NULL);
1215 continue;
1216 }
1217
1218 ThreadStackTrace* stacktrace = ts->get_stack_trace();
1219 assert(stacktrace != NULL, "Must have a stack trace dumped");
1220
1221 // Create Object[] filled with locked monitors
1222 // Create int[] filled with the stack depth where a monitor was locked
1223 int num_frames = stacktrace->get_stack_depth();
1307 // For PEAK_POOL_USAGE stat, obj is required to be a memory pool object.
1308 // For THREAD_CONTENTION_COUNT and TIME stat, obj is required to be a thread ID.
1309 // type - the type of statistic to be reset
1310 //
1311 JVM_ENTRY(jboolean, jmm_ResetStatistic(JNIEnv *env, jvalue obj, jmmStatisticType type))
1312 ResourceMark rm(THREAD);
1313
1314 switch (type) {
1315 case JMM_STAT_PEAK_THREAD_COUNT:
1316 ThreadService::reset_peak_thread_count();
1317 return true;
1318
1319 case JMM_STAT_THREAD_CONTENTION_COUNT:
1320 case JMM_STAT_THREAD_CONTENTION_TIME: {
1321 jlong tid = obj.j;
1322 if (tid < 0) {
1323 THROW_(vmSymbols::java_lang_IllegalArgumentException(), JNI_FALSE);
1324 }
1325
1326 // Look for the JavaThread of this given tid
1327 ThreadsListHandle tlh;
1328 if (tid == 0) {
1329 JavaThreadIterator jti(tlh.list());
1330 // reset contention statistics for all threads if tid == 0
1331 for (JavaThread* java_thread = jti.first(); java_thread != NULL; java_thread = jti.next()) {
1332 if (type == JMM_STAT_THREAD_CONTENTION_COUNT) {
1333 ThreadService::reset_contention_count_stat(java_thread);
1334 } else {
1335 ThreadService::reset_contention_time_stat(java_thread);
1336 }
1337 }
1338 } else {
1339 // reset contention statistics for a given thread
1340 JavaThread* java_thread = tlh.list()->find_JavaThread_from_java_tid(tid);
1341 if (java_thread == NULL) {
1342 return false;
1343 }
1344
1345 if (type == JMM_STAT_THREAD_CONTENTION_COUNT) {
1346 ThreadService::reset_contention_count_stat(java_thread);
1347 } else {
1348 ThreadService::reset_contention_time_stat(java_thread);
1349 }
1350 }
1351 return true;
1352 break;
1353 }
1354 case JMM_STAT_PEAK_POOL_USAGE: {
1355 jobject o = obj.l;
1356 if (o == NULL) {
1357 THROW_(vmSymbols::java_lang_NullPointerException(), JNI_FALSE);
1358 }
1359
1360 oop pool_obj = JNIHandles::resolve(o);
1388 JVM_END
1389
1390 // Returns the fast estimate of CPU time consumed by
1391 // a given thread (in nanoseconds).
1392 // If thread_id == 0, return CPU time for the current thread.
1393 JVM_ENTRY(jlong, jmm_GetThreadCpuTime(JNIEnv *env, jlong thread_id))
1394 if (!os::is_thread_cpu_time_supported()) {
1395 return -1;
1396 }
1397
1398 if (thread_id < 0) {
1399 THROW_MSG_(vmSymbols::java_lang_IllegalArgumentException(),
1400 "Invalid thread ID", -1);
1401 }
1402
1403 JavaThread* java_thread = NULL;
1404 if (thread_id == 0) {
1405 // current thread
1406 return os::current_thread_cpu_time();
1407 } else {
1408 ThreadsListHandle tlh;
1409 java_thread = tlh.list()->find_JavaThread_from_java_tid(thread_id);
1410 if (java_thread != NULL) {
1411 return os::thread_cpu_time((Thread*) java_thread);
1412 }
1413 }
1414 return -1;
1415 JVM_END
1416
1417 // Returns a String array of all VM global flag names
1418 JVM_ENTRY(jobjectArray, jmm_GetVMGlobalNames(JNIEnv *env))
1419 // last flag entry is always NULL, so subtract 1
1420 int nFlags = (int) Flag::numFlags - 1;
1421 // allocate a temp array
1422 objArrayOop r = oopFactory::new_objArray(SystemDictionary::String_klass(),
1423 nFlags, CHECK_0);
1424 objArrayHandle flags_ah(THREAD, r);
1425 int num_entries = 0;
1426 for (int i = 0; i < nFlags; i++) {
1427 Flag* flag = &Flag::flags[i];
1428 // Exclude notproduct and develop flags in product builds.
1429 if (flag->is_constant_in_binary()) {
1638 void do_unlocked();
1639 int count() { return _count; }
1640 };
1641
1642 ThreadTimesClosure::ThreadTimesClosure(objArrayHandle names,
1643 typeArrayHandle times) {
1644 assert(names() != NULL, "names was NULL");
1645 assert(times() != NULL, "times was NULL");
1646 _names_strings = names;
1647 _names_len = names->length();
1648 _names_chars = NEW_C_HEAP_ARRAY(char*, _names_len, mtInternal);
1649 _times = times;
1650 _times_len = times->length();
1651 _count = 0;
1652 }
1653
1654 //
1655 // Called with Threads_lock held
1656 //
1657 void ThreadTimesClosure::do_thread(Thread* thread) {
1658 assert(Threads_lock->owned_by_self(), "Must hold Threads_lock");
1659 assert(thread != NULL, "thread was NULL");
1660
1661 // exclude externally visible JavaThreads
1662 if (thread->is_Java_thread() && !thread->is_hidden_from_external_view()) {
1663 return;
1664 }
1665
1666 if (_count >= _names_len || _count >= _times_len) {
1667 // skip if the result array is not big enough
1668 return;
1669 }
1670
1671 EXCEPTION_MARK;
1672 ResourceMark rm(THREAD); // thread->name() uses ResourceArea
1673
1674 assert(thread->name() != NULL, "All threads should have a name");
1675 _names_chars[_count] = os::strdup(thread->name());
1676 _times->long_at_put(_count, os::is_thread_cpu_time_supported() ?
1677 os::thread_cpu_time(thread) : -1);
1678 _count++;
2099 }
2100
2101 ResourceMark rm(THREAD);
2102 typeArrayOop ta = typeArrayOop(JNIHandles::resolve_non_null(ids));
2103 typeArrayHandle ids_ah(THREAD, ta);
2104
2105 typeArrayOop sa = typeArrayOop(JNIHandles::resolve_non_null(sizeArray));
2106 typeArrayHandle sizeArray_h(THREAD, sa);
2107
2108 // validate the thread id array
2109 validate_thread_id_array(ids_ah, CHECK);
2110
2111 // sizeArray must be of the same length as the given array of thread IDs
2112 int num_threads = ids_ah->length();
2113 if (num_threads != sizeArray_h->length()) {
2114 THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(),
2115 "The length of the given long array does not match the length of "
2116 "the given array of thread IDs");
2117 }
2118
2119 ThreadsListHandle tlh;
2120 for (int i = 0; i < num_threads; i++) {
2121 JavaThread* java_thread = tlh.list()->find_JavaThread_from_java_tid(ids_ah->long_at(i));
2122 if (java_thread != NULL) {
2123 sizeArray_h->long_at_put(i, java_thread->cooked_allocated_bytes());
2124 }
2125 }
2126 JVM_END
2127
2128 // Returns the CPU time consumed by a given thread (in nanoseconds).
2129 // If thread_id == 0, CPU time for the current thread is returned.
2130 // If user_sys_cpu_time = true, user level and system CPU time of
2131 // a given thread is returned; otherwise, only user level CPU time
2132 // is returned.
2133 JVM_ENTRY(jlong, jmm_GetThreadCpuTimeWithKind(JNIEnv *env, jlong thread_id, jboolean user_sys_cpu_time))
2134 if (!os::is_thread_cpu_time_supported()) {
2135 return -1;
2136 }
2137
2138 if (thread_id < 0) {
2139 THROW_MSG_(vmSymbols::java_lang_IllegalArgumentException(),
2140 "Invalid thread ID", -1);
2141 }
2142
2143 JavaThread* java_thread = NULL;
2144 if (thread_id == 0) {
2145 // current thread
2146 return os::current_thread_cpu_time(user_sys_cpu_time != 0);
2147 } else {
2148 ThreadsListHandle tlh;
2149 java_thread = tlh.list()->find_JavaThread_from_java_tid(thread_id);
2150 if (java_thread != NULL) {
2151 return os::thread_cpu_time((Thread*) java_thread, user_sys_cpu_time != 0);
2152 }
2153 }
2154 return -1;
2155 JVM_END
2156
2157 // Gets an array containing the CPU times consumed by a set of threads
2158 // (in nanoseconds). Each element of the array is the CPU time for the
2159 // thread ID specified in the corresponding entry in the given array
2160 // of thread IDs; or -1 if the thread does not exist or has terminated.
2161 // If user_sys_cpu_time = true, the sum of user level and system CPU time
2162 // for the given thread is returned; otherwise, only user level CPU time
2163 // is returned.
2164 JVM_ENTRY(void, jmm_GetThreadCpuTimesWithKind(JNIEnv *env, jlongArray ids,
2165 jlongArray timeArray,
2166 jboolean user_sys_cpu_time))
2167 // Check if threads is null
2168 if (ids == NULL || timeArray == NULL) {
2169 THROW(vmSymbols::java_lang_NullPointerException());
2170 }
2171
2172 ResourceMark rm(THREAD);
2173 typeArrayOop ta = typeArrayOop(JNIHandles::resolve_non_null(ids));
2174 typeArrayHandle ids_ah(THREAD, ta);
2175
2176 typeArrayOop tia = typeArrayOop(JNIHandles::resolve_non_null(timeArray));
2177 typeArrayHandle timeArray_h(THREAD, tia);
2178
2179 // validate the thread id array
2180 validate_thread_id_array(ids_ah, CHECK);
2181
2182 // timeArray must be of the same length as the given array of thread IDs
2183 int num_threads = ids_ah->length();
2184 if (num_threads != timeArray_h->length()) {
2185 THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(),
2186 "The length of the given long array does not match the length of "
2187 "the given array of thread IDs");
2188 }
2189
2190 ThreadsListHandle tlh;
2191 for (int i = 0; i < num_threads; i++) {
2192 JavaThread* java_thread = tlh.list()->find_JavaThread_from_java_tid(ids_ah->long_at(i));
2193 if (java_thread != NULL) {
2194 timeArray_h->long_at_put(i, os::thread_cpu_time((Thread*)java_thread,
2195 user_sys_cpu_time != 0));
2196 }
2197 }
2198 JVM_END
2199
2200
2201
2202 #if INCLUDE_MANAGEMENT
2203 const struct jmmInterface_1_ jmm_interface = {
2204 NULL,
2205 NULL,
2206 jmm_GetVersion,
2207 jmm_GetOptionalSupport,
2208 jmm_GetThreadInfo,
2209 jmm_GetMemoryPools,
2210 jmm_GetMemoryManagers,
2211 jmm_GetMemoryPoolUsage,
2212 jmm_GetPeakMemoryPoolUsage,
|