Gnoupi
Gnoupi

Reputation: 4734

Is there a way to launch an aggressive and complete garbage collection in Java?

For memory optimization reasons, I'm launching myself the garbage collector during profiling, to check if objects are correctly cleaned after disposing of them.

The call to garbage collector is not enough, though, and it seems that there is no guarantee of what it will clean.

Is there a way to call it, to be sure it will recover as much as it can, in profiling conditions (this would have no point in production, of course)? Or is "calling it several times" the only way to be "almost sure"?

Or did I simply misunderstand something about the Garbage Collector?

Upvotes: 6

Views: 2023

Answers (4)

Thomas Pornin
Thomas Pornin

Reputation: 74382

In all generality, a "complete garbage collection" is ill-defined. The GC detects unreachable objects, and reclaim them. It so happens that most GC implementations operate on a "cycle" basis, and once a complete cycle has run, it is possible to define an sound notion of "reclaimed space". Therefore, if you can run a full cycle and that cycle has found no reclaimable space at all, and the application is otherwise "idle" (e.g. not updating pointers), then you could say that you have temporarily reached a "fully collected" point.

Thus, you may want to do something like that:

Runtime r = Runtime.getRuntime();
r.gc();
long f = r.freeMemory();
long m = r.maxMemory();
long t = r.totalMemory();
for (;;) {
    r.gc();
    long f2 = r.freeMemory();
    long m2 = r.maxMemory();
    long t2 = r.totalMemory();
    if (f == f2 && m == m2 && t == t2) 
        break;
    f = f2; 
    m = m2; 
    t = t2; 
}   
System.out.println("Full GC achieved.");

This code relies on some assumptions, foremost of which being that Runtime.gc() is more than a "hint", and really forces some GC activity. Sun's JVM can be launched with the "-XX:-DisableExplicitGC" flag, which transforms Runtime.gc() into a no-op, effectively preventing the code above from doing anything.

There are a few caveats as well:

  • A JVM may have some background continuous activity, e.g. Timer threads. Some of that activity may be "hidden", i.e. not code written by the application developer. Also, think of the AWT / Swing event-dispatcher thread.

  • A GC run may trigger extra asynchronous activity, through finalizable objects or soft/weak/phantom references. Such activity is necessarily asynchronous and may run for unbounded amounts of time. Runtime.gc() will not wait for that to finish. It is actually a matter of definition: do you consider the GC to be "complete" if the finalizers and reference queues have not yet been processed ?

  • Nothing really forces the code above to terminate...

For a "more complete" GC, you may use the JVMTI interface (the one used by debuggers) which allows you to run the GC but also to pause the target JVM threads, which makes it much easier to define and achieve a "complete GC" state.

Upvotes: 4

Lucero
Lucero

Reputation: 60190

Basically, all you can do is this:

Runtime r = Runtime.getRuntime();
r.gc();

However, keep in mind that all references which can be reached somehow are considered to be alive, even if you think that they are not. Depending on the exact GC and settings this may or may not collect (most) memory which is not "alive".

Upvotes: 1

matt b
matt b

Reputation: 139921

No, you cannot deterministically launch a full garbage collection.

If what you are after is trying to make sure that the GC has run at all during your profiling attempt, to remove any objects which would normally be removed (so that you can find where the actual leaks are), then it's best to make sure your test runs run for long enough where you can reasonably expect that the GC would run (or would run several times).

Upvotes: 2

BalusC
BalusC

Reputation: 1108642

Forcibly allocate the max amount of memory available. When JVM is on corner of OutOfMemoryError it's forced to run the GC.

byte[] boom = new byte[512 * 1024 * 1024]; // Assuming 512MB

Obviously for pure testing reasons :)

Another option is to use a better profiler. The one which gives better reports about memory usage and GC eligible objects.

Upvotes: 4

Related Questions