devxlogo

Memory Management

Memory Management

ven though the Java Virtual Machine performs automatic garbagecollection, you can’t completely forget about memory managementissues. How and when garbage collection is performed isimplementation dependent. Some JVMs will wait until allavailable memory is used up before kicking in the garbage collector,while others will run it incrementally. That is why Runtime.gc() isincluded in the core APIs. Invoking this method will ask the JVMto run the garbage collector. Unfortunately, it is only a hintto the JVM that you would like the garbage collector to run, andthere is no guarantee that it will actually run at all. However,many JVMs will run the garbage collector shortly after this call.

The finalize() method is another tricky spot. You should not thinkof this as the Java equivalent of a destructor. C++ makes guaranteesabout when destructors are executed. Java makes no hard promisesabout when finalize() will be invoked, other than that it will run at some point before the memory used by the object is reused. That is why Runtime.runFinalization() is provided, but, again, no guarantee ismade that finalization will actually run immediately after the call.It is only a hint or request to run all the finalizers of eligibleobjects.

Java 2 provides a greater ability to manage memory in thejava.lang.ref package. Contrary to popular belief, Java programs canleak memory. If you stop using an object, but retain a strong referenceto it, the object will never be garbage-collected. It is common forcertain data structures, like caches, to unintentionally leak memoryin this manner. Java 2 provides Weak References to alleviate thisproblem. If an object is only referenced by weak references, it maybe garbage-collected.

The Java 2 reference classes include a non-instantiable Reference baseclass and three subclasses that define different types of weakreferences: SoftReference, WeakReference, and PhantomReference. AReference is a wrapper around a Java object that does not maintaina strong reference to the object. The garbage collector uses animplementation-dependent algorithm to determine whether or not to garbage-collect a SoftReference, whereas a WeakReference is alwaysreclaimed. A PhantomReference can be associated with a ReferenceQueuewhich allows you to perform post-finalization operations on areference. The following example program gives a brief introductionto these concepts:

// $RCSfile: References.java,v $ $Revision: 1.1 $$Date: 1999/09/09 23:48:05 $color> import java.lang.ref.*;public class References {  public static void main(String[] args) {    Object weakObj, phantomObj;    Reference ref;    WeakReference weakRef;    PhantomReference phantomRef;    ReferenceQueue weakQueue, phantomQueue;    weakObj    = new String("Weak Reference");    phantomObj = new String("Phantom Reference");    weakQueue    = new ReferenceQueue();    phantomQueue = new ReferenceQueue();    weakRef    = new WeakReference(weakObj, weakQueue);    phantomRef = new PhantomReference(phantomObj, phantomQueue);    // Print referents to prove they exist.  Phantom referents    // are inaccessible so we should see a null value.color>    System.out.println("Weak Reference: " + weakRef.get());    System.out.println("Phantom Reference: " + phantomRef.get());    // Clear all strong referencescolor>    weakObj    = null;    phantomObj = null;    // Invoke garbage collector in hopes that references    // will be queuedcolor>    System.gc();    // See if the garbage collector has queued the referencescolor>    System.out.println("Weak Queued: " + weakRef.isEnqueued());    // Try to finalize the phantom references if not alreadycolor>    if(!phantomRef.isEnqueued()) {      System.out.println("Requestion finalization.");      System.runFinalization();    }    System.out.println("Phantom Queued: " + phantomRef.isEnqueued());    // Wait until the weak reference is on the queue and remove itcolor>    try {      ref = weakQueue.remove();      // The referent should be nullcolor>      System.out.println("Weak Reference: " + ref.get());      // Wait until the phantom reference is on the queue and remove itcolor>      ref = phantomQueue.remove();      System.out.println("Phantom Reference: " + ref.get());      // We have to clear the phantom referent even though       // get() returns nullcolor>      ref.clear();    } catch(InterruptedException e) {      e.printStackTrace();      return;    }  }}

devx-admin

Share the Post: