Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.
Comment: Migrated to Confluence 4.0

...

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.

...

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

...

.

...

Noncompliant

...

Code

...

Example

...

(Off-by-One

...

Programming

...

Error)

...

The

...

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.

{:=
Code Block
bgColor
#FFCCCC
}
public class Leak {
  static Vector vector = new Vector();

  public void useVector(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.useVector(1);
      i++;
    }
  }
}
{code} 

h2. Compliant Solution ({{>=}})

This compliant solution corrects the mistake by changing the loop condition to {{n >= 0}}. 

{code:bgColor=#ccccff}

Compliant Solution (>=)

This compliant solution corrects the mistake by changing the loop condition to n >= 0.

Code Block
bgColor#ccccff
public void useVector(int count) { 	
  for (int n = 0; n < count; n++) {
    vector.add(Integer.toString(n));
  }
  // ...
  for (int n = count - 1; n >= 0; n--) {
    vector.removeElementAt(n);
  }
}	
{code}

h2. Compliant Solution ({{

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) { 	
  for (int n = 0; n < count; n++) {
    vector.add(Integer.toString(n));
  }
  // ...
  vector.clear(); // Clear the vector
}
{code}


h2. Noncompliant Code Example 

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.

Code Block
bgColor#FFCCCC
  

{code:bgColor=#FFCCCC}
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");
    // ...
  }
}
{code}

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 storage.

Code Block
bgColor#ccccff
 the {{HashMap}} persists for the entire lifetime of the {{Storer}} instance. 


h2. 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.

{code:bgColor=#ccccff}
public class Storer {
  private void doSomething() {
    HashMap<Integer,String> hm = new HashMap<Integer,String>();
    hm.put(1,"java");
    // ...
  }
}
{code}

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.

Code Block
bgColor#FFCCCC
 

{code: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) { 
      // Handle exception 
    }		 
  }
}

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


h2. Noncompliant Code Example 

Noncompliant Code Example (Exception

...

before

...

Remove)

This noncompliant code example attempts to remove the reader through use of the removeActionListener() method.

Code Block
bgColor#FFCCCC

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 
}

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 reader object's reference is removed.

Code Block
bgColor#ccccff

Reader reader = new Reader();
button.

{mc} Bloch 08 says: The best way to ensure that callbacks are garbage collected promptly is to store only weak references to them, for instance, by storing them only as keys in a WeakHashMap. {mc}

This noncompliant code example attempts to remove the {{reader}} through use of the {{removeActionListener()}} method. 

{code:bgColor=#FFCCCC}
Reader reader = new Reader();
button.addActionListener(reader);
try {
  reader.readSomething();
} catch // Can skip next line of code
  // Dereferenced, but control flow can change(IOException e) { 
  // Handle exception 
} finally {
  button.removeActionListener(reader);  
} catch (IOException e) { 
  // Forward to handler Always executed
}
{code}

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

h2. Compliant Solution ({{finally}} Block)

This compliant solution uses a {{finally}} block to ensure that the {{reader}} object's reference is removed. 

