1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package org.apache.logging.log4j.message;
18
19 import java.lang.management.LockInfo;
20 import java.lang.management.MonitorInfo;
21 import java.lang.management.ThreadInfo;
22
23
24
25
26
27 class ExtendedThreadInformation implements ThreadInformation {
28
29 private final ThreadInfo info;
30
31
32 public ExtendedThreadInformation(ThreadInfo thread) {
33 this.info = thread;
34 }
35
36 public void printThreadInfo(StringBuilder sb) {
37 sb.append("\"").append(info.getThreadName()).append("\"");
38 sb.append(" Id=").append(info.getThreadId()).append(" ");
39 formatState(sb, info);
40 if (info.isSuspended()) {
41 sb.append(" (suspended)");
42 }
43 if (info.isInNative()) {
44 sb.append(" (in native)");
45 }
46 sb.append('\n');
47 }
48
49 public void printStack(StringBuilder sb, StackTraceElement[] stack) {
50 int i = 0;
51 for (StackTraceElement element : stack) {
52 sb.append("\tat ").append(element.toString());
53 sb.append('\n');
54 if (i == 0 && info.getLockInfo() != null) {
55 Thread.State ts = info.getThreadState();
56 switch (ts) {
57 case BLOCKED:
58 sb.append("\t- blocked on ");
59 formatLock(sb, info.getLockInfo());
60 sb.append('\n');
61 break;
62 case WAITING:
63 sb.append("\t- waiting on ");
64 formatLock(sb, info.getLockInfo());
65 sb.append('\n');
66 break;
67 case TIMED_WAITING:
68 sb.append("\t- waiting on ");
69 formatLock(sb, info.getLockInfo());
70 sb.append('\n');
71 break;
72 default:
73 }
74 }
75
76 for (MonitorInfo mi : info.getLockedMonitors()) {
77 if (mi.getLockedStackDepth() == i) {
78 sb.append("\t- locked ");
79 formatLock(sb, mi);
80 sb.append('\n');
81 }
82 }
83 ++i;
84 }
85
86 LockInfo[] locks = info.getLockedSynchronizers();
87 if (locks.length > 0) {
88 sb.append("\n\tNumber of locked synchronizers = ").append(locks.length).append('\n');
89 for (LockInfo li : locks) {
90 sb.append("\t- ");
91 formatLock(sb, li);
92 sb.append('\n');
93 }
94 }
95 }
96
97 private void formatLock(StringBuilder sb, LockInfo lock) {
98 sb.append("<").append(lock.getIdentityHashCode()).append("> (a ");
99 sb.append(lock.getClassName()).append(")");
100 }
101
102 private void formatState(StringBuilder sb, ThreadInfo info) {
103 Thread.State state = info.getThreadState();
104 sb.append(state);
105 switch (state) {
106 case BLOCKED: {
107 sb.append(" (on object monitor owned by \"");
108 sb.append(info.getLockOwnerName()).append("\" Id=").append(info.getLockOwnerId()).append(")");
109 break;
110 }
111 case WAITING: {
112 StackTraceElement element = info.getStackTrace()[0];
113 String className = element.getClassName();
114 String method = element.getMethodName();
115 if (className.equals("java.lang.Object") && method.equals("wait")) {
116 sb.append(" (on object monitor");
117 if (info.getLockOwnerName() != null) {
118 sb.append(" owned by \"");
119 sb.append(info.getLockOwnerName()).append("\" Id=").append(info.getLockOwnerId());
120 }
121 sb.append(")");
122 } else if (className.equals("java.lang.Thread") && method.equals("join")) {
123 sb.append(" (on completion of thread ").append(info.getLockOwnerId()).append(")");
124 } else {
125 sb.append(" (parking for lock");
126 if (info.getLockOwnerName() != null) {
127 sb.append(" owned by \"");
128 sb.append(info.getLockOwnerName()).append("\" Id=").append(info.getLockOwnerId());
129 }
130 sb.append(")");
131 }
132 break;
133 }
134 case TIMED_WAITING: {
135 StackTraceElement element = info.getStackTrace()[0];
136 String className = element.getClassName();
137 String method = element.getMethodName();
138 if (className.equals("java.lang.Object") && method.equals("wait")) {
139 sb.append(" (on object monitor");
140 if (info.getLockOwnerName() != null) {
141 sb.append(" owned by \"");
142 sb.append(info.getLockOwnerName()).append("\" Id=").append(info.getLockOwnerId());
143 }
144 sb.append(")");
145 } else if (className.equals("java.lang.Thread") && method.equals("sleep")) {
146 sb.append(" (sleeping)");
147 } else if (className.equals("java.lang.Thread") && method.equals("join")) {
148 sb.append(" (on completion of thread ").append(info.getLockOwnerId()).append(")");
149 } else {
150 sb.append(" (parking for lock");
151 if (info.getLockOwnerName() != null) {
152 sb.append(" owned by \"");
153 sb.append(info.getLockOwnerName()).append("\" Id=").append(info.getLockOwnerId());
154 }
155 sb.append(")");
156 }
157 break;
158 }
159 default:
160 break;
161 }
162 }
163 }