17

It is said that we cannot force the garbage collection process in java.
It's after all, a daemon thread.

But still sometimes, why we call the System.gc( ); function explicitly ?
Is it worth calling it ? Any Pro's and Con's ?
If not useful in many situations, why this method is not deprecated from Java ?

PS : Explanation with an example will be useful

Saurabh Gokhale
  • 53,625
  • 36
  • 139
  • 164

8 Answers8

10

The best way, in my opinion, to think of the System.gc() method is as a "hint" to the VM that garbage collection should run. That said, much like a large percentage of "optimizations" people think they are performing, it's usually best to just let the system take care of things on its own. Systems are evolving etc, etc, etc. There are still some instances where the developer may actually know better and the use case for it is probably very similar to why some code is still written in assembly (most of the time, the compiler is better, but in a few instances -- or with a few developers -- humans can actually write more efficient code).

One example I've seen used in the past to justify its existence is in the event that a large number of objects were allocated and you as the developer know the instant they are no longer going to be used. In that case, you may have more information about the memory utilization than the GC does (or at least, before it realizes it) and, since the amount of memory reclaimed will be significant, it makes sense to suggest that it runs.

ewernli
  • 38,045
  • 5
  • 92
  • 123
Chris Thompson
  • 35,167
  • 12
  • 80
  • 109
8

You answered half of your question: is it worth it? No, because you can't force it.

Runs the garbage collector. Calling this method suggests that the Java virtual machine expend effort toward recycling unused objects in order to make the memory they currently occupy available for quick reuse.

This is almost EULA-English for "you can try but we both know the outcome". :)

Furthermore, application servers can (and often will) disable it using the -XX:-DisableExplicitGC command line option.

So what's the point then? Well, there could be one: some applications like to display the amount of free memory available on the heap, and before you refresh your display, it could be moderately useful to call System.gc(); before it.

biziclop
  • 48,926
  • 12
  • 77
  • 104
  • System.gc() is quite an expensive call though. "When control returns from the method call, the Java Virtual Machine has made a best effort to reclaim space from all discarded objects". – RecursiveExceptionException Jun 17 '16 at 18:35
  • 1
    This is like saying that healthy lifestyle isn't worth it as it isn't guaranteed to work. If you control the environment, you can make sure that it works. There are much more misuses than proper uses of `System.gc()` out there, but this doesn't make it useless. – maaartinus Dec 22 '17 at 05:14
7

Q: why we call the System.gc( ); function explicitly ?

A: Because somebody wrote bad code.

I think most people would agree that you shouldn't call System.gc() explicitly.

Let the system manage memory as it's supposed to. Any code relying on that for performance is most likely broken. Also, keep in mind that the JVM can entirely ignore your request.

If you want more information, I'd suggest reading the answers to:

java - why is it a bad practice to call System.gc?

Community
  • 1
  • 1
Justin Niessner
  • 242,243
  • 40
  • 408
  • 536
4

There are some cases when calling System.gc() is useful:

  • You're going to run some benchmark, so you need to start in a well-defined state.
  • You're expecting some heavy load and want to get prepared as good as possible.
  • You have multiple servers and want to avoid pauses by scheduling GC on them periodically like here.

There may be more use cases, however, it's nothing you could expect to need soon. Most of the time it's better to let it do its work its way.