{code:bgColor=#ccccff}
Reader reader 

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.

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() {
    if (elements.length == size) {
      Object[] oldElements = elements;
      elements = new Object[2 * elements.length + 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 == 0) {
    = new Reader();
button.addActionListener(reader);
try {
  reader.readSomething();
} catch (IOException e) { 
  // Handle exception 
} finally {
  button.removeActionListener(reader);  // Always executed
}
{code}


h2. Noncompliant Code Example (Member Object Leaks)

This noncompliant code example implements a stack data structure \[[Bloch 2008|AA. References#Bloch 08]\] that continues to hold references to elements after they have been popped off the stack.  

{code: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();
 // Ensures object consistency
  }
  Object result 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) {elements[size] = null; // Eliminate obsolete reference
  return result;
} 

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 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.

Code Block
bgColor#FFCCCC

class HashMetaData {
  private Map<SSLSocket, InetAddress> m = Collections.synchronizedMap(
      Object[] oldElements = elements;
      elements = new Object[2 * elements.length + 1];new HashMap<SSLSocket, InetAddress>());

  public void storeTempConnection(SSLSocket sock, InetAddress ip) {
      Systemm.arraycopyput(oldElementssock, 0, elements, 0, sizeip);
  
  }

  }
}
{code} 

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. 

h2. Compliant Solution ({{null}})

This compliant solution assigns {{null}} to all obsolete references. 

{code: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;
} 
{code}

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 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|AA. References#Commes 07]\].


h2. 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. 

{code:bgColor=#FFCCCC}
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);  
  }	
}
{code}

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. 


h2. Compliant Solution (Weak References)

This compliant solution uses _weak references_ to allow timely garbage collection. 

{code:bgColor=#ccccff}
// ...
private Map<SSLSocket, InetAddress> m = Collections.synchronizedMap(
  new WeakHashMap<SSLSocket, InetAddress>()
);
{code}

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 2006|AA. References#API 06]\], 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|AA. References#Goetz 05b]\].


h2. 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 {{HashMap}}). 

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 {{put()}} or {{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:

{code:bgColor=#ccccff}
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);

    // poll 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);  
  }
}
{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.

h2. 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.

{code:bgColor=#ccccff}
class 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 = new SoftReference<SSLSocket>(sock, queue);
    while ((sr = (SoftReference) queue.poll()) != null) {
      // Removes the WeakReference object and the value (not the referent)
      m.remove(sr); 
    }  
    m.put(sr, ip);
  }

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

Weak references are garbage-collected more aggressively than soft references. Consequently, weak references should be preferred in applications where efficient memory usage is critical, and soft references should be preferred in applications that rely heavily on caching.


h2. 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 | {color:green}{*}P1{*}{color} | {color:green}{*}L3{*}{color} |

h2. Related Guidelines

| [ISO/IEC TR 24772:2010|http://www.aitcnet.org/isai/] | Memory Leak \[XYL\] |
| [MITRE CWE|http://cwe.mitre.org/] | [CWE-401|http://cwe.mitre.org/data/definitions/401.html]. Improper release of memory before removing last reference ("memory leak") |

h2. Bibliography

| \[[API 2006|AA. References#API 06]\] | Class {{Vector}}, Class {{WeakReference}} |
| \[[Bloch 2008|AA. References#Bloch 08]\] | Item 6. Eliminate obsolete object references |
| \[[Commes 2007|AA. References#Commes 07]\] | Memory Leak Avoidance |
| \[[Goetz 2005a|AA. References#Goetz 05]\] | Lapsed Listeners |
| \[[Goetz 2005b|AA. References#Goetz 05b]\] | Memory Leaks with Global Maps; Reference Queues |
| \[[Gupta 2005|AA. References#Gupts 05]\] | |


----
[!The CERT Oracle Secure Coding Standard for Java^button_arrow_left.png!|MSC03-J. Never hard code sensitive information]&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;[!The CERT Oracle Secure Coding Standard for Java^button_arrow_up.png!|49. Miscellaneous (MSC)]&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;[!The CERT Oracle Secure Coding Standard for Java^button_arrow_right.png!|MSC05-J. Do not exhaust heap space]

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 2006], 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 HashMap).

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 put() or 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:

Code Block
bgColor#ccccff

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);

    // poll 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);  
  }
}

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.

Code Block
bgColor#ccccff

class 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 = new SoftReference<SSLSocket>(sock, queue);
    while ((sr = (SoftReference) queue.poll()) != null) {
      // Removes the WeakReference object and the value (not the referent)
      m.remove(sr); 
    }  
    m.put(sr, 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 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

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 2006]

Class Vector, Class WeakReference

[Bloch 2008]

Item 6. Eliminate obsolete object references

[Commes 2007]

Memory Leak Avoidance

[Goetz 2005a]

Lapsed Listeners

[Goetz 2005b]

Memory Leaks with Global Maps; Reference Queues

[Gupta 2005]

 

...

Image Added      49. Miscellaneous (MSC)      Image Added