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