To bring one step further what chohan wrote ...
I usually have all my classes implementing the Destructable interface (even my JUnit tests :-) )
public interface Destructable
{
public void destruct ();
}
Then in evey single class as advised, you can also nullify all the references :
public class MyCustomClass
implements Destructable
{
// Do you own business & then ...
// add this
public void destruct ()
{
ObjRef = null;
}
}
I always advise not to call System.gc; unless you can do so always after nullifying many reference. Do do it after many objects have been cut appart.
I usually try to have the finalize () interacting intelligently with the destruct interface but it can be risky ! Say you have destruct an Object & then nullified it ... If you call the method a second time the call to destruct () to the object you have references to will generate an NullPointerException that you should trap.
Now another comment about your Threads.
May be you should make sure that they clearly step out of the run () method. As a matter of fact, if the run method does not run out the Threads stay active & the Class cannot be GCed - as well as all the classes (instances of ...) that are referenced by it.
Also if you have many Frames & JFrames, you should make sure you invoke the dispose () method each time !
Also you should make sure you always do a late initialization of all the Object an instance references.
Say you have a class holding a reference to a HashMap. Here is a bit of code you will find in many occasion :
public class MyCustomClass
{
// This instance is almost immediately marked for GC
// (as soon as teh constructor is run)
public HashMap hm = (HashMap) new HashTable();
MyCustomClass ()
{
hm = (HashMap) new HashTable();
}
public void setValue (...)
{
hm.setValue (...);
}
HashMap getMap()
{
return hm;
}
}
With late initialization, you could then do like this :
public class MyCustomClass
{
// This instance is almost immediately marked for GC
// (as soon as teh constructor is run)
public HashMap hm = null;
MyCustomClass ()
{
}
public void setValue (...)
{
if (hm == null)
hm = (HashMap) new HashTable();
hm.setValue (...);
}
HashMap getMap()
{
if (hm == null)
hm = (HashMap) new HashTable();
return hm;
}
// Provide a proper destruct ()
// First removing hm content & then emptying it !
}
Finally,
For performance issues O Reilly has a very good book about it. Use also JunitPerf (see on www.junit.org for references).
Rgds,
Thomas,
At IBM there is a tutorial on how to do that properly.
I remember pposting it to a person I "worship" :-))
Chuck a look there !
http://www-105.ibm.com/developerworks/education.nsf/dw/java-onlinecourse-bynewest?OpenDocument&Count=500