Programming errors can prevent garbage collection of objects that are no longer relevant to program operation. The garbage collector collects only unreachable objects; consequently, the presence of reachable objects that remain unused indicates memory mismanagement. Consumption of all available heap space can cause an
OutOfMemoryError, which usually results in program termination.
Noncompliant Code Example (Off-by-One Programming Error)
vector object in the noncompliant code example leaks memory. The condition for removing the
vector element is mistakenly written as
n > 0 instead of
n >= 0. Consequently, the method fails to remove one element per invocation and quickly exhausts the available heap space.
Compliant Solution (
This compliant solution corrects the mistake by changing the loop condition to
n >= 0. It also wraps the cleanup code in a
finally block so that it still executes even if the interim code throws an exception.
Compliant Solution (
Prefer the use of standard language semantics where possible. This compliant solution uses the
vector.clear() method, which removes all elements:
Noncompliant Code Example (Nonlocal Instance Field)
This noncompliant code example declares and allocates a
HashMap instance field that is used only in the
Programmers may be surprised that the
HashMap persists for the entire lifetime of the
Compliant Solution (Reduce Scope of Instance Field)
This compliant solution declares the
HashMap as a local variable within the
doSomething() method. The
hm local variable is eliminated after the method returns. When the local variable holds the only reference to the
HashMap, the garbage collector can reclaim its associated storage.
Localizing or confining the instance field to a narrower scope simplifies garbage collection; today's generational garbage collectors perform well with short-lived objects.
Noncompliant Code Example (Lapsed Listener)
This noncompliant code example, known as the Lapsed Listener [Goetz 2005a], demonstrates unintentional object retention. The
button continues to hold a reference of the
reader object after completion of the
readSomething() method, even though the
reader object is never used again. Consequently, the garbage collector cannot collect the
reader object. A similar problem occurs with inner classes because they hold an implicit reference to the enclosing class.
Noncompliant Code Example (Exception before Remove)
This noncompliant code example attempts to remove the
reader through use of the
If an exception is thrown by the
readSomething() method, the
removeActionListener() statement is never executed.
Compliant Solution (
This compliant solution uses a
finally block to ensure that the
reader object's reference is removed:
Noncompliant Code Example (Member Object Leaks)
This noncompliant code example implements a stack data structure [Bloch 2008] that continues to hold references to elements after they have been popped off the stack:
The object references are retained on the stack even after the element is popped. Such obsolete references cause objects to remain live; consequently, the objects cannot be garbage-collected.
Compliant Solution (
This compliant solution assigns
null to all obsolete references:
The garbage collector can then include individual objects formerly referenced from the stack in its list of objects to free.
Although these examples appear trivial and do not represent significant problems in production code, obsolete references remain a concern when dealing with data structures such as hash tables containing many large records. It is prudent to assign
null to array-like custom data structures; doing so with individual objects references or local variables is unnecessary because the garbage collector handles these cases automatically [Commes 2007].
Noncompliant Code Example (Strong References)
A common variation of the obsolete object fallacy is the unintentional retention of objects in collections such as maps. In this noncompliant code example, a server maintains temporary metadata about all committed secure connections:
It is possible to close a socket without removing it from this map. Consequently, this map may contain dead sockets until
removeTempConnection() is invoked on them. In the absence of notification logic, it is impossible to determine when to call
removeTempConnection(). Moreover, nullifying original objects or referents (
Socket connections) is unwieldy.
Compliant Solution (Weak References)
This compliant solution uses weak references to allow timely garbage collection:
Strong references prevent the garbage collector from reclaiming objects that are stored inside container objects, such as in a
Map. According to the Java API [API 2014], weak reference objects "do not prevent their referents from being made finalizable, finalized, and then reclaimed."
Keys held in
WeakHashMap objects are referenced through weak references. Objects become eligible for garbage collection when they lack strong references. Consequently, use of weak references allows the code to refer to the referent without delaying garbage collection of the referent. This approach is suitable only when the lifetime of the object is required to be the same as the lifetime of the key.
Simply facilitating garbage collection of unneeded objects through use of weak references is insufficient. Programs must also prune the data structure so that additional live entries can be accommodated. One pruning technique is to call the
get() method of
WeakHashMap and remove any entry that corresponds to a
null return value (polling). Use of reference queues is a more efficient method [Goetz 2005b].
Compliant Solution (Reference Queue)
Reference queues provide notifications when a referent is garbage-collected. When the referent is garbage-collected, the
HashMap continues to strongly reference both the
WeakReference object and the corresponding map value (for each entry in the
When the garbage collector clears the reference to an object, it adds the corresponding
WeakReference object to the reference queue. The
WeakReference object remains in the reference queue until some operation is performed on the queue (such as a
remove()). After such an operation, the
WeakReference object in the hash map is also garbage-collected. Alternatively, this two-step procedure can be carried out manually by using the following code:
Note that the two-argument constructor of
WeakReference takes a
Queue argument and must be used to perform direct queue processing. Dead entries should be pruned prior to insertion.
Compliant Solution (Soft References)
Use of soft references is also permitted. Soft references guarantee that the referent will be reclaimed before an
OutOfMemoryError occurs and also that the referent will remain live until memory begins to run out.
Weak references are garbage-collected more aggressively than soft references. Consequently, weak references should be preferred in applications in which efficient memory usage is critical, and soft references should be preferred in applications that rely heavily on caching.
Memory leaks in Java applications may be exploited in a DoS attack.
Memory Leak [XYL]
CWE-401, Improper Release of Memory before Removing Last Reference ("Memory Leak")
Item 6, "Eliminate Obsolete Object References"
"Memory Leak Avoidance"
"Memory Leaks with Global Maps"