Versions Compared

Key

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

Java’s Java'€™s garbage collection feature provides significant benefits from a security perspective over non-garbage-collected languages such as C and C++. The garbage collector (GC) is designed to automatically reclaim unreachable memory and avoid memory leaks. Although it is quite adept at performing this task, a malicious attacker can nevertheless launch a denial-of-service (DoS) attack, for example, by inducing abnormal heap memory allocation or abnormally prolonged object retention. For example, some versions of the GC could need to halt all executing threads to keep up with incoming allocation requests that trigger increased heap management activity. System throughput rapidly diminishes in this scenario. Real-time systems, in particular, are vulnerable to a more subtle slow-heap-exhaustion DoS attack, perpetrated by stealing CPU cycles. An attacker can perform memory allocations in a way that increases the consumption of resources (such as CPU, battery power, and memory) without triggering an OutOfMemoryError. Writing garbage-collection-friendly code helps restrict many attack avenues.

...

This noncompliant code example uses both a short-lived local object rarelyUsedBuffer and a long-lived heavily used object heavilyUsedBuffer. Both are allocated in nonheap memory and are not garbage collected.

Code Block
bgColor#FFCCCC

ByteBuffer rarelyUsedBuffer = ByteBuffer.allocateDirect(8192);
// use rarelyUsedBuffer once

ByteBuffer heavilyUsedBuffer = ByteBuffer.allocateDirect(8192);
// use heavilyUsedBuffer many times

...

This compliant solution uses an indirect buffer to allocate the short-lived, infrequently used object. The heavily used buffer appropriately continues to use a nonheap, non-garbage-collected direct buffer.

Code Block
bgColor#ccccff

ByteBuffer rarelyUsedBuffer = ByteBuffer.allocate(8192);
// use rarelyUsedBuffer once

ByteBuffer heavilyUsedBuffer = ByteBuffer.allocateDirect(8192);
// use heavilyUsedBuffer many times

...

In this noncompliant code example, buffer is a local variable that holds a reference to a temporary array. The programmer attempts to help the GC by assigning null to the buffer array when it is no longer needed.

Code Block
bgColor#FFCCCC

int[] buffer = new int[100];
doSomething(buffer);
buffer = null  // No need to explicitly assign null

...

This compliant solution uses a lexical block to control the scope, and consequently the lifetime, of the buffer object.

Code Block
bgColor#ccccff

{ // limit the scope of buffer
  int[] buffer = new int[100];
  doSomething(buffer);
}

...

In this noncompliant code example, a long-lived ArrayList contains references to both long- and short-lived elements. The programmer marks elements that have become irrelevant by setting a “dead” flag in the object.

Code Block
bgColor#FFCCCC

class DataElement {
   private boolean dead = false;
   // other fields

   public boolean isDead() { return dead; }
   public void killMe() { dead = true; }
}

// elsewhere
ArrayList longLivedList = new ArrayList<DataElement>(...);

// processing that renders an element irrelevant
// Kill the element that is now irrelevant
longLivedList.get(someIndex).killMe();

...

In this compliant solution, rather than use a dead flag, the programmer assigns null to ArrayList elements that have become irrelevant.

Code Block
bgColor#ccccff

class DataElement {
   // dead flag removed

   // other fields
}

// elsewhere
ArrayList longLivedList = new ArrayList<DataElement>(...);

// processing that renders an element irrelevant
// set the reference to the irrelevant DataElement to null
longLivedList.set(someIndex, null);

...

This compliant solution avoids the problems associated with intentionally null references by using a singleton sentinel object. This technique is known as the Null Object pattern (also as the Sentinel pattern). When feasible, programmers should choose this design pattern over the explicit null reference values.

Code Block
bgColor#ccccff

class DataElement {
  public static final DataElement NULL = createSentinel();
   // dead flag removed

   // other fields

  private static final DataElement createSentinel() {
     // allocate a sentinel object, setting all its fields
     // to carefully chosen "do nothing" values
  }
}

// elsewhere
ArrayList longLivedList = new ArrayList<DataElement>(...);

// processing that renders an element irrelevant
// set the reference to the irrelevant DataElement to
// the NULL object
longLivedList.set(someIndex, NULL);

...

[API 2006]

Class System

[Bloch 2008]

Item 6: “Eliminate obsolete object references”

[Coomes 2007]

Garbage Collection Concepts and Programming Tips

[Goetz 2004]

Java theory and practice: Garbage collection and performance

[Lo 2005]

Security Issues in Garbage Collection

 

OBJ03-J. Do not mix generic with nongeneric raw types in new code      04. Object Orientation (OBJ)      05. Methods (MET)