0

This is not a duplicate as the thread mentioned as duplicate only tells you why to not use System.gc(), while I do know that, that's not my question.

Using System.gc() or Runtime.getRuntime().gc() won't always execute garbage collection, it just requests it and it can even be ignored by the JVM.

Is there a reason behind this? Is it "random"? Since I don't think random even exists in programming, I'm curious why it sometimes doesn't collect it, and sometimes does and also at different times.

javascaped
  • 31
  • 5
  • 2
    "_I don't think random even exists..._" - now that's entertaining. Cryptography relies on it existing; are you suggesting that cryptography doesn't exist? P.S. of course it's not random! – Boris the Spider Jun 09 '18 at 23:00
  • @BoristheSpider cryptography isn't random, but do you know WHEN it will execute? Are there rules? – javascaped Jun 09 '18 at 23:01
  • 1
    @BoristheSpider this depends how OP defines *randomness in programming*. Without some external resource (i.e. some entropy generator), I would regard this statement as true. – Turing85 Jun 09 '18 at 23:01
  • 1
    @Turing85 I don't think it depends on how I define random, but whether I make a difference between random and pseudo-random :P – javascaped Jun 09 '18 at 23:02
  • This is more a wild guess than a definitive answer, but I think [the javadoc of `Runtime.gc()`](https://docs.oracle.com/javase/10/docs/api/java/lang/Runtime.html#gc()) gives a hint as to why only a "best attemt" is made by this call: "*[...] The virtual machine performs this recycling process automatically as needed, in a separate thread"*. If , by chance, garbage collection is already running when you call `System.gc()`, I could imagine that the call just returns since the (already running) gc routine is in the midst of its work. – Turing85 Jun 09 '18 at 23:04
  • @Turing85 interesting. But besides that, my question should have been elaborated, I don't only wonder why it doesn't execute that always, but also why - without requesting it - it sometimes collects garbage, sometimes not, different times. So same question but then without the requesting part. – javascaped Jun 09 '18 at 23:06
  • Garbage collection is expensive and difficult to schedule optimally. For that reason, the runtime GC may decide to ignore the request if carrying it out would negatively impact the performance profile of the runtime. – jspcal Jun 09 '18 at 23:07
  • @Turing85 programs run on hardware, not in isolation. Hardware is a pretty good source of randomness... – Boris the Spider Jun 09 '18 at 23:08
  • @BoristheSpider I honestly don't think that this discussion about randomness could be won by anyone, as it's all about pseudorandomness, which in fact has the same chance as randomness.. So ye it's kinda random lol, with my statement in my post however, I meant that I just didn't think that this could be random (and have such a differences in time) – javascaped Jun 09 '18 at 23:21
  • 1
    "_I honestly don't think that this discussion about randomness could be won by anyone_" - really not sure what you mean here, there is a correct and an incorrect answer. My point is that using "random" in this context is ... unhelpful. – Boris the Spider Jun 09 '18 at 23:26
  • *"The thread mentioned as duplicate only tells you why to not use System.gc()"* - no, the [answers](https://stackoverflow.com/a/75536/1362755) do more than that, e.g. they mention `DiableExplicitGC`, which is a reason why system.gc may be ignored. – the8472 Jun 10 '18 at 16:22
  • Possible duplicate of [When does System.gc() do anything](https://stackoverflow.com/questions/66540/when-does-system-gc-do-anything) – the8472 Jun 10 '18 at 16:22

1 Answers1

8

Yes. There is a very good reason.


First you need to understand a couple of facts about garbage collection in general:

  1. Running the garbage collector is expensive.
  2. Running the garbage collector (repeatedly) at the wrong time can be catastrophically inefficient1.
  3. Next to impossible for a typical application to predict when the GC can be run most efficiently.

So to your questions:

Using System.gc() or Runtime.getRuntime().gc() won't always execute garbage collection, it just requests it and it can even be ignored by the JVM. Is there a reason behind this?

Yes. It is primarily to guard against the catastrophic behavior effects that naive programmers can cause by calling gc() at the wrong time.

Is it "random"?

Nope. It is nothing to do with randomness.

In practice, typical JVMs have a command line switch that determines whether gc() calls are ignored, or not. This allows the user / deployer / integrator / whoever to mitigate the poor choice made by the programmer.

But note that it cannot be overridden from Java code. That would defeat the purpose of making this a command line switch.

I'm curious why it sometimes doesn't collect it, and sometimes does and also at different times.

The normal behavior of a JVM is to try to run the garbage collector when it is most efficient to do so. The JVM can optimize two ways:

  • It can optimize to maximize the throughput of the collectors; i.e. to minimize the CPU time spent on collection

  • It can optimize to minimize the length of GC pauses; i.e. the times where the JVM has to freeze all application threads during the collection.

It is complicated. From the perspective of an external observer (who / which doesn't have access to the heap stats, etcetera) it may be hard to understand why the GC runs at a given point in time. But is certainly not random.


1 - One of the counter-intuitive properties of a GC algorithm is that the cost of collecting is (in most cases) dominated by the costs of tracing non-garbage objects and moving in memory to coalesce the freed space. So if you call the GC when there is not much garbage to collect, you will end up tracing / moving large amounts of non-garbage for little actual benefit. By contrast, the JVM has a better insight on when it is a good time to collect. For a start, it knows how much space is left in each pool at any point in time.

As well as being counter-intuitive, this behavior gets worse as the heap gets bigger. So a programmer can write code that uses gc() in the wrong way, and not notice that there is a performance problem. The performance only becomes an issue when the application is run with a production workload / problem size. Combine this with the effects of using the heap to cache things, and / or memory leaks.....

Stephen C
  • 698,415
  • 94
  • 811
  • 1,216
  • Good answer. My only suggestion is, to further explain the complexity you mention, add a bit about how there are many different garbage collector implementations. Each takes a different approach and exhibits different behaviors in various scenarios. – Basil Bourque Jun 10 '18 at 03:29
  • @BasilBourque - I don't think it is necessary to explain the complexity here. The Oracle Garbage Collection documents do a better job than I could. – Stephen C Jun 10 '18 at 13:38
  • Another example could be the [Epsilon](http://openjdk.java.net/jeps/318) 'garbage collector' that will be added in Java 11. It does not perform any garbage collection at all. – Mark Rotteveel Jun 16 '18 at 09:40