Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.

Even though Java supports memory management through garbage collection, there are innumerable possibilities of introducing memory leaks due to programming errors. Furthermore, the Programming errors can prevent garbage collection of objects that are no longer relevant to program operation. The garbage collector collects only the unreachable objects and not those that are still reachable. The ; consequently, the presence of reachable objects that remain unused clearly call for indicates memory mismanagement.

Depending on program scale and available memory, one of the most undesired errors, the OutOfMemoryError may manifest itself wherein the heap space runs out causing program failure.

Noncompliant Code Example

Consumption of all available heap space can cause an OutOfMemoryError, which usually results in program termination.

Excessive memory leaks can lead to memory exhaustion and denial of service (DoS) and must be avoided (see MSC05-J. Do not exhaust heap space for more information).

Noncompliant Code Example (Off-by-One Programming Error)

The vector object in the noncompliant code example leaks memory. The 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 is mistakenly written as n > 0 instead of n>n >= 0. As a result, in every iteration Consequently, the method leaks fails to remove one vector elementelement per invocation and quickly exhausts the available heap space.

Code Block
bgColor#FFCCCC

public class Leak {
  static Vector vector = new Vector();

  public void leakingVectoruseVector(int count) { 	
    for (int n = 0; n n<count< count; n++) {
      vector.add(Integer.toString(n));
    }
    // ...
    for (int n = count - 1; n > n>00; n--) { //free 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.leakingVectoruseVector(1);
      i++;
    }
  }
}

Compliant Solution (

...

>=)

The This compliant solution corrects the mistake by changing the loop condition to n>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.

Code Block
bgColor#ccccff

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

Compliant Solution (2)

To be safe, it is usually better to use the standard language semantics as shown below.

Code Block
bgColor#ccccff

while (!vector.isEmpty()){
  vector.removeElementAt(vector.size() - 1);	        	    
}

Compliant Solution (3)

Wiki Markup
An alternative (and preferable) way to clear the vector is to use {{vector.clear()}}. Likewise,  if a range of elements has to be released from a vector, {{vector.subList(fromIndex, toIndex).clear()}} can be used. In this case the {{fromIndex}} and the {{toIndex}} would both be {{0}} as the {{count}} variable is {{1}} on each iteration. \[[API 06|AA. Java References#API 06]\]

Code Block
bgColor#ccccff

vector.clear();

Noncompliant Code Example

  for (; n < count; n++) {
      vector.add(Integer.toString(n));
    }
    // ...
  } finally {
    for (n = n - 1; n >= 0; n--) {
      vector.removeElementAt(n);
    }
  }
}	

Compliant Solution (clear())

Prefer the use of standard language semantics where possible. This compliant solution uses the vector.clear() method, which removes all elements:

Code Block
bgColor#ccccff
public void useVector(int count) { 	
  try {
    for (int n = 0; n < count; n++) {
      vector.add(Integer.toString(n));
    }
    // ...
  } finally {
    vector.clear(); // Clear the vector
  }
}

Noncompliant Code Example (Nonlocal Instance Field)

This noncompliant code example declares and allocates a HashMap instance field that is used only in the doSomething() method:This noncompliant example creates a HashMap instance field within the class body but uses it only in the doSomething method. Sometimes, it is not obvious that it will continue to persist as long as class BadScope's instance is alive.

Code Block
bgColor#FFCCCC

public class BadScopeStorer {
  private HashMap<Integer,String> hm = new HashMap<Integer, String>();
  
  private void doSomething() {
    hm.// hm is used only here and never referenced again
    hm.put(1, "java");
    // hm is used only here...
  }
}

Compliant Solution

Programmers may be surprised that the HashMap persists for the entire lifetime of the Storer instance.

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 storageLocalizing or confining the instance field to a narrower scope gives the garbage collector a better chance of succeeding at collecting the object in a timely manner. Short-lived objects are always collected quickly by generational garbage collectors.

Code Block
bgColor#ccccff

public class GoodScopeStorer {
  private void doSomething() {
    HashMap<Integer,String> hm = new HashMap<Integer,String>();
    hm.put(1,"java");
    // ...
  }
}

Noncompliant Code Example

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. This noncompliant code snippet is an example of unintentional object retention and is commonly called the Lapsed Listener. The button continues to hold a reference of the reader object even after completion of the readSomething() method. As a result, the garbage collector will not 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 as because they hold an implicit reference to the outer enclosing class.

Code Block
bgColor#FFCCCC

public class LapseEvent extends JApplet   {
  JButton button;
  public void init() {
    button = new JButton("Click Me");
    getContentPane().add(button, BorderLayout.CENTER);
    Reader reader = new Reader();
    button.addActionListener(reader);
    try {
      reader.readSomething();
    } catch (IOException e) { 
      /*/ handleHandle exception */
    }		 
  }
}

