United StatesChange Country, Oracle Worldwide Web Sites Communities I am a... I want to...
Bug ID: JDK-6571589 (thread) Thread.getStackTrace() returns null
JDK-6571589 : (thread) Thread.getStackTrace() returns null

Details
Type:
Bug
Submit Date:
2007-06-20
Status:
Closed
Updated Date:
2011-05-18
Project Name:
JDK
Resolved Date:
2011-05-18
Component:
core-libs
OS:
windows_xp
Sub-Component:
java.lang
CPU:
x86
Priority:
P3
Resolution:
Fixed
Affected Versions:
5.0,6u2
Fixed Versions:

Related Reports
Backport:
Backport:
Backport:
Relates:

Sub Tasks

Description
With the following test program, NullPointerException will be
thrown. That is not in line with the API.
http://java.sun.com/javase/6/docs/api/java/lang/Thread.html#getStackTrace()

TP:
----->
public class STNull {
  public static void main(String[] args) throws Exception {
    while(true) {
      Thread t = new Thread();
      t.start();
      StackTraceElement[] stes = t.getStackTrace();
      System.out.println(stes.length);
    }
  }
}
<-----

One of our customers reported NPE would be seen on Linux/EM64T below.

----->
java version "1.5.0_12"
Java(TM) 2 Runtime Environment, Standard Edition (build 1.5.0_12-b04)
Java HotSpot(TM) 64-Bit Server VM (build 1.5.0_12-b04, mixed mode)

java version "1.6.0_02"
Java(TM) SE Runtime Environment (build 1.6.0_02-b04)
Java HotSpot(TM) 64-Bit Server VM (build 1.6.0_02-b04, mixed mode)

java version "1.7.0-ea"
Java(TM) SE Runtime Environment (build 1.7.0-ea-b13)
Java HotSpot(TM) 64-Bit Server VM (build 1.7.0-ea-b13, mixed mode)
<-----

I also reproduced this against both jdk 5.0 and jdk 6.0 on my Windows
XP laptop as follows.

----->
$ java -version
java version "1.5.0_10"
Java(TM) 2 Runtime Environment, Standard Edition (build 1.5.0_10-b03)
Java HotSpot(TM) Client VM (build 1.5.0_10-b03, mixed mode, sharing)

$ java STNull
0
0
0
0
0
Exception in thread "main" java.lang.NullPointerException
        at STNull.main(STNull.java:7) 

$ /g/jdk60/bin/java -version 
java version "1.6.0"
Java(TM) SE Runtime Environment (build 1.6.0-b105)
Java HotSpot(TM) Client VM (build 1.6.0-b105, mixed mode)

$ /g/jdk60/bin/java STNull
0
0
0
0
0
0
0
0
Exception in thread "main" java.lang.NullPointerException
        at STNull.main(STNull.java:7) 
<-----

                                    

Comments
EVALUATION

The problem here is that there is a race between the thread calling getStackTrace and the thread, on which the stacktrace is trying to be retrieved, terminating. The library code for getStackTrace calls isAlive to determine if the thread is alive before calling into the vm to retrieve its stacktrace. Of course the thread may be alive at this point and subsequently terminate before the vm tries to retrieve its stacktrace.

Looking at the vm operation VM_ThreadDump it looks this this code quite rightly handles threads that have terminated or are exiting, by adding a ThreadSnapshot that has a NULL _stack_trace. The problem or area of contention seems to be that ThreadService::dump_stack_traces when it sees a NULL stacktrace in one of the snapshots it puts a NULL into the StackTraceElement[][] instead of possibly an empty StackTraceElement[] element. The library code is not expecting this null.

..or is it. Thread.getAllStackTraces already tests for a possible null
element in the StackTraceElement[][] returned from JVM_DumpThreads. So that being said I have amended the library code to handle this situation.

*** (#1 of 1): [ UNSAVED ] ###@###.###
                                     
2007-06-25
EVALUATION

Also:
1) Update getAllStackTraces to remove redundant isAlive check and amend the logic to only add traces for threads that have stacktraces available, i.e. not null.

2) Add extra clarification to getStackTrace specification about the possible return value of a thread that has been started but has not yet been scheduled to run by the system
                                     
2007-06-25
SUGGESTED FIX

------- Thread.java -------
1398c1398,1399
<      * this thread has not started or has terminated.
---
>      * this thread has not started, has started but has not yet been
>      * scheduled to run by the system, or has terminated.
1437a1439,1440
>           // optimization so we do not call into the vm for threads that
>           // have not yet started or have terminated
1441c1444,1451
<           return dumpThreads(new Thread[] {this})[0];
---
>           StackTraceElement[][] stackTraceArray = dumpThreads(new Thread[] {this});
>           StackTraceElement[] stackTrace = stackTraceArray[0];
>           // a thread that was alive during the previous isAlive call may have
>           // since terminated, therefore not having a stacktrace.
>           if (stackTrace == null) {
>               stackTrace = EMPTY_STACK_TRACE;
>           }
>           return stackTrace;
1499,1503c1509,1510
<             if (threads[i].isAlive()) {
<                 StackTraceElement[] stackTrace = traces[i];
<                 if (stackTrace == null) {
<                     stackTrace = EMPTY_STACK_TRACE;
<                 }
---
>             StackTraceElement[] stackTrace = traces[i];
>             if (stackTrace != null) {
1505c1512,1513
<             }
---
>           }
>           // else terminated so we don't put it in the map
                                     
2007-06-25



Hardware and Software, Engineered to Work Together