How to tell when a Java object's memory is released?
I have a Swing browser application with a bug that as I add/remove to/from t开发者_Python百科he GUI the memory isn't released for those objects and I'm trying to track down what is holding onto them. Problem is I don't know how to tell when something has actually be fully released from memory.
Is there a way to tell if an object has been released from memory? I'm used to Objective-C where there are several ways to tell.
Thanks
You can't really do it in Java. All the answers mentioning finalizers are really not what you're after.
The best you can do is enqueue a PhantomReference in a ReferenceQueue and poll until you get the reference.
final ReferenceQueue rq = new ReferenceQueue();
final PhantomReference phantom = new PhantomReference( referenceToObjectYouWantToTrack, rq );
You want to read Peter Kofler's answer here (it explains what a PhantomReference is):
Have you ever used Phantom reference in any project?
Very interesting read here:
http://www.kdgregory.com/index.php?page=java.refobj
Basically, I'm using a PhantomReference in a project where a very special kind of cache needs to be computed once, when the software is installed. To efficiently compute this (disk-based) cache, a gigantic amount of memory is needed (the more the better). I'm using a PhantomReference to track "nearly exactly" when that gigantic amount of memory is released.
There are multiple ways of detecting memory leaks. Here the three I'm currently thinking of:
- Attaching a Profiler to your application (Netbeans or Eclipse TPTP should be useful here)
- Making a heap dump and analyze (with Eclipse Memory Analyzer) what instances of a class are held in memory by which other instances.
- Attaching VisualVM to track Garbage Collection status.
Edit:
As NoozNooz42 has pointed out, a PhantomReference
can do everything a finalizer can, without the problems finalizers present. So, I encourage using PhantomReferences
over extending finalize()
. I am keeping my original post in tact, since I think Java programmers should at least know that finalize()
exists.
Original Post:
Every Java class has a finalize()
method that gets run when no other Objects hold a reference to that class. You can extend this method like so:
protected void finalize() throws Throwable {
try {
// Do whatever you want
} finally {
super.finalize();
}
}
By doing so, you can figure out if anything holds a reference to the Objects in question. Just make sure you always call super.finalize()
if you use this approach.
Reference on finalization:
http://java.sun.com/developer/technicalArticles/javase/finalization/
Try YourKit. It's a Java profiler which can show you your memory usage and what the heck is going on. IIRC, the free trial can integrate with Eclipse and has all of the paid version's features (it just has a time limit).
精彩评论