2323import java .lang .management .ThreadInfo ;
2424import org .apache .logging .log4j .message .ThreadInformation ;
2525import org .apache .logging .log4j .util .StringBuilders ;
26+ import org .jspecify .annotations .Nullable ;
2627
2728/**
2829 * 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) {
119120 break ;
120121 }
121122 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 )) {
126127 sb .append (" (on object monitor" );
127128 if (info .getLockOwnerName () != null ) {
128129 sb .append (" owned by \" " );
129130 sb .append (info .getLockOwnerName ()).append ("\" Id=" ).append (info .getLockOwnerId ());
130131 }
131132 sb .append (')' );
132- } else if (className . equals ( "java.lang.Thread" ) && method . equals ( "join" )) {
133+ } else if ("java.lang.Thread" . equals ( className ) && "join" . equals ( method )) {
133134 sb .append (" (on completion of thread " )
134135 .append (info .getLockOwnerId ())
135136 .append (')' );
@@ -144,19 +145,19 @@ private void formatState(final StringBuilder sb, final ThreadInfo info) {
144145 break ;
145146 }
146147 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 )) {
151152 sb .append (" (on object monitor" );
152153 if (info .getLockOwnerName () != null ) {
153154 sb .append (" owned by \" " );
154155 sb .append (info .getLockOwnerName ()).append ("\" Id=" ).append (info .getLockOwnerId ());
155156 }
156157 sb .append (')' );
157- } else if (className . equals ( "java.lang.Thread" ) && method . equals ( "sleep" )) {
158+ } else if ("java.lang.Thread" . equals ( className ) && "sleep" . equals ( method )) {
158159 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 )) {
160161 sb .append (" (on completion of thread " )
161162 .append (info .getLockOwnerId ())
162163 .append (')' );
@@ -174,4 +175,10 @@ private void formatState(final StringBuilder sb, final ThreadInfo info) {
174175 break ;
175176 }
176177 }
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+ }
177184}
0 commit comments