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, such as by inducing abnormal heap memory allocation or abnormally prolonged object retention. For example, some versions of the GC garbage collector 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.
...
Since JDK 1.2, the generational GC garbage 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 garbage collector performs a minor collection on the younger generation when it fills up with dead objects [Oracle 2010a]. 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 number of objects allocated since the last garbage collection.
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 [Oracle 2010a].
With generational GCsgarbage collectors, 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 GCgarbage collector'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 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.
...
Do Not Explicitly Invoke the Garbage Collector
The GC 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 as to when the GC garbage collector will actually run. In fact, the call only suggests that the GC garbage collector 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 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 GCgarbage collection, a less demanding concurrent cycle may be invoked by specifying the flag -XX:ExplicitGCInvokedConcurrent
.
Applicability
Misusing garbage-collection utilities can cause severe performance degradation resulting in a DoS attack.
When an application goes through several phases, such as an initialization and a ready phase, it could require heap compaction between phases. Given an uneventful period, System.gc()
may be invoked in such cases, provided that there is a suitable uneventful period between phases.
...
The Apache Geronimo and Tomcat vulnerability GERONIMO-4574, reported in March 2009, resulted from PolicyContext
handler data objects being set in a thread and never released. This caused , causing these data objects to remain in memory longer than necessary.
Related Guidelines
CWE ID 405, " Asymmetric Resource Consumption resource consumption (Amplificationamplification)" |
Bibliography
[API 2011] | |
Item 6: , "Eliminate obsolete object references"Obsolete Object References | |
"Garbage Collection Concepts and Programming Tips" | |
Java theory Theory and practicePractice: Garbage collection Collection and performancePerformance | |
[Lo 2005] |
...