Java Performance Services
Training, Seminars, Benchmarking, Tuning

Java Performance Tuning Course


Chania Crete, May 17-20, 2010


Sun Extreme Learning EXL-2025

Houston, December 1-4,2009
New York, December 8-11, 2009
Washington DC, January 5-8, 2010



San Francisco, January 11-14

Anti-if

I have joined Anti-IF Campaign

Calendar

««Nov 2009»»
SMTWTFS
1234
5
67
891011121314
15161718192021
22232425262728
2930

Performance Anti-Patterns

My Top Tags

                                       

Mailing List

My RSS Feeds








Using NetBeans 6.0 to Find that Elusive Memory Leak

posted Wednesday, 14 March 2007
Last week I spent some time on the phone with Gregg Sporar, a NetBeans evangelist, looking at the new NetBeans 6.0 Profiler. Some time ago I’d given Gregg a chunk of code and asked him to find the memory leak using NetBeans. The only ground rule was; he was to avoid looking at the code. Some time later Gregg came back and showed me how he’d used NetBeans to locate the leak.

Though Gregg had found the leak, the process was less than satisfactory from my point of view. Gregg had used a lot of his vast experience with solving these problems in order to solve this problem. And, he had to dive into the code far earlier in the process than what I would have liked. Even though the code is trivial, it still took a few hours before he nailed it.

What I really wanted was a process that someone with far less experience than Gregg could follow. I also wanted to avoid the code can follow yet still be successful. Some of the answer to this problem is in better tooling. Fortunately that improvement in tooling can be found in Netbeans 6.0 M7. The two most promising features IMHO are generations and path to closest GC Walker. I’ll start with generations and show how it enabled Gregg to quickly find the leaking object.

Where as our age is computed by tallying the number of winters we survive, an objects age is calculated by the number of garbage collection cycles that is survives. So it stands to reason that if we look at the age of each object we should find that the ones that leak will be much older than ones that don’t. There are a few obvious exceptions to this. For example, data that is loaded at startup and is kept in memory for the duration. That said, a quick examination of a list of really old objects with some semantic knowledge should reveal objects that are leaking. As it so happens, NetBeans profiler provides you with that information.

The feature, called generations, provides the list of objects and ages that can be used to help determine just which object is leaking. Using this feature, Gregg found what was leaking in minutes. However, it didn’t tell him where the leak was. Without the heapwalker tool, Gregg was forced to dive into the code.

Just last week Gregg and I reloaded the other half of the problem, finding where the object leaking. For that we used Heap Walker found in NetBeans 6.0 M7. The first set in using heapwalker is to get a binary heap dump. You can do that using -Xrunhprof or simply triggering a dump using jconsole or jmap. Once imported into NetBeans, the profiler offers a view of all objects in the heap. From the classes view you can select an instance and from there see it’s reference information. From the reference information you can display the shortest path to a GC root.

What Gregg and I found when we did this was not only the source of the leak but we made a more interesting observation. The source of the leak was the only domain object between the GC root and the object that was leaking. After a quick back and forth I concluded that this wasn’t an accident and in fact it could be the basis for a process to help in the diagnosis of memory leaks. To test this out we quickly cobbled together yet another test case. In this case it was a leak on a the http session object. The problem was; the application was too simple to confirm the initial observation. IOWs we just didn’t have a domain object to show up between the leakee and the GC root. However the session state is an implied collection and it was very easily identified as the source of the leak.

Where does all of this stand? It seems that by using a combination of generations and heapwalker one should be able to quickly diagnose memory leaks. It also seems that there maybe a way to automate the diagnostic process just as deadlock detection has been baked in today. However, we only used the technique on a very small number of applications so it could all be a red-herring also. As soon as I get some time, I plan on trying out this more difficult case described by Attila Szegedi. I’m also interested in hearing about any experiences other have in using the new profiling features.

tags:        




1. tomasz left...
Thursday, 5 April 2007 6:45 pm

Thank you so much for the post! I've been searching through a lot of profiling related material and this one seemed to hit the spot for me. Tried it immediately, but hit a snag and wonder if I could ask for a little more feedback.

I was able to generate the binary heap dump on a remote machine, downloaded it to my local box and tried to load it into the profiler through 'Profile > LoadHeatDump...' that's when NB6 gives me this: - - java.lang.IllegalArgumentException

  • at sun.nio.ch.FileChannelImpl.position(FileChannelImpl.java:278)

  • at com.sun.tools.profiler.heap.LongMap.<init>(LongMap.java:40)

  • at com.sun.tools.profiler.heap.Hpr ofHeap.<init>(HprofHeap.java:92)

  • at com.sun.tools.profiler.heap.HeapFactor y.createHeap(HeapFactory.java:48)

  • at com.sun.tools.profiler.heap.HeapFactory.createHeap(HeapFactory .java:31)

  • at org.netbean s.modules.profiler.heapwalk.HeapWalker.createHeap(HeapWalker.java:158)

    < /li>
  • at org.netbeans.modules.prof iler.heapwalk.HeapWalker.<init>(HeapWalker.java:50)

  • at org.netbeans.modules.profiler.heapwalk .ui.OpenHeapWalkerAction$1.run(OpenHeapWalkerAction.java:39)

  • at org.openide.util.RequestProcessor$ Task.run(RequestProcessor.java:541)

at org.openide.util.RequestProcessor$Processor.run(RequestProcessor.java:963)

- does the profiler expect a particular file type, extension, etc? could the file be getting corrupted during transfer from remote to local machine?

I'm using NB6 M7 on OS X 10.4.9 PPC The heap dump got generated with the following argument: -J-Xrunhprof:heap=sites,cpu=samples,format=b,file=java.hprof.bin.txt

Thanks


2. Kirk Pepperdine left...
Thursday, 5 April 2007 7:37 pm

Hi Tomasz,,

Though Apple is annoyingly behind on Java releases and this stuff is cutting edge. That said, M7 does work on Mac OS. I used it in a demonstration on my Mac in Vegas two weeks ago.

The command line seems fine if one considers that -J is used to pass the parameter along to another JVM and the space in form at=b is exclusive to this blog entry. I say this because the error looks similar to one you may get if you load an ascii version of the dump. IOWs, format=b is not optional ;-}

Did you report the bug to the netbeans team? I'm almost certain they will be interested in hearing from you.


3. tomasz left...
Thursday, 5 April 2007 8:05 pm

... that's what I was afraid of, but I though 'let's double check that', so I really appreciate your response. I'd much rather use Linux for this type of stuff, but that's beyond my control at this point.