class Reader implements ActionListener {
  public void actionPerformed(ActionEvent e)  {
    Toolkit.getDefaultToolkit().beep();
  }
  public void readSomething() throws IOException {
    // readRead from file
  }
}

Noncompliant Code Example (Exception before Remove)

This noncompliant code example attempts to remove the reader through use of the removeActionListener() method:To solve this problem, a matching pair of the removeActionListener should be used, as shown below. Unfortunately, this is not the panacea because an exception in the reader.readSomething method can change the control flow in such a way that the removeActionListener statement is never executed.

Code Block
bgColor#FFCCCC

Reader reader = new Reader();
button.addActionListener(reader);
try {
  reader.readSomething();  // canCan skip next line of code
  button.removeActionListener(reader);  // dereferenced// Dereferenced, but control flow can change
  button.removeActionListener(reader);  
} catch (IOException e) { 
  //* handleForward exceptionto */handler 
}		 

Compliant Solution

If an exception is thrown by the readSomething() method, the removeActionListener() statement is never executed.

Compliant Solution (finally Block)

This compliant solution uses a finally block to ensure that the The solution is to use the finally block to ensure that the reader object's reference is unregistered. removed:

Code Block
bgColor#ccccff

Reader reader = new Reader();
button.addActionListener(reader);
try {
  reader.readSomething();
} catch (IOException e) { 
  //* handleHandle exception */
} }
finally {
  button.removeActionListener(reader);  // always getsAlways executed
}

Noncompliant Code Example

...

