Lesson 10 | Forcing garbage collection in Java |
Objective | How to request garbage collection in Java. |
Requesting Garbage Collection in Java
Is it possible to request garbage collection from the JVM in Java?
In the Java programming language, it is possible to request the initiation of garbage collection, although such an invocation does not guarantee immediate or complete execution of the garbage collection process. The Java standard library provides the `System.gc()` method, and the `Runtime.getRuntime().gc()` method, both of which serve as explicit requests to the Java Virtual Machine (JVM) to perform garbage collection.
The specification for the
- `System.gc()` and
- `Runtime.getRuntime().gc()`
methods stipulates that calling these methods suggests that the JVM execute garbage collection. However, the operative term here is "suggests." The invocation serves as a hint to the garbage collector that this is an opportune time to reclaim unused memory, but it is entirely at the discretion of the garbage collector and the broader JVM to heed this suggestion. Consequently, there is no certainty that garbage collection will occur immediately upon invocation, or that all eligible objects for garbage collection will be reclaimed.
The discretionary nature of garbage collection upon request arises from the JVM's overarching goal to manage memory in an optimized manner. Garbage collection is a resource-intensive operation that can impact performance metrics like throughput and latency. The JVM employs complex algorithms and heuristics to determine the most opportune moments to run garbage collection cycles, balancing various performance criteria. These factors may include the current allocation rate, heap occupancy levels, and specific performance goals (e.g., minimizing pause times or maximizing throughput).
Therefore, while it is technically feasible to request garbage collection from within a Java application, it is generally considered an anti-pattern to rely on explicit garbage collection invocations for program correctness or performance tuning. Such manual interventions often signal a design or architectural issue and can undermine the JVM's ability to make optimized decisions about memory management.
In summary, while the Java standard library provides mechanisms to request garbage collection explicitly, these are advisory in nature and not to be construed as commands that must be obeyed by the JVM. The JVM retains ultimate control over the initiation and execution of garbage collection cycles, optimizing them according to internally-defined criteria and heuristics. Consequently, manual invocation of garbage collection is generally discouraged in favor of allowing the JVM to autonomously manage memory.
Forcing Garbage Collection
While you cannot reclaim the memory of a specific object, you can request that garbage collection occur.
Normally, Java performs garbage collection only if working memory is running low.
There are two ways to run the garbage collector. The first is to use the Runtime class.
The second is to use the System class.
Runtime Instance
Every Java application has a Runtime instance associated with it that allows the application to interface with the environment in which it's
running. The current runtime can be obtained from the static method getRuntime(), as in:
Runtime r = Runtime.getRuntime();
With the Runtime instance, you can now invoke the garbage collector using gc(), as in:
r.gc();
Java System Class
You can use a static method in the System class to invoke the garbage collector.
This method performs the above two lines of code and can be invoked by writing:
System.gc();
Running finalize
You can also request that all objects the garbage collector has found have their finalize methods run and their memory reclaimed.
When control returns from the method call, the Java Virtual Machine has made a best effort to complete all outstanding finalizations.
You can use the System class or a Runtime instance to invoke runFinalization() to make this occur.
Example of freeing memory
Here is an example of a program that squeezes every last ounce of memory free.
For example, in a time-critical application that might be effected by garbage collection overhead,
you may want to make sure you are starting with as much memory as possible before you start to allocate objects.
We have also used another Runtime method, called freeMemory(), that returns the memory available for our use.
public static void fullGC() {
Runtime rt = Runtime.getRuntime();
long isFree = rt.freeMemory();
long wasFree;
do {
wasFree = isFree;
rt.gc();
isFree = rt.freeMemory();
} while (isFree > wasFree);
rt.runFinalization();
}
When the amount of memory doesn't increase after invoking the garbage collector, we drop out of the loop and invoke runFinalization().
- It's not usually necessary to invoke runFinalization()
- or gc() for that matter--yourself.
We are going for every last bit of memory, so we invoke runFinalization() in case the garbage collector hasn't done so yet.