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 as a result 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 heap memory allocation as well as prolonged object retention.
For example, the GC will need needs to halt all executing threads 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
.
...
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 as a result 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 plays 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.
...
Wiki Markup |
---|
The code fragment demonstrated below (based on \[[Goetz 04|AA. Java References#Goetz 04]\]) shows a container, {{MutableHolder}}. In {{MutableHolder}}, the instance field {{value}} can be updated to reference a new value which makes itits existence long-term. |
Code Block | ||
---|---|---|
| ||
public class MutableHolder { private Hashtable<Integer, String> value; // not final public Object getValue() { return value; } public void setValue(Hashtable<Integer, String> ht) { value = (Hashtable<Integer, String>)ht; } } |
This example also violates OBJ37-J. Do not return references to private data.
Compliant Solution
The highlighted container is This compliant solution highlights a custom container called ImmutableHolder
. When value
is assigned in ImmutableHolder
's constructor, it is a younger object that is referencing an older one (Hashtable<Integer, String> ht
). This is a much better position to be in as far as the garbage collector is concerned. Note that a shallow copy was is used in this case to preserve references to the older value.
...
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
Noncompliant Code Example
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 introduce more bugs. Assigning null
to local variables is also not very useful as the Java Just-In-Time compiler (JIT) can equivalently do a liveness analysis. Perhaps the worst one can do A related bad practice is to use a finalizer to null
out references, thereby befriending a huge performance hit.
Code Block | ||
---|---|---|
| ||
int[] buffer = new int[100]; doSomething(buffer); buffer = null // no need for explicitly assigning null |
Compliant Solution
Wiki Markup |
---|
The code snippet shown below improves on the discouraged practice by narrowing down the scope of the variable {{buffer}} so that the garbage collector collects the object as soon as it goes out of scope. \[[Bloch 08|AA. Java References#Bloch 08]\] |
...
Array based data structures such as ArrayLists
are an exception since as the programmer has to explicitly set only a few of the array elements to null
to indicate their demise.
...
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 will actually run since because the call only suggests a runthat it will subsequently execute. 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 garbage 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 . Given an uneventful period, System.gc()
may be explicitly invoked in this case.
Risk Assessment
Misusing some garbage collection utilities can cause Denial Of Service (DoS) related issues and severe performance degradation.
...