23
23
import java .lang .management .ThreadInfo ;
24
24
import org .apache .logging .log4j .message .ThreadInformation ;
25
25
import org .apache .logging .log4j .util .StringBuilders ;
26
+ import org .jspecify .annotations .Nullable ;
26
27
27
28
/**
28
29
* Provides information on locks and monitors in the thread dump. This class requires Java 1.6 to compile and
@@ -119,17 +120,17 @@ private void formatState(final StringBuilder sb, final ThreadInfo info) {
119
120
break ;
120
121
}
121
122
case WAITING : {
122
- final StackTraceElement element = info . getStackTrace ()[ 0 ] ;
123
- final String className = element .getClassName ();
124
- final String method = element .getMethodName ();
125
- if (className . equals ( "java.lang.Object" ) && method . equals ( "wait" )) {
123
+ final StackTraceElement element = getFirstStackTraceElement ( info ) ;
124
+ final String className = element != null ? element .getClassName () : null ;
125
+ final String method = element != null ? element .getMethodName () : null ;
126
+ if ("java.lang.Object" . equals ( className ) && "wait" . equals ( method )) {
126
127
sb .append (" (on object monitor" );
127
128
if (info .getLockOwnerName () != null ) {
128
129
sb .append (" owned by \" " );
129
130
sb .append (info .getLockOwnerName ()).append ("\" Id=" ).append (info .getLockOwnerId ());
130
131
}
131
132
sb .append (')' );
132
- } else if (className . equals ( "java.lang.Thread" ) && method . equals ( "join" )) {
133
+ } else if ("java.lang.Thread" . equals ( className ) && "join" . equals ( method )) {
133
134
sb .append (" (on completion of thread " )
134
135
.append (info .getLockOwnerId ())
135
136
.append (')' );
@@ -144,19 +145,19 @@ private void formatState(final StringBuilder sb, final ThreadInfo info) {
144
145
break ;
145
146
}
146
147
case TIMED_WAITING : {
147
- final StackTraceElement element = info . getStackTrace ()[ 0 ] ;
148
- final String className = element .getClassName ();
149
- final String method = element .getMethodName ();
150
- if (className . equals ( "java.lang.Object" ) && method . equals ( "wait" )) {
148
+ final StackTraceElement element = getFirstStackTraceElement ( info ) ;
149
+ final String className = element != null ? element .getClassName () : null ;
150
+ final String method = element != null ? element .getMethodName () : null ;
151
+ if ("java.lang.Object" . equals ( className ) && "wait" . equals ( method )) {
151
152
sb .append (" (on object monitor" );
152
153
if (info .getLockOwnerName () != null ) {
153
154
sb .append (" owned by \" " );
154
155
sb .append (info .getLockOwnerName ()).append ("\" Id=" ).append (info .getLockOwnerId ());
155
156
}
156
157
sb .append (')' );
157
- } else if (className . equals ( "java.lang.Thread" ) && method . equals ( "sleep" )) {
158
+ } else if ("java.lang.Thread" . equals ( className ) && "sleep" . equals ( method )) {
158
159
sb .append (" (sleeping)" );
159
- } else if (className . equals ( "java.lang.Thread" ) && method . equals ( "join" )) {
160
+ } else if ("java.lang.Thread" . equals ( className ) && "join" . equals ( method )) {
160
161
sb .append (" (on completion of thread " )
161
162
.append (info .getLockOwnerId ())
162
163
.append (')' );
@@ -174,4 +175,10 @@ private void formatState(final StringBuilder sb, final ThreadInfo info) {
174
175
break ;
175
176
}
176
177
}
178
+
179
+ @ Nullable
180
+ private static StackTraceElement getFirstStackTraceElement (final ThreadInfo info ) {
181
+ final StackTraceElement [] stackTrace = info .getStackTrace ();
182
+ return stackTrace != null && stackTrace .length > 0 ? stackTrace [0 ] : null ;
183
+ }
177
184
}
0 commit comments