You are viewing an old version of this page. View the current version.

Compare with Current View Page History

« Previous Version 8 Next »

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.

Noncompliant Code Example

This noncompliant 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. As a result, in every iteration the method leaks one vector element.

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.

    for (int n=count-1; n>=0; n--) {
      vector.removeElementAt(n);
    }	

Noncompliant Code Example

This example implements a stack data structure [[Bloch 08]] Item 6: Eliminate obsolete object references. 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.

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. The garbage collector can now include this object in its list of objects to free. A NullPointerException exception results on subsequent attempts to access the particular object.

public Object pop() {
  if (size==0)
    throw new EmptyStackException();
  Object result = elements[--size];
  elements[size] = null; // Eliminate obsolete reference
  return result;
} 

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.

Risk Assessment

Memory leaks in Java applications may be exploited, resulting in denial-of-service attacks.

Rule

Severity

Likelihood

Remediation Cost

Priority

Level

MSC01-J

low

unlikely

high

P1

L3

Automated Detection

TODO

Related Vulnerabilities

Search for vulnerabilities resulting from the violation of this rule on the CERT website.

References

[[Gupta 05]]
[[Bloch 08]] Item 6: Eliminate obsolete object references


MSC00-J. Eliminate class initialization cycles      11. Miscellaneous (MSC)      MSC02-J. Be aware of the JVM Tool Interface

  • No labels