Login | Register   
RSS Feed
Download our iPhone app
Browse DevX
Sign up for e-mail newsletters from DevX


Memory Management

Even though the Java Virtual Machine performs automatic garbage collection, you can't completely forget about memory management issues. How and when garbage collection is performed is implementation dependent.

ven though the Java Virtual Machine performs automatic garbage collection, you can't completely forget about memory management issues. How and when garbage collection is performed is implementation dependent. Some JVMs will wait until all available memory is used up before kicking in the garbage collector, while others will run it incrementally. That is why Runtime.gc() is included in the core APIs. Invoking this method will ask the JVM to run the garbage collector. Unfortunately, it is only a hint to the JVM that you would like the garbage collector to run, and there 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 think of this as the Java equivalent of a destructor. C++ makes guarantees about when destructors are executed. Java makes no hard promises about 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 is made that finalization will actually run immediately after the call. It is only a hint or request to run all the finalizers of eligible objects.

Java 2 provides a greater ability to manage memory in the java.lang.ref package. Contrary to popular belief, Java programs can leak memory. If you stop using an object, but retain a strong reference to it, the object will never be garbage-collected. It is common for certain data structures, like caches, to unintentionally leak memory in this manner. Java 2 provides Weak References to alleviate this problem. If an object is only referenced by weak references, it may be garbage-collected.

The Java 2 reference classes include a non-instantiable Reference base class and three subclasses that define different types of weak references: SoftReference, WeakReference, and PhantomReference. A Reference is a wrapper around a Java object that does not maintain a strong reference to the object. The garbage collector uses an implementation-dependent algorithm to determine whether or not to garbage-collect a SoftReference, whereas a WeakReference is always reclaimed. A PhantomReference can be associated with a ReferenceQueue which allows you to perform post-finalization operations on a reference. The following example program gives a brief introduction to these concepts:

// $RCSfile: References.java,v $ $Revision: 1.1 $ $Date: 1999/09/09 23:48:05 $ 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. System.out.println("Weak Reference: " + weakRef.get()); System.out.println("Phantom Reference: " + phantomRef.get()); // Clear all strong references weakObj = null; phantomObj = null; // Invoke garbage collector in hopes that references // will be queued System.gc(); // See if the garbage collector has queued the references System.out.println("Weak Queued: " + weakRef.isEnqueued()); // Try to finalize the phantom references if not already 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 it try { ref = weakQueue.remove(); // The referent should be null System.out.println("Weak Reference: " + ref.get()); // Wait until the phantom reference is on the queue and remove it ref = phantomQueue.remove(); System.out.println("Phantom Reference: " + ref.get()); // We have to clear the phantom referent even though // get() returns null ref.clear(); } catch(InterruptedException e) { e.printStackTrace(); return; } } }

Daniel F. Savarese holds a B.S. in astronomy and an M.S. in computer science, both from the University of Maryland, College Park. He is the author of the OROMatcher regular expression library for Java. Reach him here.
Comment and Contribute






(Maximum characters: 1200). You have 1200 characters left.



Thanks for your registration, follow us on our social networks to keep up-to-date