...
Excessive memory leaks can lead to memory exhaustion and denial of service (DoS) and must be avoided . For more information, (see rule MSC05-J. Do not exhaust heap space for more information).
Noncompliant Code Example (Off-by-One Programming Error)
...
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.
...
Prefer the use of standard language semantics where possible. This compliant solution uses the vector.clear()
method, which removes all elements.:
Code Block | ||
---|---|---|
| ||
public void useVector(int count) { try { for (int n = 0; n < count; n++) { vector.add(Integer.toString(n)); } // ... } finally { vector.clear(); // Clear the vector } } |
...
This noncompliant code example declares and allocates a HashMap
instance field that is used only in the doSomething()
method.:
Code Block | ||
---|---|---|
| ||
public class Storer { private HashMap<Integer,String> hm = new HashMap<Integer, String>(); private void doSomething() { // hm is used only here and never referenced again hm.put(1, "java"); // ... } } |
...
This noncompliant code example attempts to remove the reader
through use of the removeActionListener()
method.:
Code Block | ||
---|---|---|
| ||
Reader reader = new Reader(); button.addActionListener(reader); try { reader.readSomething(); // Can skip next line of code // Dereferenced, but control flow can change button.removeActionListener(reader); } catch (IOException e) { // Forward to handler } |
...
This compliant solution uses a finally
block to ensure that the reader
object's reference is removed.:
Code Block | ||
---|---|---|
| ||
Reader reader = new Reader(); button.addActionListener(reader); try { reader.readSomething(); } catch (IOException e) { // Handle exception } finally { button.removeActionListener(reader); // Always executed } |
...
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.:
Code Block | ||
---|---|---|
| ||
public class Stack { private Object[] elements; private int size = 0; public Stack(int initialCapacity) { this.elements = new Object[initialCapacity]; } public void push(Object e) { ensureCapacity(); elements[size++] = e; } public Object pop() { // This method causes memory leaks if (size == 0) { throw new EmptyStackException(); } return elements[--size]; } /* * Ensure space for at least one more element, roughly * doubling the capacity each time the array needs to grow. */ private void ensureCapacity() { if (elements.length == size) { Object[] oldElements = elements; elements = new Object[2 * elements.length + 1]; System.arraycopy(oldElements, 0, elements, 0, size); } } } |
...
This compliant solution assigns null
to all obsolete references.:
Code Block | ||
---|---|---|
| ||
public Object pop() { if (size == 0) { throw new EmptyStackException(); // Ensures object consistency } Object result = elements[--size]; elements[size] = null; // Eliminate obsolete reference return result; } |
...
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].
...
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.:
Code Block | ||
---|---|---|
| ||
class HashMetaData { private Map<SSLSocket, InetAddress> m = Collections.synchronizedMap( new HashMap<SSLSocket, InetAddress>()); public void storeTempConnection(SSLSocket sock, InetAddress ip) { m.put(sock, ip); } public void removeTempConnection(SSLSocket sock) { m.remove(sock); } } |
...
This compliant solution uses weak references to allow timely garbage collection.:
Code Block | ||
---|---|---|
| ||
// ... private Map<SSLSocket, InetAddress> m = Collections.synchronizedMap( new WeakHashMap<SSLSocket, InetAddress>() ); |
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 20062014], weak reference objects "do not prevent their referents from being made finalizable, finalized, and then reclaimed."
...
Code Block | ||
---|---|---|
| ||
class HashMetaData { private Map<WeakReference<SSLSocket>, InetAddress> m = Collections.synchronizedMap( new HashMap<WeakReference<SSLSocket>, InetAddress>()); ReferenceQueue queue = new ReferenceQueue(); public void storeTempConnection(SSLSocket sock, InetAddress ip) { WeakReference<SSLSocket> wr = new WeakReference<SSLSocket>(sock, queue); // pollPoll for dead entries before adding more while ((wr = (WeakReference) queue.poll()) != null) { // Removes the WeakReference object and the value (not the referent) m.remove(wr); } m.put(wr, ip); } public void removeTempConnection(SSLSocket sock) { m.remove(sock); } } |
...
Weak references are garbage-collected more aggressively than soft references. Consequently, weak references should be preferred in applications where 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 attack.
Rule | Severity | Likelihood | Remediation Cost | Priority | Level |
---|---|---|---|---|---|
MSC04-J | lowLow | unlikelyUnlikely | highHigh | P1 | L3 |
Related Guidelines
Memory Leak [XYL] | |
CWE-401. , Improper release Release of memory before removing last reference Memory before Removing Last Reference ("memory leakMemory Leak") |
Bibliography
Item 6. Eliminate obsolete object references, "Eliminate Obsolete Object References" | |
Memory Leak Avoidance | |
Lapsed Listeners | |
Memory Leaks with Global Maps; Reference Queues | |
|
...