users@glassfish.java.net

NPE in glassfish-v1_ur1-p01-b02 -- AMXDebug.java

From: <glassfish_at_javadesktop.org>
Date: Wed, 25 Jun 2008 08:06:05 PDT

I am getting NullPointerException in AMXDebug.getDebug() while starting up glassfish. I am using glassfish-v1_ur1-p01-b02.

The stack-trace is as follows:
Caused by: java.lang.NullPointerException
at com.sun.appserv.management.base.AMXDebug.getDebug(AMXDebug.java:336)
at com.sun.enterprise.management.support.MBeanImplBase.getAMXDebug(MBeanImplBase.java:537)
at com.sun.enterprise.management.support.MBeanImplBase.debug(MBeanImplBase.java:572)
at com.sun.enterprise.management.support.MBeanImplBase.trace(MBeanImplBase.java:307)
at com.sun.enterprise.management.support.AMXImplBase.registerSelfMgrChildren(AMXImplBase.java:2052)
at com.sun.enterprise.management.support.AMXImplBase.registerSpecialContainees(AMXImplBase.java:2065)
at com.sun.enterprise.management.support.AMXImplBase.preRegister(AMXImplBase.java:2207)
at com.sun.jmx.interceptor.DefaultMBeanServerInterceptor.preRegisterInvoke(DefaultMBeanServerInterceptor.java:1010)

The relevant code is as follows:

com/sun/appserv/management/base/AMXDebug.java: (I have added line numbers as comments for convenience here)

private final Map<String,WrapOutput> mOutputs; //line 124

public boolean //line 333
getDebug( final String id ) //line 334
{
return _getOutput( id ).getDebug(); //line 336
}

private WrapOutput //line 492
_getOutput( final String id ) //line 493
{
WrapOutput output = mOutputs.get( id ); //line 495
if ( output == null ) //line 496
{
synchronized( this ) //line 498
{
if ( mOutputs.get( id ) == null ) //line 500
{
debug( "Creating output for " + StringUtil.quote( id ) );
try
{
output = new WrapOutput( getOutputFile( id ), mDefaultDebug ); //line 505
mOutputs.put( id, output ); //line 506
}
catch( Throwable t )
{
debug( "Couldn't create output for " + StringUtil.quote( id ) ); //line 510
}
}
} //line 513
} //line 514

return output;
} //line 517

Is it possible to get a NPE here? I can see the following scenario:
Lets say two threads execute method getDebug(String id) simultaneously with the same id. Both thread-A and thread-B come in "_getOutput(final String id)" in line 493, both thread-A and B finds output is null in line 496. Thread-A acquires lock in line 498, thread-B is waiting for lock in line 498. Thread-A goes ahead, initializes output in line 505, puts it in the map and comes out of synchronized block.
Now Thread-B gets lock on line 498, finds mOutputs.get(id) is not null in line 500 (as it was populated by thread-A) and then comes out of if block, synchronized block and returns the local variable "output" which was never re-initialized to a non-null value after line 495 (even though mOutputs.get(id) is not null now).
This is a possible scenario in which NPE can happen in Thread-B.

I am not sure if this is whats actually happening, though is a possible one. Also the above code is like classical Double-checked Locking where unsafe publication of not-fully initialized objects can happen. But even if the reference of "output" (in line 505) is not safely published, it ought not to be null. (and we are getting NPE). This DCL can be another bug that can come up in this code.

Is it possible that two threads are executing simultaneously as explained above? Or is it due to something else.

Thanks in advance for helping.

-- Abhishek
[Message sent by forum member 'abhisanoujam' (abhisanoujam)]

http://forums.java.net/jive/thread.jspa?messageID=282530