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