Java Solaris Communities Sun Store Join SDN My Profile Why Join?
 
Bug Database
Bug Detail
Quick Lists
Top 25 Bugs
Top 25 RFE's
Recently Closed Bugs
Printable Page Printable Page


Bug Database
Bug ID: 4966410
Votes 0
Synopsis Stacktrace missing from NullPointerException
Category hotspot:compiler2
Reported Against 1.4.2
Release Fixed
State 11-Closed, duplicate of 4292742, bug
Priority: 4-Low
Related Bugs 4292742
Submit Date 10-DEC-2003
Description




FULL PRODUCT VERSION :
java version "1.4.2_01"
Java(TM) 2 Runtime Environment, Standard Edition (build 1.4.2_01-b06)
Java HotSpot(TM) Client VM (build 1.4.2_01-b06, mixed mode)


ADDITIONAL OS VERSION INFORMATION :
Linux mattias-laptop 2.4.20 #4 SMP Fri Aug 8 09:48:27 CEST 2003 i686 i686 i386 GNU/Linux
(This Linux installation is a  customer  9 with a modified kernel).

Windows 2000


A DESCRIPTION OF THE PROBLEM :
Under some (unclear) circumstances NullPointerExceptions can be thrown without any stacktrace. This makes the error handling within our system difficult. (The fact that the NullPointerException is thrown is not the bug - this is expected behaviour)

This only seems to happen when the JVM is run with "-server" option.

For more details on the problem see "Steps to Reproduce" below


STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
I have managed to create a small testcase that reproduces the issue. There is one Makefile and a source file "StackTraceTest.java".  I am pasting them below as text (ie in the "Source code..." entry).

With these files
1. Place the files in the current directory
2. Make sure JAVA_HOME environment variable is set
3. Run "make"
4. Run "make runtest"

One strange effect I noted was that if the line "import java.lang.reflect.*;" was removed from the test program, the problem seems to happen later (ie after about 6000 testruns instead of 2000). Should this even affect the generated class file in any way??


EXPECTED VERSUS ACTUAL BEHAVIOR :
EXPECTED -
The NullPointerException should always include stacktrace.
ACTUAL -
After a number of Ok testruns by the program (typically around 2000), the test results in a NullPointerException with no stacktrace. After the first failure, all subsequent runs seem to fail as well.

ERROR MESSAGES/STACK TRACES THAT OCCUR :
...
****** validation failed. Thread 100, test run 9, total count 2181
java.lang.NullPointerException
 
****** validation failed. Thread 37, test run 23, total count 2182
java.lang.NullPointerException
 
****** validation failed. Thread 38, test run 23, total count 2183
java.lang.NullPointerException
...

Note the lack of stacktrace on the NullPointerExceptions.


REPRODUCIBILITY :
This bug can be reproduced often.

---------- BEGIN SOURCE ----------
================== StackTraceTest.java =================

import java.lang.reflect.*;
import java.io.*;
import java.util.*;

public class StackTraceTest extends Thread
{
    public static void main( String[] args )
        throws Exception {
        
        System.out.println("Starting...");
        int threadCount = 100;
        int testCount = 100;

        StackTraceTest[] tests =
            new StackTraceTest[ threadCount ];
        for( int i=0; i<threadCount; ++i ) {
            tests[i] = new StackTraceTest();
        }
        for( int j=0; j<tests.length; ++j ) {
            tests[j].start();
        }
        for( int i=0; i<testCount; ++i ) {
            for( int j=0; j<tests.length; ++j ) {
                tests[j].addAction( RUN_TEST );
            }
        }
        for( int j=0; j<tests.length; ++j ) {
            tests[j].addAction( EXIT );
        }
    }
    
    private final static int NO_ACTION = 0;
    private final static int RUN_TEST = 1;
    private final static int EXIT = 2;

    private LinkedList _actionList = new LinkedList();

