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.

...

Wiki Markup
Since JDK 1.2, the generational garbageGC collector has reduced memory allocation costs to low levels, in many cases lower than in C or C++. Generational garbage collection reduces garbage collection costs by grouping objects into generations. The _younger generation_ consists of short-lived objects. The GC performs a minor collection on the younger generation when it fills up with dead objects \[java:[Oracle 2010a|AA. References#Oracle 10]\]. Improved garbage collection algorithms have reduced the cost of garbage collection  so that it is proportional to the number of live objects in the younger generation rather than to the total number of objects allocated since the last garbage collection.

Wiki Markup
Note that objects in the younger generation that persist for longer durations are _tenured_ and are moved to the _tenured generation_. 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 \[java:[Oracle 2010a|AA. References#Oracle 10]\].

With generational GCs, use of short-lived immutable objects is generally more efficient than use of long-lived mutable objects, such as object pools. Avoiding object pools improves the garbage collector's GC’s efficiency. Object pools bring additional costs and risks: they can create synchronization problems and can require explicit management of deallocations, possibly creating problems with dangling pointers. Further, determining the correct amount of memory to reserve for an object pool can be difficult, especially for mission-critical code. Use of long-lived mutable objects remains appropriate in cases where when allocation of objects is particularly expensive (for example, when performing multiple joins across databases). Similarly, object pools are an appropriate design choice when the objects represent scarce resources, such as thread pools and database connections.

The rules "FIO00-J. Defensively copy mutable inputs and mutable internal components" and "OBJ09-J. Defensively copy private mutable class members before returning their references" promote GCgarbage-collection-friendly code.

Avoid Large Objects

The allocation of large objects is expensive, and the cost to initialize their fields is proportional to their size. Additionally, frequent allocation of large objects of different sizes can cause fragmentation issues or non-compacting noncompacting collect operations.

Do Not Use Direct Buffers for Short-Lived, Infrequently Used Objects

The new I/O classes (NIO) classes in java.nio allow the creation and use of direct buffers. These buffers tremendously increase throughput for repeated I/O activities. However, their creation and reclamation is more expensive than the creation and reclamation for heap-based non-direct nondirect buffers because direct buffers are managed using OS-specific native code. This added management cost makes direct buffers a poor choice for single-use or infrequently used cases. Direct buffers are also not subject to Java's garbage collectorJava’s GC, which can cause memory leaks. Frequent allocation of large direct buffers can cause an OutOfMemoryError.

...

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

...

This compliant solution uses an indirect buffer to allocate the short-lived, infrequently used object. The heavily used buffer appropriately continues to use a non-heapnonheap, 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

Do Not Attempt to

...

Help the Garbage Collector

...

by Setting Local Reference Variables to Null

Setting local reference variables to null to "help “help the garbage collector" collector” is unnecessary. It adds clutter to the code and can introduce subtle bugs. Java Justjust-Inin-Time time compilers (JITs) can perform an equivalent liveness analysis; in fact, most implementations do this. A related bad practice is use of a finalizer to null out references. See rule "MET18-J. Avoid using finalizers" for additional details.

Noncompliant Code Example

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

...

Wiki Markup
Program logic occasionally requires tight control over the lifetime of an object referenced from a local variable. In the unusual cases where such control is necessary, use a lexical block to limit the scope of the variable because the garbage collectorGC can collect the object immediately when it goes out of scope \[java:[Bloch 2008|AA. References#Bloch 08]\].

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" “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();

The garbage collector GC cannot collect the dead DataElement object until it becomes unreferenced. Note that all methods that operate on objects of class DataElement must check whether the instance in hand is dead.

Compliant Solution (Set Reference to null)

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

...

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

...

Wiki Markup
When using this pattern, the Null {{NULL}} object must be a singleton and must be final. It may be either public or private, depending on the overall design of the {{DataElement}} class. The state of the Null{{NULL}} object should be immutable after creation; thisimmutability can be enforced either by useusing of {{final}} fields or by explicit code in the methods of the {{DataElement}} class. See \[java:[Grand 2002|AA. References#Grand 02]\] "Chapter 8, Behavioral“Behavioral patternsPatterns, the Null Object",” for additional information on this design pattern.

Do Not Explicitly Invoke the Garbage Collector

The garbage collector GC can be explicitly invoked by calling the System.gc() method. Even though the documentation says that it "runs “runs the garbage collector," ” there is no guarantee as to when the garbage collector GC will actually run. In fact, the call only suggests that the GC will subsequently execute.

  • Irresponsible use of this feature can severely degrade system performance by triggering garbage collection at inopportune moments rather than waiting until ripe periods when it is safe to garbage collect without significant interruption of the program's program’s execution.

In the Java Hotspot VM (default since JDK 1.2), System.gc() forces an explicit garbage collection. Such calls can be buried deep within libraries, so they may be difficult to trace. To ignore the call in such cases, use the flag -XX:+DisableExplicitGC. To avoid long pauses while performing a full GC, a less demanding concurrent cycle may be invoked by specifying the flag -XX:ExplicitGCInvokedConcurrent.

...

Misusing garbage collection utilities can cause severe performance degradation resulting in a denial of service ( DoS )attach.

Rule

Severity

Likelihood

Remediation Cost

Priority

Level

OBJ15-J

low

likely

high

P3

L3

...

Related Guidelines

MITRE CWE

CWE ID 405, "Asymmetric “Asymmetric Resource Consumption (Amplification)" ”

Bibliography

<ac:structured-macro ac:name="unmigrated-wiki-markup" ac:schema-version="1" ac:macro-id="bd72dd6a44046208-00eb7808-4bb54f42-b288a0d0-097b1c56f02ae415e7d81311"><ac:plain-text-body><![CDATA[

[java:[API 2006

AA. References#API 06]]

Class System

]]></ac:plain-text-body></ac:structured-macro>

<ac:structured-macro ac:name="unmigrated-wiki-markup" ac:schema-version="1" ac:macro-id="bc39b9af68eb6399-3464f11f-49fc40aa-8956b6f8-9411b3406eec8057b25750da"><ac:plain-text-body><![CDATA[

[java:[Bloch 2008

AA. References#Bloch 08]]

Item 6: "Eliminate “Eliminate obsolete object references" references”

]]></ac:plain-text-body></ac:structured-macro>

<ac:structured-macro ac:name="unmigrated-wiki-markup" ac:schema-version="1" ac:macro-id="2180b5cd93b30959-8eb0bee0-420b4db9-9eebb5d5-11bc2a4fcc510b8d2bf75587"><ac:plain-text-body><![CDATA[

[java:[Coomes 2007

AA. References#Coomes 07]]

Garbage Collection Concepts and Programming Tips

]]></ac:plain-text-body></ac:structured-macro>

<ac:structured-macro ac:name="unmigrated-wiki-markup" ac:schema-version="1" ac:macro-id="e7a13e2e43e5dec0-d6c624df-4f844292-86e59be8-33168b09d988a0d48ec29ccd"><ac:plain-text-body><![CDATA[

[java:[Goetz 2004

AA. References#Goetz 04]]

Java theory and practice: Garbage collection and performance

]]></ac:plain-text-body></ac:structured-macro>

<ac:structured-macro ac:name="unmigrated-wiki-markup" ac:schema-version="1" ac:macro-id="0757ea291502a403-0ed40d64-40174b5e-be7f9c5a-00919566566bc71663eabea0"><ac:plain-text-body><![CDATA[

[java:[Lo 2005

AA. References#Lo 05]]

Security Issues in Garbage Collection

]]></ac:plain-text-body></ac:structured-macro>

...