Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Howto print java class garbage collection events?

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.

like image 856
Maxim Veksler Avatar asked Feb 21 '09 23:02

Maxim Veksler


People also ask

How do you monitor garbage collection activities?

The typical CUI GC monitoring method involves using a separate CUI application called "jstat", or selecting a JVM option called "verbosegc" when running JVM. GUI GC monitoring is done by using a separate GUI application, and three most commonly used applications would be "jconsole", "jvisualvm" and "Visual GC".


3 Answers

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.

like image 88
Hubert Avatar answered Oct 06 '22 02:10

Hubert


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.

like image 45
ng. Avatar answered Oct 06 '22 00:10

ng.


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

like image 35
Maxim Veksler Avatar answered Oct 06 '22 01:10

Maxim Veksler