Discussions

News: Ariadna: Free open source memory leak debugging tool

  1. Matthias Ernst has released a memory leak debugging tool. Ariadna requires JVMTI / JDK 5.0.

    ariadna is a low-overhead VM plugin that dumps a heap image on request. It is reference graph aware and finds the reference chain responsible for an object's survival. The heap can be analyzed with a web browser.

    ariadna is open source, released under the ASL.

    ariadna is very similar to Bill Foote's heap analysis tool HAT but should have lower overhead.

    Ariadna home page

    Threaded Messages (8)

  2. Hey,

    cool stuff.

    Which search strategy does Ariadna use? Depth-First? If so the reference chain most likely will not be the shortest path possible...

    I have built something similar that analyzes the dump of the default Java profiler. Uses lots of memory and can be used after termination of your program, but works for JDK 1.3 and 1.4:

    http://jsl.sourceforge.net/javaSniffer.html

    It is a demo application for a search library that next to breadth-first (used for the sniffer), depth-first and A* can be enabled to perform many other search strategies.

    Oliver
  3. Hi Oliver,

    ariadna uses breadth-first from the object in question towards the roots. The heap format basically is an adjacency list that is mmapped and sorted by referee.

    Matthias
  4. Ariadna uses breadth-first from the object in question towards the roots.

    Great, so you always have the shortes path. Can you let Ariadna display more than one path to the roots? Most of the time there is more than one path...

    Would be great if I could use it, but why does it work for 5.0 only? Using any special API there?
    The heap format basically is an adjacency list that is mmapped and sorted by referee

    So, does this mean your graph is directed then? Makes sense as you know in which way you will search. What does it mean the list is sorted by referee?

    My structure is a simple double linked graph. And it is constructed from the heap dump like HAT does. If you use it be sure to have lots of memory in your machine ;)

    Oliver
  5. Great, so you always have the shortes path. Can you let Ariadna display more than one path to the roots?

    Currently, no. I'm lacking a reasonable predicate to identify two paths as 'different'. It would be easy, though, to implement a 'next' button.
    why does it work for 5.0 only?
    As far as I understand, the JVMPI formats for heap dumps (beyond the very basic one that doesn't include references) are not self-describing. They give you a block of memory whose format can only be interpreted if you know the classes' fields. I was too lazy to collect these via JNI. JVMTI is much nicer in this respect, although they still tell you field offsets that are not easily mapped to, say, JNI jFieldIds. That's why ariadna doesn't tell you which field the reference is in ...
    does it mean the list is sorted by referee?
    The heap dump file is directly mapped into memory as a MappedByteBuffer. It is sorted so that incoming references to an object are grouped together and can be found through binary search. BTW, I suspect quicksort on a mmapped file probably isn't the most efficient algorithm WRT paging ...
  6. Sometimes you will have more than one path from an object to the roots I guess. Knowing the referencing field would be convenient as well, however, which one it is should be obvious from code most of the time, I guess.

    You say you lack a predicate to tell two paths are different. This makes me wonder, how does your search algorithm work? I implemented the search with an open and a closed list and this makes it pretty easy to continue the search after a root has been found: you just expand the next reference on the open list. Wouldn't that work for you as well? Or are you using a different strategy?

    Oliver
  7. You say you lack a predicate to tell two paths are different.

    I wasn't clear. I meant "sufficiently" different to be of additional value to the user. Often there's tons of different paths that are equivalent in nature. Example: the log4j root logger that is reachable through all "parent" fields from other loggers who are all reachable from statics in the classes which are all reachable because some class in this classloader is still held in a thread local. These are all similar paths and they would annoy me. I rather want a way to cut the graph at a user-defined location. A "what if this leak were fixed" query.
    This makes me wonder, how does your search algorithm work? I implemented the search with an open and a closed list.

    Ahem, I have no idea what an open and closed list are. I iterate as follows:

    chains(0) = [[ query ]]
    chains(n+1) = [ next:chain | chain <- chains(n), next <-referrersthathavenotbeenvisitedyet(head(chain)) ]

    Until I find a chain that starts with a GC root.

    (If this annoys people we can take the discussion offline. Mail me at matthiasdoternstatcoremediadotcom).

    Matthias
  8. JVMTI Rocks![ Go to top ]

    I wrote a tool like this for JDK 1.4 that used JVMPI to splat out the heap, run over that, etc.

    The big problem is that the API for JDK 1.4 requires huge amounts of memory to be allocated and ended up being really slow (especially if you had a really big heap)

    The improvements in JVMTI are awesome.

    One thing we had in our tool that I didn't see in Ariadna is a way to call into the profiler peice through Java. We had a couple of APIs like

       WriteReferencesForObjects(Object[] o, File f)

    where you could call into the profiler through JNI to have it write out a file that shows the references to the objects in the array. We then coupled this with our Checkin tests, so if the tests ran into a situation they thought was a memory leak, the developer would immediately get a file with the objects and their references.

    For JDK 1.4 we played a little loosy-goosey by only loading the dll when we needed to make our JNI calls (rather than on dll load). Not sure if you can do this in JDK 1.5 (because I'm not sure if you can add the tag objects and can can_generate_garbage_collection events if you are not in the Init phase).
  9. JVMTI Rocks![ Go to top ]

    We had a couple of APIs like &nbsp;&nbsp;&nbsp;WriteReferencesForObjects(Object[] o, File f)where you could call into the profiler through JNI to have it write out a file that shows the references to the objects in the array. We then coupled this with our Checkin tests, so if the tests ran into a situation they thought was a memory leak, the developer would immediately get a file with the objects and their references.

    This sounds really cool, is this tool available anywhere?

    Oliver