comparison src/share/vm/services/management.cpp @ 2100:b1a2afa37ec4

7003271: Hotspot should track cumulative Java heap bytes allocated on a per-thread basis Summary: Track allocated bytes in Thread's, update on TLAB retirement and direct allocation in Eden and tenured, add JNI methods for ThreadMXBean. Reviewed-by: coleenp, kvn, dholmes, ysr
author phh
date Fri, 07 Jan 2011 10:42:32 -0500
parents f95d63e2154a
children 3582bf76420e
comparison
equal deleted inserted replaced
2097:039eb4201e06 2100:b1a2afa37ec4
1 /* 1 /*
2 * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved. 2 * Copyright (c) 2003, 2011, Oracle and/or its affiliates. All rights reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 * 4 *
5 * This code is free software; you can redistribute it and/or modify it 5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as 6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation. 7 * published by the Free Software Foundation.
99 _optional_support.isOtherThreadCpuTimeSupported = 1; 99 _optional_support.isOtherThreadCpuTimeSupported = 1;
100 } else { 100 } else {
101 _optional_support.isCurrentThreadCpuTimeSupported = 0; 101 _optional_support.isCurrentThreadCpuTimeSupported = 0;
102 _optional_support.isOtherThreadCpuTimeSupported = 0; 102 _optional_support.isOtherThreadCpuTimeSupported = 0;
103 } 103 }
104
104 _optional_support.isBootClassPathSupported = 1; 105 _optional_support.isBootClassPathSupported = 1;
105 _optional_support.isObjectMonitorUsageSupported = 1; 106 _optional_support.isObjectMonitorUsageSupported = 1;
106 #ifndef SERVICES_KERNEL 107 #ifndef SERVICES_KERNEL
107 // This depends on the heap inspector 108 // This depends on the heap inspector
108 _optional_support.isSynchronizerUsageSupported = 1; 109 _optional_support.isSynchronizerUsageSupported = 1;
109 #endif // SERVICES_KERNEL 110 #endif // SERVICES_KERNEL
111 _optional_support.isThreadAllocatedMemorySupported = 1;
110 } 112 }
111 113
112 void Management::initialize(TRAPS) { 114 void Management::initialize(TRAPS) {
113 // Start the low memory detector thread 115 // Start the low memory detector thread
114 LowMemoryDetector::initialize(); 116 LowMemoryDetector::initialize();
384 return MemoryService::get_memory_pool(ph); 386 return MemoryService::get_memory_pool(ph);
385 } 387 }
386 388
387 static void validate_thread_id_array(typeArrayHandle ids_ah, TRAPS) { 389 static void validate_thread_id_array(typeArrayHandle ids_ah, TRAPS) {
388 int num_threads = ids_ah->length(); 390 int num_threads = ids_ah->length();
389 // should be non-empty array
390 if (num_threads == 0) {
391 THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(),
392 "Empty array of thread IDs");
393 }
394 391
395 // Validate input thread IDs 392 // Validate input thread IDs
396 int i = 0; 393 int i = 0;
397 for (i = 0; i < num_threads; i++) { 394 for (i = 0; i < num_threads; i++) {
398 jlong tid = ids_ah->long_at(i); 395 jlong tid = ids_ah->long_at(i);
400 // throw exception if invalid thread id. 397 // throw exception if invalid thread id.
401 THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(), 398 THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(),
402 "Invalid thread ID entry"); 399 "Invalid thread ID entry");
403 } 400 }
404 } 401 }
405
406 } 402 }
407 403
408 static void validate_thread_info_array(objArrayHandle infoArray_h, TRAPS) { 404 static void validate_thread_info_array(objArrayHandle infoArray_h, TRAPS) {
409
410 // check if the element of infoArray is of type ThreadInfo class 405 // check if the element of infoArray is of type ThreadInfo class
411 klassOop threadinfo_klass = Management::java_lang_management_ThreadInfo_klass(CHECK); 406 klassOop threadinfo_klass = Management::java_lang_management_ThreadInfo_klass(CHECK);
412 klassOop element_klass = objArrayKlass::cast(infoArray_h->klass())->element_klass(); 407 klassOop element_klass = objArrayKlass::cast(infoArray_h->klass())->element_klass();
413 if (element_klass != threadinfo_klass) { 408 if (element_klass != threadinfo_klass) {
414 THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(), 409 THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(),
415 "infoArray element type is not ThreadInfo class"); 410 "infoArray element type is not ThreadInfo class");
416 } 411 }
417
418 } 412 }
419 413
420 414
421 static MemoryManager* get_memory_manager_from_jobject(jobject obj, TRAPS) { 415 static MemoryManager* get_memory_manager_from_jobject(jobject obj, TRAPS) {
422 if (obj == NULL) { 416 if (obj == NULL) {
768 LowMemoryDetector::detect_low_memory(pool); 762 LowMemoryDetector::detect_low_memory(pool);
769 } 763 }
770 return prev; 764 return prev;
771 JVM_END 765 JVM_END
772 766
767 // Gets an array containing the amount of memory allocated on the Java
768 // heap for a set of threads (in bytes). Each element of the array is
769 // the amount of memory allocated for the thread ID specified in the
770 // corresponding entry in the given array of thread IDs; or -1 if the
771 // thread does not exist or has terminated.
772 JVM_ENTRY(void, jmm_GetThreadAllocatedMemory(JNIEnv *env, jlongArray ids,
773 jlongArray sizeArray))
774 // Check if threads is null
775 if (ids == NULL || sizeArray == NULL) {
776 THROW(vmSymbols::java_lang_NullPointerException());
777 }
778
779 ResourceMark rm(THREAD);
780 typeArrayOop ta = typeArrayOop(JNIHandles::resolve_non_null(ids));
781 typeArrayHandle ids_ah(THREAD, ta);
782
783 typeArrayOop sa = typeArrayOop(JNIHandles::resolve_non_null(sizeArray));
784 typeArrayHandle sizeArray_h(THREAD, sa);
785
786 // validate the thread id array
787 validate_thread_id_array(ids_ah, CHECK);
788
789 // sizeArray must be of the same length as the given array of thread IDs
790 int num_threads = ids_ah->length();
791 if (num_threads != sizeArray_h->length()) {
792 THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(),
793 "The length of the given long array does not match the length of "
794 "the given array of thread IDs");
795 }
796
797 MutexLockerEx ml(Threads_lock);
798 for (int i = 0; i < num_threads; i++) {
799 JavaThread* java_thread = find_java_thread_from_id(ids_ah->long_at(i));
800 if (java_thread != NULL) {
801 sizeArray_h->long_at_put(i, java_thread->cooked_allocated_bytes());
802 }
803 }
804 JVM_END
805
773 // Returns a java/lang/management/MemoryUsage object representing 806 // Returns a java/lang/management/MemoryUsage object representing
774 // the memory usage for the heap or non-heap memory. 807 // the memory usage for the heap or non-heap memory.
775 JVM_ENTRY(jobject, jmm_GetMemoryUsage(JNIEnv* env, jboolean heap)) 808 JVM_ENTRY(jobject, jmm_GetMemoryUsage(JNIEnv* env, jboolean heap))
776 ResourceMark rm(THREAD); 809 ResourceMark rm(THREAD);
777 810
832 return ClassLoadingService::get_verbose(); 865 return ClassLoadingService::get_verbose();
833 case JMM_THREAD_CONTENTION_MONITORING: 866 case JMM_THREAD_CONTENTION_MONITORING:
834 return ThreadService::is_thread_monitoring_contention(); 867 return ThreadService::is_thread_monitoring_contention();
835 case JMM_THREAD_CPU_TIME: 868 case JMM_THREAD_CPU_TIME:
836 return ThreadService::is_thread_cpu_time_enabled(); 869 return ThreadService::is_thread_cpu_time_enabled();
870 case JMM_THREAD_ALLOCATED_MEMORY:
871 return ThreadService::is_thread_allocated_memory_enabled();
837 default: 872 default:
838 assert(0, "Unrecognized attribute"); 873 assert(0, "Unrecognized attribute");
839 return false; 874 return false;
840 } 875 }
841 JVM_END 876 JVM_END
849 return ClassLoadingService::set_verbose(flag != 0); 884 return ClassLoadingService::set_verbose(flag != 0);
850 case JMM_THREAD_CONTENTION_MONITORING: 885 case JMM_THREAD_CONTENTION_MONITORING:
851 return ThreadService::set_thread_monitoring_contention(flag != 0); 886 return ThreadService::set_thread_monitoring_contention(flag != 0);
852 case JMM_THREAD_CPU_TIME: 887 case JMM_THREAD_CPU_TIME:
853 return ThreadService::set_thread_cpu_time_enabled(flag != 0); 888 return ThreadService::set_thread_cpu_time_enabled(flag != 0);
889 case JMM_THREAD_ALLOCATED_MEMORY:
890 return ThreadService::set_thread_allocated_memory_enabled(flag != 0);
854 default: 891 default:
855 assert(0, "Unrecognized attribute"); 892 assert(0, "Unrecognized attribute");
856 return false; 893 return false;
857 } 894 }
858 JVM_END 895 JVM_END
1094 // maxDepth - the maximum depth of stack traces to be dumped: 1131 // maxDepth - the maximum depth of stack traces to be dumped:
1095 // maxDepth == -1 requests to dump entire stack trace. 1132 // maxDepth == -1 requests to dump entire stack trace.
1096 // maxDepth == 0 requests no stack trace. 1133 // maxDepth == 0 requests no stack trace.
1097 // infoArray - array of ThreadInfo objects 1134 // infoArray - array of ThreadInfo objects
1098 // 1135 //
1136 // QQQ - Why does this method return a value instead of void?
1099 JVM_ENTRY(jint, jmm_GetThreadInfo(JNIEnv *env, jlongArray ids, jint maxDepth, jobjectArray infoArray)) 1137 JVM_ENTRY(jint, jmm_GetThreadInfo(JNIEnv *env, jlongArray ids, jint maxDepth, jobjectArray infoArray))
1100 // Check if threads is null 1138 // Check if threads is null
1101 if (ids == NULL || infoArray == NULL) { 1139 if (ids == NULL || infoArray == NULL) {
1102 THROW_(vmSymbols::java_lang_NullPointerException(), -1); 1140 THROW_(vmSymbols::java_lang_NullPointerException(), -1);
1103 } 1141 }
1157 dump_result.add_thread_snapshot(ts); 1195 dump_result.add_thread_snapshot(ts);
1158 } 1196 }
1159 } 1197 }
1160 } else { 1198 } else {
1161 // obtain thread dump with the specific list of threads with stack trace 1199 // obtain thread dump with the specific list of threads with stack trace
1162
1163 do_thread_dump(&dump_result, 1200 do_thread_dump(&dump_result,
1164 ids_ah, 1201 ids_ah,
1165 num_threads, 1202 num_threads,
1166 maxDepth, 1203 maxDepth,
1167 false, /* no locked monitor */ 1204 false, /* no locked monitor */
1249 if (ts->threadObj() == NULL) { 1286 if (ts->threadObj() == NULL) {
1250 // if the thread does not exist or now it is terminated, set threadinfo to NULL 1287 // if the thread does not exist or now it is terminated, set threadinfo to NULL
1251 result_h->obj_at_put(index, NULL); 1288 result_h->obj_at_put(index, NULL);
1252 continue; 1289 continue;
1253 } 1290 }
1254
1255
1256 1291
1257 ThreadStackTrace* stacktrace = ts->get_stack_trace(); 1292 ThreadStackTrace* stacktrace = ts->get_stack_trace();
1258 assert(stacktrace != NULL, "Must have a stack trace dumped"); 1293 assert(stacktrace != NULL, "Must have a stack trace dumped");
1259 1294
1260 // Create Object[] filled with locked monitors 1295 // Create Object[] filled with locked monitors
1496 if (java_thread != NULL) { 1531 if (java_thread != NULL) {
1497 return os::thread_cpu_time((Thread*) java_thread, user_sys_cpu_time != 0); 1532 return os::thread_cpu_time((Thread*) java_thread, user_sys_cpu_time != 0);
1498 } 1533 }
1499 } 1534 }
1500 return -1; 1535 return -1;
1536 JVM_END
1537
1538 // Gets an array containing the CPU times consumed by a set of threads
1539 // (in nanoseconds). Each element of the array is the CPU time for the
1540 // thread ID specified in the corresponding entry in the given array
1541 // of thread IDs; or -1 if the thread does not exist or has terminated.
1542 // If user_sys_cpu_time = true, the sum of user level and system CPU time
1543 // for the given thread is returned; otherwise, only user level CPU time
1544 // is returned.
1545 JVM_ENTRY(void, jmm_GetThreadCpuTimesWithKind(JNIEnv *env, jlongArray ids,
1546 jlongArray timeArray,
1547 jboolean user_sys_cpu_time))
1548 // Check if threads is null
1549 if (ids == NULL || timeArray == NULL) {
1550 THROW(vmSymbols::java_lang_NullPointerException());
1551 }
1552
1553 ResourceMark rm(THREAD);
1554 typeArrayOop ta = typeArrayOop(JNIHandles::resolve_non_null(ids));
1555 typeArrayHandle ids_ah(THREAD, ta);
1556
1557 typeArrayOop tia = typeArrayOop(JNIHandles::resolve_non_null(timeArray));
1558 typeArrayHandle timeArray_h(THREAD, tia);
1559
1560 // validate the thread id array
1561 validate_thread_id_array(ids_ah, CHECK);
1562
1563 // timeArray must be of the same length as the given array of thread IDs
1564 int num_threads = ids_ah->length();
1565 if (num_threads != timeArray_h->length()) {
1566 THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(),
1567 "The length of the given long array does not match the length of "
1568 "the given array of thread IDs");
1569 }
1570
1571 MutexLockerEx ml(Threads_lock);
1572 for (int i = 0; i < num_threads; i++) {
1573 JavaThread* java_thread = find_java_thread_from_id(ids_ah->long_at(i));
1574 if (java_thread != NULL) {
1575 timeArray_h->long_at_put(i, os::thread_cpu_time((Thread*)java_thread,
1576 user_sys_cpu_time != 0));
1577 }
1578 }
1501 JVM_END 1579 JVM_END
1502 1580
1503 // Returns a String array of all VM global flag names 1581 // Returns a String array of all VM global flag names
1504 JVM_ENTRY(jobjectArray, jmm_GetVMGlobalNames(JNIEnv *env)) 1582 JVM_ENTRY(jobjectArray, jmm_GetVMGlobalNames(JNIEnv *env))
1505 // last flag entry is always NULL, so subtract 1 1583 // last flag entry is always NULL, so subtract 1
2018 jmm_GetInputArgumentArray, 2096 jmm_GetInputArgumentArray,
2019 jmm_GetMemoryPools, 2097 jmm_GetMemoryPools,
2020 jmm_GetMemoryManagers, 2098 jmm_GetMemoryManagers,
2021 jmm_GetMemoryPoolUsage, 2099 jmm_GetMemoryPoolUsage,
2022 jmm_GetPeakMemoryPoolUsage, 2100 jmm_GetPeakMemoryPoolUsage,
2023 NULL, 2101 jmm_GetThreadAllocatedMemory,
2024 jmm_GetMemoryUsage, 2102 jmm_GetMemoryUsage,
2025 jmm_GetLongAttribute, 2103 jmm_GetLongAttribute,
2026 jmm_GetBoolAttribute, 2104 jmm_GetBoolAttribute,
2027 jmm_SetBoolAttribute, 2105 jmm_SetBoolAttribute,
2028 jmm_GetLongAttributes, 2106 jmm_GetLongAttributes,
2036 jmm_SetPoolThreshold, 2114 jmm_SetPoolThreshold,
2037 jmm_GetPoolCollectionUsage, 2115 jmm_GetPoolCollectionUsage,
2038 jmm_GetGCExtAttributeInfo, 2116 jmm_GetGCExtAttributeInfo,
2039 jmm_GetLastGCStat, 2117 jmm_GetLastGCStat,
2040 jmm_GetThreadCpuTimeWithKind, 2118 jmm_GetThreadCpuTimeWithKind,
2041 NULL, 2119 jmm_GetThreadCpuTimesWithKind,
2042 jmm_DumpHeap0, 2120 jmm_DumpHeap0,
2043 jmm_FindDeadlockedThreads, 2121 jmm_FindDeadlockedThreads,
2044 jmm_SetVMGlobal, 2122 jmm_SetVMGlobal,
2045 NULL, 2123 NULL,
2046 jmm_DumpThreads 2124 jmm_DumpThreads