Calling System.gc( ) explicitly?

2019-01-07 22:47发布

问题:

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

回答1:

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.



回答2:

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.



回答3:

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?



回答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.



回答5:

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.



回答6:

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.



回答7:

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.



回答8:

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?