maaartinus
  • 44,714
  • 32
  • 161
  • 320
  • 1
    I disagree with the second one - if you start running a "heavy" load then generally the JVM is good enough to realise this and will GC as appropriate. – Michael Berry Jan 24 '11 at 17:39
  • I meant, you do it *before* you start the heavy load, which is something the JVM can't know in advance. It's just like making all duties in advance when you expect a hard day to come. – maaartinus Jan 24 '11 at 19:25
  • @berry120 you can empty the young gen (on Sun's hotspot) if you sure you'd swarm it. Generally, calling GC in a multi-threaded environment is not recommended in any way except fixing issues that java developers gratefully left. (speaking again about the darned memory mapped buffers) – bestsss Jan 26 '11 at 23:08
  • For "best results", I found that calling System.gc() many times in a row might be needed (maybe 10 times). Also, I found that pausing (Thread.sleep, 1 second or so) can help get more consistent benchmark results for CPU intensive stuff, as this allows the CPU to cool off. Also, the pause might help to ensure System.gc() is actually freeing some space. – Thomas Mueller Dec 22 '17 at 14:45
2

Not intending to answer the question, calling the garbage collector explicitly is a bad, bad practice, however some code in java does rely on finalization... and attempts to enforce it. Calling it is useful in some profiling scenarios as well. No standard JVM ignores System.gc(). Sure, it can be disabled. However, b/c aside memory the garbage collector manages java references to external resources, it might be needed.

here is some code from java.nio.Bits

static void reserveMemory(long size) {

    synchronized (Bits.class) {
        if (!memoryLimitSet && VM.isBooted()) {
            maxMemory = VM.maxDirectMemory();
            memoryLimitSet = true;
        }
        if (size <= maxMemory - reservedMemory) {
            reservedMemory += size;
            return;
        }
    }

    System.gc();
    try {
        Thread.sleep(100);
    } catch (InterruptedException x) {
        // Restore interrupt status
        Thread.currentThread().interrupt();
    }
    synchronized (Bits.class) {
        if (reservedMemory + size > maxMemory)
            throw new OutOfMemoryError("Direct buffer memory");
        reservedMemory += size;
    }

Sleep is necessary for the finalized to run actually (or attempted run), Cleaners usually have fast-track on the high-priority finalizer thread.

bestsss
  • 11,796
  • 3
  • 53
  • 63
0

It is an anti-pattern to use System.gc() explicitly, though we use it to suggest JVM for sweeping garbage but it is up to the JVM whether it will or not, it further imposes some criteria that it look into when System.gc() occurs. If criteria follows then it acts; otherwise not.

Carl Manaster
  • 39,912
  • 17
  • 102
  • 155
RTA
  • 1,251
  • 2
  • 14
  • 33
0

What version of Java are we talking about here? In 6, I'd never call it explicitly. As a general rule of thumb the garbage collector is good enough to know when best to clean up resources and it's got enough configurable VM options. I've certainly never felt the need to call it in code, and I'd say unless you were doing something really bizarre (or showing resource usage) it's best not to. If you're feeling the need to call it then I'd say you've done something bad or wrong elsewhere.

If we're talking about working with Java 1.4 or before though, sometimes I find it does need a helping hand. No examples to hand (sorry) but I do remember needing to throw it a hint to avoid horrible lag when it decided to eventually kick in. With the same code on 6, the problem went away and calling it made little or no difference.

Of course, when you're calling System.gc() all you're actually doing is suggesting to the VM that now might be a good time to run the garbage collector. It doesn't mean it actually will, it's merely a suggestion that a perfectly valid VM implementation might entirely ignore. In fact there's even a DisableExplicitGC option that mean these calls definitely won't take affect (and lots of code in production environments is run with this option.)

So yes, it is still used in code - but the vast majority of the time it's not good practice at all.

Michael Berry
  • 70,193
  • 21
  • 157
  • 216
-1
It is said that we cannot force the garbage collection process in java.

That is a very popular belief, which is totally wrong.

Several applications do that on a regular basis and some even have shiny buttons you can click that do really perform a GC. In other words: they don't "hint" the GC that they'd like the GC to trigger but they do really force a GC.

So that belief is both popular and wrong. What is less popular is the knowledge as to how you actually trigger such a GC, as shown by the unique (and very vague) answer to my +6 times upvoted question here:

Java: How do you really force a GC using JVMTI's ForceGargabeCollection?

Community
  • 1
  • 1
SyntaxT3rr0r
  • 27,745
  • 21
  • 87
  • 120
  • 5
    You can not "force" a generic JVM to do garbage collection because a garbage collector is not actually required by the JVM spec. – ILMTitan Jan 24 '11 at 18:39
  • 1
    "When control returns from the method call, the Java Virtual Machine **has made a best effort to reclaim space** from all discarded objects." There's no reason for a down vote, a JVM lacking GC does its best effort, too. – maaartinus Jan 24 '11 at 19:35
  • @ILMTitan: Then I guess it's a good thing a guesstimates of 99% of Java programs out there are running on VMs that allow jvmti instrumentation and hence supporting that documented call ;) – SyntaxT3rr0r Jan 24 '11 at 19:35
  • People are downvoting because they hate it when their long-life beliefs gets shattered into pieces... – SyntaxT3rr0r Jan 24 '11 at 19:36
  • 3
    @SyntaxT3rr0r, the myth is (as explained in the answer to your question) that System.gc() is just some vague hint. Although the spec allows the JVM to treat it as a hint, in the standard desktop/server JVMs it just runs it. That is how those shiny buttons are generally implemented. I didn't downvote, but I would note that your answer doesn't address the question. It is at best a comment. – Yishai Jan 24 '11 at 21:23
  • No downvote, but even this can throw JVMTI_ERROR_ACCESS_DENIED. – Highland Mark Jan 24 '11 at 21:43
  • 1
    I was not the one to actually downvote, because I was unaware of that API, and did find it interesting (though you could quibble it is not "in java"). My comment was mainly to show that the rhetoric in this answer was somewhat stronger than reality could support. – ILMTitan Jan 24 '11 at 22:23
  • wow -2 for the truth :) And you do know, guys, how direct memory (for DirectBuffers is released), through a Cleaner (in the finalizer thread) and **EXPLICIT call to System.gc()**. – bestsss Jan 25 '11 at 16:34
  • As for all comments about the bad-code, etc. It is the only sane way to unmap file mapped ByteBuffer, check it out (and see the amounts of votes!!): http://bugs.sun.com/view_bug.do?bug_id=4724038 – bestsss Jan 25 '11 at 17:07
  • @SyntaxT3rr0r upvoted. Think I'll comfortably apply System.gc() to solve my unanswerd question at http://stackoverflow.com/questions/5039349/another-forcing-java-garbage-collection-question-with-i-think-a-justifiable-us then. – RAY Feb 22 '11 at 06:44
  • "Calling the gc method ___suggests___ that the Java Virtual Machine expend effort toward recycling unused objects [...]" – RecursiveExceptionException Jun 17 '16 at 18:38