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

Compare with Current View Page History

Version 1 Next »

From a security point of view, Java's garbage collection feature provides significant benefits over traditional languages such as C and C++. The garbage collector (GC) is designed to automatically reclaim unreachable memory and thus avoid memory leaks. While it is quite adept at performing this task, a malicious attacker can launch a Denial of Service (DoS) attack by inducing abnormal object memory allocation as well as object retention.

For example, the GC will need to halt all executing threads in order to keep up with the incoming requests that command increased heap management in terms of space allocation. 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 source memory allocations in a way that keeps resource consumption (such as CPU, battery power, memory) high without triggering an OutOfMemoryError.

Writing garbage collection friendly code helps restrict many attack avenues. The best practices have been collated and enumerated below.

Use Short-lived Immutable Objects

Since JDK 1.2, the new generational garbage collector has eased out memory allocation related costs to minimal levels, even lesser than C/C++. Deallocation has also become cheaper wherein the cost of garbage collection has become commensurate with the number of live objects in the younger generation and not the total number of objects allocated since the last run. Very few younger generation objects continue to live through to the next garbage collection cycle; the rest become ready to be collected in the impending collection cycle.

That said, with generational GCs it is advantageous to use short-lived immutable objects instead of long-lived mutable objects. Object pools are examples of the latter and should thus be avoided to increase the garbage collector's efficiency. Moreover, object pools can create synchronization problems, deallocations have to be managed explicitly leading to dangers of dangling pointers and the size of the pool also takes a dominant role in critical code. Exceptions to this recommendation can be made when the allocation takes longer in comparison, such as while performing multiple joins across databases or while using objects that represent scarce resources such as thread pools and database connections.

The code fragment below (adopted from [[Goetz 04]]) shows two containers, MutableHolder and ImmutableHolder. In MutableHolder, the instance field value can be updated to reference a new value which makes it long-term. On the other hand, when value is assigned in ImmutableHolder's constructor, it is a younger object that is referencing an older one (Object o). The latter case is a much better position to be in as far as the garbage collector is concerned.

public class MutableHolder {
  private Object value;
  public Object getValue() { return value; }
  public void setValue(Object o) { value = o; }
}

public class ImmutableHolder {
  private final Object value;
  public ImmutableHolder(Object o) { value = o; }
  public Object getValue() { return value; }
}
Avoid Large Objects

The allocation for large objects is expensive and initializing (zeroing) also takes time. Sometimes large objects of different sizes can cause fragmentation issues or non compacting collect.

Nulling References

Reference nulling to "help the garbage collector" is not necessary at all. In fact, it just adds clutter to the code and may lead to bugs. Assigning null to local variables is also not very useful as JIT can equivalently do a liveness analysis. Perhaps the worst one can do is to use a finalizer to null out references, thereby befriending a huge performance hit.

int[] buffer = new int[100];
doSomething(buffer);
buffer = null  // no need for explicitly assigning null

Array based data structures such as ArrayLists are an exception since the programmer has to explicitly set only a few of the array elements to null to indicate their demise.

Do Not Explicitly Invoke the Garbage Collector

The garbage collector can be explicitly invoked by calling the System.gc() method. Even though the documentation says that it "Runs the garbage collector", there is no guarantee on when the garbage collector would actually run since the call only suggests a run. Other reasons include,

  • Irresponsible use of this feature can severely degrade system performance as the garbage collector would not wait until ripe periods when it is safe to garbage collect without interrupting the program execution significantly.
  • The application does not have enough information available on when to call System.gc().

In the Java Hotspot VM (default since JDK 1.2), System.gc() does an explicit collection. Sometimes these calls are buried deep within libraries and are hard to trace. To ignore the call in such cases, use the flag -XX:+DisableExplicitGC. To avoid long pauses while doing a full GC, a less demanding concurrent cycle can be invoked by specifying the flag -XX:ExplicitGCInvokedConcurrent.

One exception to this rule may exist. The garbage collector can be explicitly called when the application goes through several phases like the initialization and the ready phase. The heap needs to be compacted between these phases and given an uneventful period, System.gc() may be explicitly invoked.

Risk Assessment

Misusing some garbage collection utilities can cause Denial Of Service (DoS) related issues and severe performance degradation.

Rule

Severity

Likelihood

Remediation Cost

Priority

Level

OBJ05-J

low

likely

high

P2

L3

Automated Detection

TODO

Related Vulnerabilities

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

References

[[API 06]] Class System
[[Commes 07]] Garbage Collection Concepts and Programming Tips
[[Goetz 04]]


OBJ04-J. Encapsulate the absence of an object by using a Null Object      06. Object Orientation (OBJ)      06. Object Orientation (OBJ)

  • No labels