Even though Java supports memory management through garbage collection, there are innumerable possibilities of introducing memory leaks due to programmer committed mistakes. Depending on program scale, one of the most undesired errors, the OutOfMemoryError
may manifest itself wherein the heap space runs out causing program failure.
Non-Compliant Code Example
This non-compliant example shows a leaking vector
object. This quickly exhausts the heap space as the programmer has mistakenly written the condition for removing the vector element as n>0
instead of n>=0
. Thus, in every iteration the method leaks one vector element.
Code Block | ||
---|---|---|
| ||
public class Leak { static Vector vector = new Vector(); public void leakingVector(int count) { for (int n=0; n<count; n++) { vector.add(Integer.toString(n)); } for (int n=count-1; n>0; n--) { //free the memory vector.removeElementAt(n); } } public static void main(String[] args) throws IOException { Leak le = new Leak(); int i = 1; while(true) { System.out.println("Iteration: " + i); le.leakingVector(1); i++; } } } |
Compliant Solution
The compliant solution corrects the mistake by changing the loop condition to n>=0
.
Code Block | ||
---|---|---|
| ||
for (int n=count-1; n>=0; n--) { vector.removeElementAt(n); } |
Non-Compliant Code Example
Wiki Markup |
---|
This example implements a {{stack}} data structure \[[Effective Java Programming Language Guide, Item 5]\]. The main issue is that it does not allow the garbage collector to de-allocate memory after the {{pop}} operation. The object references are retained even after the element is pop'ed. Such _obsolete references_ are not garbage collected automatically. This can get even more deceitful since none of the objects referenced by the offending object get garbage collected either. |
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); } } } |
Compliant Solution
This compliant solution assigns null
values to all obsolete references. A NullPointerException
exception results on subsequent attempts to access the particular object.
...
While these examples may not model production scenarios, it is not uncommon to have obsolete references when dealing with data structures such as hash tables that contain many large-sized records.
References
Java memory leaks – Catch me if you can, http://www.ibm.com/developerworks/rational/library/05/0816_GuptaPalanki/
Effective Java Programming Language Guide, Item 5, Eliminate Obsolete Object References