@@ -965,4 +965,247 @@ VM_JFRChunkWriter::writeThreadStatisticsEvent(void *anElement, void *userData)
965
965
writeEventSize (_bufferWriter, dataStart);
966
966
}
967
967
968
+ static void
969
+ writeObject (J9JavaVM *vm, j9object_t obj, VM_BufferWriter *bufferWriter)
970
+ {
971
+ J9ROMClass *romClass = NULL ;
972
+ if (J9VM_IS_INITIALIZED_HEAPCLASS_VM (vm, obj)) {
973
+ romClass = J9VM_J9CLASS_FROM_HEAPCLASS_VM (vm, obj)->romClass ;
974
+ } else {
975
+ romClass = J9OBJECT_CLAZZ_VM (vm, obj)->romClass ;
976
+ }
977
+
978
+ J9UTF8 *className = J9ROMCLASS_CLASSNAME (romClass);
979
+ bufferWriter->writeFormattedString (" %.*s@%p" , J9UTF8_LENGTH (className), J9UTF8_DATA (className), obj);
980
+ }
981
+
982
+ static UDATA
983
+ stackWalkCallback (J9VMThread *vmThread, J9StackWalkState *state)
984
+ {
985
+ J9JavaVM *vm = vmThread->javaVM ;
986
+ J9ObjectMonitorInfo *monitorInfo = (J9ObjectMonitorInfo *)state->userData2 ;
987
+ IDATA *monitorCount = (IDATA *)(&state->userData3 );
988
+ J9Method *method = state->method ;
989
+ J9Class *methodClass = J9_CLASS_FROM_METHOD (method);
990
+ J9UTF8 *className = J9ROMCLASS_CLASSNAME (methodClass->romClass );
991
+ J9ROMMethod *romMethod = J9_ROM_METHOD_FROM_RAM_METHOD (method);
992
+ J9UTF8 *methodName = J9ROMMETHOD_NAME (romMethod);
993
+
994
+ VM_BufferWriter *bufferWriter = (VM_BufferWriter *)state->userData1 ;
995
+
996
+ bufferWriter->writeFormattedString (
997
+ " at %.*s.%.*s" ,
998
+ J9UTF8_LENGTH (className), J9UTF8_DATA (className),
999
+ J9UTF8_LENGTH (methodName), J9UTF8_DATA (methodName));
1000
+
1001
+ if (J9_ARE_ANY_BITS_SET (romMethod->modifiers , J9AccNative)) {
1002
+ bufferWriter->writeFormattedString (" (Native Method)\n " );
1003
+ } else {
1004
+ UDATA offsetPC = state->bytecodePCOffset ;
1005
+ bool compiledMethod = (NULL != state->jitInfo );
1006
+ J9UTF8 *sourceFile = getSourceFileNameForROMClass (vm, methodClass->classLoader , methodClass->romClass );
1007
+ if (NULL != sourceFile) {
1008
+ bufferWriter->writeFormattedString (
1009
+ " (%.*s" , J9UTF8_LENGTH (sourceFile), J9UTF8_DATA (sourceFile));
1010
+
1011
+ UDATA lineNumber = getLineNumberForROMClass (vm, method, offsetPC);
1012
+
1013
+ if ((UDATA)-1 != lineNumber) {
1014
+ bufferWriter->writeFormattedString (" :%zu" , lineNumber);
1015
+ }
1016
+
1017
+ if (compiledMethod) {
1018
+ bufferWriter->writeFormattedString (" (Compiled Code)" );
1019
+ }
1020
+
1021
+ bufferWriter->writeFormattedString (" )\n " );
1022
+ } else {
1023
+ bufferWriter->writeFormattedString (" (Bytecode PC: %zu" , offsetPC);
1024
+ if (compiledMethod) {
1025
+ bufferWriter->writeFormattedString (" (Compiled Code)" );
1026
+ }
1027
+ bufferWriter->writeFormattedString (" )\n " );
1028
+ }
1029
+
1030
+ /* Use a while loop as there may be more than one lock taken in a stack frame. */
1031
+ while ((0 != *monitorCount) && ((UDATA)monitorInfo->depth == state->framesWalked )) {
1032
+ bufferWriter->writeFormattedString (" \t (entered lock: " );
1033
+ writeObject (vm, monitorInfo->object , bufferWriter);
1034
+ bufferWriter->writeFormattedString (" )\n " );
1035
+
1036
+ monitorInfo += 1 ;
1037
+ state->userData2 = monitorInfo;
1038
+
1039
+ (*monitorCount) -= 1 ;
1040
+ }
1041
+ }
1042
+
1043
+ return J9_STACKWALK_KEEP_ITERATING;
1044
+ }
1045
+
1046
+ static void
1047
+ writeThreadInfo (J9VMThread *currentThread, J9VMThread *walkThread, VM_BufferWriter *bufferWriter)
1048
+ {
1049
+ J9JavaVM *vm = currentThread->javaVM ;
1050
+ J9InternalVMFunctions *vmFuncs = vm->internalVMFunctions ;
1051
+ UDATA javaTID = J9VMJAVALANGTHREAD_TID (currentThread, walkThread->threadObject );
1052
+ UDATA osTID = ((J9AbstractThread *)walkThread->osThread )->tid ;
1053
+ UDATA javaPriority = vmFuncs->getJavaThreadPriority (vm, walkThread);
1054
+ UDATA state = J9VMTHREAD_STATE_UNKNOWN;
1055
+ const char *stateStr = " ?" ;
1056
+ j9object_t monitorObject = NULL ;
1057
+ char *threadName = NULL ;
1058
+
1059
+ /* Get thread state and monitor */
1060
+ state = getVMThreadObjectState (walkThread, &monitorObject, NULL , NULL );
1061
+ switch (state) {
1062
+ case J9VMTHREAD_STATE_RUNNING:
1063
+ stateStr = " R" ;
1064
+ break ;
1065
+ case J9VMTHREAD_STATE_BLOCKED:
1066
+ stateStr = " B" ;
1067
+ break ;
1068
+ case J9VMTHREAD_STATE_WAITING:
1069
+ case J9VMTHREAD_STATE_WAITING_TIMED:
1070
+ case J9VMTHREAD_STATE_SLEEPING:
1071
+ stateStr = " CW" ;
1072
+ break ;
1073
+ case J9VMTHREAD_STATE_PARKED:
1074
+ case J9VMTHREAD_STATE_PARKED_TIMED:
1075
+ stateStr = " P" ;
1076
+ break ;
1077
+ case J9VMTHREAD_STATE_SUSPENDED:
1078
+ stateStr = " S" ;
1079
+ break ;
1080
+ case J9VMTHREAD_STATE_DEAD:
1081
+ stateStr = " Z" ;
1082
+ break ;
1083
+ case J9VMTHREAD_STATE_INTERRUPTED:
1084
+ stateStr = " I" ;
1085
+ break ;
1086
+ case J9VMTHREAD_STATE_UNKNOWN:
1087
+ stateStr = " ?" ;
1088
+ break ;
1089
+ default :
1090
+ stateStr = " ??" ;
1091
+ break ;
1092
+ }
1093
+
1094
+ /* Get thread name */
1095
+ #if JAVA_SPEC_VERSION >= 21
1096
+ if (IS_JAVA_LANG_VIRTUALTHREAD (currentThread, walkThread->threadObject )) {
1097
+ /* For VirtualThread, get name from threadObject directly. */
1098
+ j9object_t nameObject = J9VMJAVALANGTHREAD_NAME (currentThread, walkThread->threadObject );
1099
+ threadName = getVMThreadNameFromString (currentThread, nameObject);
1100
+ } else
1101
+ #endif /* JAVA_SPEC_VERSION >= 21 */
1102
+ {
1103
+ threadName = getOMRVMThreadName (walkThread->omrVMThread );
1104
+ releaseOMRVMThreadName (walkThread->omrVMThread );
1105
+ }
1106
+ bufferWriter->writeFormattedString (
1107
+ " \" %s\" J9VMThread: %p tid: %zd nid: %zd prio: %zd state: %s" ,
1108
+ threadName,
1109
+ walkThread,
1110
+ javaTID,
1111
+ osTID,
1112
+ javaPriority,
1113
+ stateStr);
1114
+
1115
+ if (J9VMTHREAD_STATE_BLOCKED == state) {
1116
+ bufferWriter->writeFormattedString (" blocked on: " );
1117
+ } else if ((J9VMTHREAD_STATE_WAITING == state) || (J9VMTHREAD_STATE_WAITING_TIMED == state)) {
1118
+ bufferWriter->writeFormattedString (" waiting on: " );
1119
+ } else if ((J9VMTHREAD_STATE_PARKED == state) || (J9VMTHREAD_STATE_PARKED_TIMED == state)) {
1120
+ bufferWriter->writeFormattedString (" parked on: " );
1121
+ } else {
1122
+ bufferWriter->writeFormattedString (" \n " );
1123
+ return ;
1124
+ }
1125
+
1126
+ if (NULL != monitorObject) {
1127
+ writeObject (vm, monitorObject, bufferWriter);
1128
+ } else {
1129
+ bufferWriter->writeFormattedString (" <unknown>" );
1130
+ }
1131
+ bufferWriter->writeFormattedString (" \n " );
1132
+ }
1133
+
1134
+ static void
1135
+ writeStacktrace (J9VMThread *currentThread, J9VMThread *walkThread, VM_BufferWriter *bufferWriter)
1136
+ {
1137
+ J9JavaVM *vm = currentThread->javaVM ;
1138
+ J9InternalVMFunctions *vmFuncs = vm->internalVMFunctions ;
1139
+ J9StackWalkState stackWalkState = {0 };
1140
+ const size_t maxMonitorInfosPerThread = 32 ;
1141
+ J9ObjectMonitorInfo monitorInfos[maxMonitorInfosPerThread];
1142
+ memset (monitorInfos, 0 , sizeof (monitorInfos));
1143
+
1144
+ IDATA monitorCount = vmFuncs->getOwnedObjectMonitors (currentThread, walkThread, monitorInfos, maxMonitorInfosPerThread, FALSE );
1145
+
1146
+ stackWalkState.walkThread = walkThread;
1147
+ stackWalkState.flags =
1148
+ J9_STACKWALK_ITERATE_FRAMES
1149
+ | J9_STACKWALK_INCLUDE_NATIVES
1150
+ | J9_STACKWALK_VISIBLE_ONLY
1151
+ | J9_STACKWALK_RECORD_BYTECODE_PC_OFFSET
1152
+ | J9_STACKWALK_NO_ERROR_REPORT;
1153
+ stackWalkState.skipCount = 0 ;
1154
+ stackWalkState.frameWalkFunction = stackWalkCallback;
1155
+ stackWalkState.userData1 = bufferWriter;
1156
+ stackWalkState.userData2 = monitorInfos;
1157
+ stackWalkState.userData3 = (void *)monitorCount;
1158
+
1159
+ vmFuncs->haltThreadForInspection (currentThread, walkThread);
1160
+ vm->walkStackFrames (currentThread, &stackWalkState);
1161
+ vmFuncs->resumeThreadForInspection (currentThread, walkThread);
1162
+
1163
+ bufferWriter->writeFormattedString (" \n " );
1164
+ }
1165
+
1166
+ U_8 *
1167
+ VM_JFRChunkWriter::writeThreadDumpEvent ()
1168
+ {
1169
+ /* reserve size field */
1170
+ U_8 *dataStart = reserveEventSize ();
1171
+
1172
+ _bufferWriter->writeLEB128 (ThreadDumpID);
1173
+
1174
+ /* write start time */
1175
+ _bufferWriter->writeLEB128 (j9time_current_time_millis ());
1176
+
1177
+ const U_64 bufferSize = THREAD_DUMP_EVENT_SIZE_PER_THREAD * _vm->peakThreadCount ;
1178
+ U_8 *resultBuffer = (U_8 *)j9mem_allocate_memory (sizeof (U_8) * bufferSize, OMRMEM_CATEGORY_VM);
1179
+
1180
+ if (NULL != resultBuffer) {
1181
+ VM_BufferWriter resultWriter (privatePortLibrary, resultBuffer, bufferSize);
1182
+ J9VMThread *walkThread = J9_LINKED_LIST_START_DO (_vm->mainThread );
1183
+ UDATA numThreads = 0 ;
1184
+ J9InternalVMFunctions *vmFuncs = _vm->internalVMFunctions ;
1185
+
1186
+ Assert_VM_mustHaveVMAccess (_currentThread);
1187
+ vmFuncs->acquireExclusiveVMAccess (_currentThread);
1188
+
1189
+ while (NULL != walkThread) {
1190
+ writeThreadInfo (_currentThread, walkThread, &resultWriter);
1191
+ writeStacktrace (_currentThread, walkThread, &resultWriter);
1192
+
1193
+ walkThread = J9_LINKED_LIST_NEXT_DO (_vm->mainThread , walkThread);
1194
+ numThreads += 1 ;
1195
+ }
1196
+ resultWriter.writeFormattedString (" Number of threads: %zd" , numThreads);
1197
+
1198
+ vmFuncs->releaseExclusiveVMAccess (_currentThread);
1199
+
1200
+ writeUTF8String (resultWriter.getBufferStart (), resultWriter.getSize ());
1201
+ j9mem_free_memory (resultBuffer);
1202
+ } else {
1203
+ _buildResult = OutOfMemory;
1204
+ }
1205
+
1206
+ /* write size */
1207
+ writeEventSize (dataStart);
1208
+
1209
+ return dataStart;
1210
+ }
968
1211
#endif /* defined(J9VM_OPT_JFR) */
0 commit comments