    private static int threadIdCounter = 0;
    private static synchronized int getThreadId() {
        return ++threadIdCounter;
    }

    private int _threadId = getThreadId();
    private int _testCount = 0;

    public void run() {

        int action;
        do {
            action = getAction();
            if( action == RUN_TEST ) {
                test(null);
            }
            try {
                // Wait 1/10 sec
                synchronized( this ) {
                    wait(100);
                }
            } catch( InterruptedException ignored ) {}
        } while( action != EXIT );
    }

    private synchronized int getAction() {
        if( _actionList.isEmpty() ) {
            return NO_ACTION;
        } else {
            return ((Integer)_actionList.removeFirst()).intValue();
        }
    }

    public synchronized void addAction( int action ) {
        _actionList.addLast( new Integer(action));
        notify();
    }

    private static String _refResult = null;
    private static int _totalTestCount = 0;
    private static synchronized void validateResult(
        String result, int threadId, int testCount ) {

        ++_totalTestCount;
        if( _totalTestCount % 1000 == 0 ) {
            System.out.println( "Total Count: "+_totalTestCount );
        }

        if( _refResult == null ) {
            _refResult = result;
        } else {
            if( ! _refResult.equals( result )) {
                System.out.println("****** validation failed. Thread "+
                                   threadId+", test run "+testCount+
                                   ", total count "+_totalTestCount);
                System.out.println(result);
            }
        }
    }

    public void test( String s ) {

        ++_testCount;
        try {
            "ABC".startsWith( s );
        }
        catch( Exception e ) {
            StringWriter sout = new StringWriter();
            e.printStackTrace(new PrintWriter(sout));
            String result = sout.toString();
            validateResult( result, _threadId, _testCount );
        }
    }
}

=============== Makefile ========================
StackTraceTest.class: StackTraceTest.java
	$(JAVA_HOME)/bin/javac $^

runtest:
	$(JAVA_HOME)/bin/java -server -cp . StackTraceTest

runtest_client:
	$(JAVA_HOME)/bin/java -client -cp . StackTraceTest


---------- END SOURCE ----------

CUSTOMER SUBMITTED WORKAROUND :
Run JVM without "-server" flag
(Incident Review ID: 230192) 
======================================================================
Work Around
Run with -Xint

  xxxxx@xxxxx   2003-12-15

Some observation that I have made 

For jdk 1.3.1

For -server
Use -Xint or -Xcomp  
use -XX:-OmitStackTraceInFastThrow ( 1.3.1_14 and above )


Use client 

For jdk 1.4.2

For -server

Use -Xint 
Use -Xcomp  
Use -XX:+FullSpeedJVMDI ( 1.4.2_05 and above )

or Use client

For jdk 1.5

use -XX:-OmitStackTraceInFastThrow

Use client
choon-  xxxxx@xxxxx   2004-11-25 05:23:42 GMT
choon-  xxxxx@xxxxx   2004-11-25 07:44:56 GMT
Evaluation
Reproduced on Sparc:

jaberwocky% java -server StackTraceTest
Starting...
Total Count: 1000
Total Count: 2000
Total Count: 3000
****** validation failed. Thread 22, test run 40, total count 3968
java.lang.NullPointerException

****** validation failed. Thread 59, test run 41, total count 3969
java.lang.NullPointerException


Pass to the runtime group.

  xxxxx@xxxxx   2003-12-10


Running with java -server -Xint StackTraceTest  test always passes for me.
Running in mixed mode seems to trigger this exception.

  xxxxx@xxxxx   2003-12-12

The testcase runs for a short bit in interpretted mode. Eventually the result or the method call gets hot thus a compile. Since their appears to be a difference between compiled exception string returned and interpretted string returned testcase fails.  This appears to be a compiler bug or testcase issue..
This is reproducible in JDK 1.5.0-b31 latest...  Assigning to compiler team for further review...
Comments
  
  Include a link with my name & email   


PLEASE NOTE: JDK6 is formerly known as Project Mustang