WEBINAR:
On-Demand
Application Security Testing: An Integral Part of DevOps

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;
}
}
}