Wiki Markup
This example implements a {{stack}} data structure \[[Bloch 08|AA. Java References#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.  

(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:

Code Block
bgColor#FFCCCC
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() {
Code Block
bgColor#FFCCCC

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 (sizeelements.length == 0size) {
      throw new EmptyStackException()Object[] oldElements = elements;
     return elements[--size];
 = }
new Object[2 /**
 elements.length * 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+ 1];
      System.arraycopy(oldElements, 0, elements, 0, size);
    }
  }
}

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 (null)

This compliant solution assigns null to all obsolete references:

Code Block
bgColor#ccccff
public Object pop() {
  if (size ==  Object[] oldElements = elements;
      elements = new Object[2 * elements.length + 10) {
    throw new EmptyStackException(); // Ensures object consistency
  }
  Object result = elements[--size];
  elements[size] = null;  System.arraycopy(oldElements, 0, elements, 0, size);
    }
  }
}

Compliant Solution

// Eliminate obsolete reference
  return result;
} 

This compliant solution assigns null values to all obsolete references. The garbage collector can now include this object then include individual objects formerly referenced from the stack in its list of objects to free. A NullPointerException exception results on subsequent attempts to access the particular object.

Code Block
bgColor#ccccff

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

Wiki Markup
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. It is prudent to assign {{null}} to array-like custom data structures, however, doing so with individual objects or local variables gives no specific advantage. The garbage collector is sufficiently equipped to handle these cases. \[[Commes 07|AA. Java References#Commes 07]\]

Noncompliant Code Example

.

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 A common variant of the aforementioned noncompliant code is the unintentional retention of objects while using a Map or a similar Collections object. In this example, a server maintains temporary metadata about all secure connections it commits to. Although the metadata is designed to be transient by nature, it persists even after the particular socket is closed. Unless some notification logic is installed, it is impossible to determine the best time to eliminate the object reference. Likewise, nulling out original objects or referents (Socket connections) by itself, proves to be unwieldy. committed secure connections:

Code Block
bgColor#FFCCCC
class HashMetaData {
  private Map<SSLSocket, InetAddress> m = Collections.synchronizedMap(
      new HashMap<SSLSocket, InetAddress>());

  public void storeTempConnection(SSLSocket sock, InetAddress ip)
Code Block
bgColor#FFCCCC

class HashMemLeak {
  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);  
  }	
}

Compliant Solution

Wiki Markup
This compliant solution uses _weak references_ to ameliorate the issue. Strong references typically used in code, do not allow the garbage collector to reclaim the objects that are stored compositely, such as in a {{Map}}. According to \[[API 06|AA. Java References#API 06]\], weak reference objects:

...

  m.put(sock, ip);  
  }

  public void removeTempConnection(SSLSocket sock) {
    m.remove(sock);  
  }	
}

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:

Code Block
bgColor#ccccff
// ...
  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 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 recording data structure so that additional live entries can be accommodated. The implementation of WeakHashMap in Java 7 includes a reference queue to efficiently remove entries that correspond to a null pointer value [https://github.com/openjdk-mirror/jdk7u-jdk/blob/master/src/share/classes/java/util/WeakHashMap.java].

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.

Reference queues provide notifications when a referent is garbage-collected. When the referent is garbage-collected, the HashMap continues to strongly reference both the SoftReference object and the corresponding map

A referent is the object that is being referred to. As soon as any strong references to the object are found to have phased out, the garbage collector reclaims the referent. With WeakHashMap, the map's key is weakly referred to and as a result determines whether the corresponding referents are ready to be collected.

Code Block
bgColor#ccccff

// ...
private Map<SSLSocket, InetAddress> m = Collections.synchronizedMap(new WeakHashMap<SSLSocket, InetAddress>());
// ...

Wiki Markup
It is not enough to facilitate the collection of unneeded objects with weak references. It is critical to prune the data structure so that more entries can be accommodated in the newly created space. This can be achieved by calling the {{get()}} method of {{WeakHashMap}} and removing the entry that corresponds to the {{null}} return value (polling). A more efficient method is to use a reference queue. \[[Goetz 05b|AA. Java References#Goetz 05b]\]

If the referent is assigned the value null, it will eventually be garbage collected. However, the hashmap will continue to strongly reference the WeakReference object and the corresponding value (for each entry in the hashmap HashMap). As soon as the GC

When the garbage collector clears the reference (which referred to the referent)to an object, it adds the corresponding WeakReference SoftReference object to the reference queue. It remains there unless The SoftReference object remains in the reference queue until some operation is performed on the queue (such as a putpoll() or remove()). After such an operation, the WeakReference SoftReference object in the hashmap is also collected. Alternatively, this two-step procedure can be carried out manually by using the following codehash map is also garbage-collected:

Code Block
bgColor#ccccff

ReferenceQueueclass queue = new ReferenceQueue();
WeakReference wr = new WeakReference(key, queue); // two-arg constructor, key = 'sock'
hashmap.put(wr, value);
while ((wr = (WeakReference) queue.poll()) != null) {
  hashmap.remove(wr); // removes the WeakReference object and the value (not the referent)
}

Note that the two-argument constructor of WeakReference takes a Queue argument and has to be used to perform direct queue processing.

It is also permissible to use soft references since they guarantee that the referent will be reclaimed before an OutOfMemoryError results but no sooner than the time when memory begins to run out.

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

Wiki Markup
\[[API 06|AA. Java References#API 06]\] Class Vector, Class WeakReference
\[[Gupta 05|AA. Java References#Gupts 05]\]
\[[Bloch 08|AA. Java References#Bloch 08]\] Item 6: Eliminate obsolete object references
\[[Commes 07|AA. Java References#Commes 07]\] Memory Leak Avoidance
\[[Goetz 05|AA. Java References#Goetz 05]\] Lapsed listeners
\[[Goetz 05b|AA. Java References#Goetz 05b]\] "Memory leaks with global Maps" and "Reference queues" 
\[[MITRE 09|AA. Java References#MITRE 09]\] [CWE ID 401|http://cwe.mitre.org/data/definitions/401.html] "Failure to Release Memory Before Removing Last Reference (aka 'Memory Leak')"

HashMetaData {
  private Map<SoftReference<SSLSocket>, InetAddress> m = 
        Collections.synchronizedMap(
        new HashMap<SoftReference<SSLSocket>, InetAddress>());
  ReferenceQueue queue = new ReferenceQueue();

  public void storeTempConnection(SSLSocket sock, InetAddress ip) {
    SoftReference<SSLSocket> sr;
    while ((sr = (SoftReference) queue.poll()) != null) {
      // Removes the WeakReference object and the value (not the referent)
      m.remove(sr); 
    }  
    sr = new SoftReference<SSLSocket>(sock, queue);
    m.put(sr, ip);
  }

  // removeTempConnection() deleted, no longer necessary
}

Note that the two-argument constructor of SoftReference takes a Queue argument and must be used to perform direct queue processing. Dead entries should be pruned prior to insertion.

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.

Risk Assessment

Memory leaks in Java applications may be exploited in a DoS attack.

Rule

Severity

Likelihood

Remediation Cost

Priority

Level

MSC04-J

Low

Unlikely

High

P1

L3

Automated Detection

ToolVersionCheckerDescription
Parasoft Jtest
Include Page
Parasoft_V
Parasoft_V
CERT.MSC04.LEAKSEnsure resources are deallocated

Related Guidelines

ISO/IEC TR 24772:2010

Memory Leak [XYL]

MITRE CWE

CWE-401, Improper Release of Memory before Removing Last Reference ("Memory Leak")

Bibliography

[API 2014]

Class Vector
Class WeakReference

[Bloch 2008]

Item 6, "Eliminate Obsolete Object References"

[Commes 2007]

"Memory Leak Avoidance"

[Goetz 2005a]

"Lapsed Listeners"

[Gupta 2005]



...

Image Added Image Added Image AddedMSC00-J. Eliminate class initialization cycles      49. Miscellaneous (MSC)      ENV01-J. Be aware of the JVM Tool Interface