views:

619

answers:

4

Hello,

java version "1.5.0_14"
Java(TM) 2 Runtime Environment, Standard Edition (build 1.5.0_14-b03)
Java HotSpot(TM) Server VM (build 1.5.0_14-b03, mixed mode)

I'm trying to debug a NullPointerException I'm getting for passing a reference to statically defined field. To be more specific, I'm setting a global on a Drools3 working memory instance.

workingMemory.setGlobal("log", workingMemorieslog);

My assumption is that the Class where the field is statically defined is being garbage collected. (The receiving class must be using WeakReference or something like that, I don't really know)

How would you suggest to debug this? I think that if I could know exactly when JVM's GC unloads a class / instance of a class then I could narrow down on the cause of the buggy behavior. (If not the exact time of the event at least getting an indication that something did happened).

Thank you, Maxim.

A: 

Do you have the stack trace?

Have you tried stepping into the 'setGlobal' method (assuming you have the code) to see what's going on?

nbeyer
+1  A: 

To trace GC activity add this to java command:

-verbose:gc -XX:+PrintGCTimeStamps -XX:+PrintGCDetails

NPE that you are getting is probably you passing null value.

Hubert
Thank you for answering, I'm already running with -XX:+PrintGCDetails -verbose:gc -Xnoclassgc and still I see no class loading / unloading information. The only output I se are lines such as :[GC [PSYoungGen: 4096K->630K(4736K)] 4096K->790K(48064K), 0.0032750 secs]
Maxim Veksler
As this answer fits the best to the initial subject of the question I'm accepting it as answer. Thank you.
Maxim Veksler
+2  A: 

Why not keep the class in memory then see if it still happens, if it does then your problem lies elsewhere. If not then you know the issue lies in garbage collection.

ng
+1  A: 

It turns out that eclipse is the main issue here.

I'll explain:

I have wrapped our webapp in a main() method in order to test performance. We use a lot of 3rd party code, namely Apache commons-pool.

It turns out we had several versions of the jar spread across the projects (eclipse projects). My app which uses these projects had commons-pool-1.3, a different project had commons-pool-1.2.

When loaded using the servlet container (Tomcat6) the webapp class loader had first priority so it always loaded the webapp version. When I started the application using main() eclipse in it's not very wise behavior exported the depended projects jars in in the -classpath BEFORE the ones in the current project.

The conflict was between 2 versions of commons-pool, which caused a non defined behavior - On a object borrow is SOMETIMES decided to create a new object. I haven't looked inside the implementation code, I assume that this is something to do with a static map hold by the GenericKeyedObjectPool (the problematic class). Because a new instance was created it indeed contains a null reference to the mentioned global.

The solution to my luck was rather simple, commons-pool is being used only by my webapp so I could delete it from all referenced projects, otherwise I think i would just try to upgrade them all to a single version. If I couldn't do either I really don't know what would I've done. This is a very strange default of eclipse.

Thank you for reading and helping.

// ps. 3 days. That's the time I've spend on understanding what the hell I did wrong in my servlet replacement code. Turns out I'm not even the problem. :P

Maxim Veksler