Wednesday, November 19, 2008

Ah.. Java

I've been using Java for a few years now. And one thing that i've come across is.. memory leaks.

"Memory leaks?" you say. Yup. "In Java? That's unpossible!" you exclaim.

No really. It's true. The garbage collector makes a fine effort to clean up most unused objects, but every so often you'll get an object being stored that can't be collected because it's still referenced somewhere. Usually these are caused by putting a object into a static Map, or Array somewhere. Mostly it's the programmers fault, though the JRE/JDK itself may have some. This one for example is caused when you use a JPopup. A reference to the JComponent it is displayed on is kept internally by the standard Java libraries. If you only ever have one JPopup in your entire program, say in a startup page, and the rest of the program is all console based, then the reference to your window will be kept until the program exits. If your program is a daemon designed to run on a server, that could be a very very long time.

So.. how to find them? Well, luckily it's only a few step process.

Finding memory leaks using the Standard JDK 5.0 tools.


1. Run the program to check for leaks.
2. Try to do something that will expose the memory leak
3. Find the PID of the the java program by running jps.exe
4. Dump the memory of the program with this command
jmap -dump:format=b,file=heap.bin
5. Run jhat, it will start a webserver on the computer it's run on at port 7000
jhat -J-mx512m heap.bin
6. Load http://localhost:7000/ for general data
7. Load http://localhost:7000/histo/count and find the class you think is leaking, click on the link
8. Scroll down till you find the section called "Instances" and click "Include subclasses"
9. Find the instance that leaked and click it
10. Scroll down till you find the link "Exclude weak refs" and click it
11. A list of references will appear. Ignore any that contain a class called sun.awt.AppContext, or AppClassLoader as these classes are Java internal classes
12. The rest of the page will show which classes are still holding references to the object. Find out why it's holding it. Maybe you forgot to do a .remove() when the item was no longer needed.

No comments: