Why calling System.gc does not guarantee execution of the garbage collector?

14

Why does not the developer have full control over the garbage collector ?

I understand that the role of GC is to automatically manage memory but why even using some method like System.gc is there no guarantee that the GC will run?

    
asked by anonymous 22.12.2015 / 05:23

3 answers

8

It is possible to have control over the garbage collector, this just does not occur with Java in its default implementation, as far as I know, also by specification. I'll answer based on the context of the question.

The specification does not give details about the operation of the GC, does not require it to function or to stop functioning at any given time, to be implemented with a specific technique, whether concurrent or not, synchronous or not, not specific as it should be your response time, so little when it should occur.

The current GC in the best-known Java implementation works as shown in the GC documentation. This can be changed as long as it does not violate the language specification.

Generations

The main reason the GC does not guarantee anything is that it can worsen a situation. In the current implementation there is a system of generations. When you call the GC forcing a collection, you think it will decrease possible latencies in the middle of a render. And it may be just the opposite. The system of generations is very complex and was created precisely to decrease the latencies when it is invoked.

If his user, the programmer, forces a collection, he is only throwing "live" data from one generation to another and there are currently only 3 of them. When the object falls in the last generation, the advantage of low latency is lost. Collecting in the last generation is something the GC should avoid. For this the best thing to do is to avoid that the data arrives there, and that only occurs when really it is necessary, when the data has a really long time of life.

Calling the GC anticipates your call and can throw an object to the next generation without need, and there collects will cost more expensive more often.

I could go into more detail, but it's not that important. The GC was made so you do not worry as it works internally.

Various implementations

The fact that it is not guaranteed does not mean that nothing will be done. Otherwise it would not make sense to have an explicit call to it.

Note that there are GCs for Java simpler than this. They can always run, and can be effective. But do not count on it.

The problem is precisely in non-standard behavior. You can not specify a default behavior for different needs, otherwise certain implementations will be disabled. And you can not specify something that will work sometimes. The specification takes the sure path of saying that it does not guarantee anything, so no one program thinks that it can benefit from some GC behavior.

You can even have settings that change the behavior of the GC.

That's why it's dangerous to program on the basis of "it worked on my machine" or "I tested it and it worked". You have to program based on the specification.

It is a mistake to do this, but if you are aware that a GC implementation that you are going to use can benefit your code in some situation, to the extent that you justify ignoring it, then you can use it. Accept the risk and control the application so that it does not use another type of GC. In 99.999% of cases, or a little more, you should not do that.

Getting full memory control

If you need to control memory more than this, do not use Java. Every language has its philosophy, its strengths and weaknesses. Java never worried about the parsimonious use of memory, its strong is at another point, that is not having to worry about memory management.

    
22.12.2015 / 06:38
8

Because that's how the language was designed. This can be seen in the official documentation:

link

Now this of course raises the question: Why was the language designed like this ?

This has to do with both the philosophy of language (it does not interest the Java programmer explicit memory management) and practical reasons: garbage is an expensive process. See this:

  

When control returns from the method call, the Java Virtual Machine   you have made a best effort to reclaim space from all discarded objects.

That is, when the control returns to the code that called the method, the JVM did everything it could to pick the garbage out there. This means the call is synchronous . Expensive process + synchronous call = your application will wait a long time to actually continue to roll.

This can be problematic, so in different scenarios, the JVM may decide that not doing the full garbage collection is the best choice. The JVM can also be manually set to ignore System.gc() .

Of course there are situations where it might be a good idea to call the GC. For example, during a game, you might want to call the GC during the loading screen instead of waiting for it to run and pause the entire system when the user is actually playing. That's why the call continues. Just do not entrust to her the correctness of your application.

    
22.12.2015 / 06:08
5

TL; DR

Because Garbage Collector (GC) is more a concept than exactly an algorithm or set of classes or APIs.

Every warranty limits how it can be implemented.

Let's go by parts ...

  

Why calling System.gc does not guarantee garbage collector execution?

There are many ways to implement a GC: concurrent and parallel , continuous , etc. In many cases it makes no sense to call this routine explicitly.

If the specification guaranteed execution on the call, it would be limiting how GC can be implemented. And that's exactly what they want to avoid.

Simpler, synchronous implementations of GC execute when calling System.gc() , but note that this is a behavior of the implementation, not of the specification.

  

Why does not the developer have full control over the garbage collector?

You can not have full control over the inner workings of something that works like a black box.

In fact, you can rather have control over certain aspects of GC when you know in advance what the implementation of a certain JVM is running on your system. There are several articles on the internet that will teach you how to handle the GC settings of each JVM.

  

I understand that the role of GC is to automatically manage memory but why even using some method like System.gc there is no guarantee that the GC will run?

" Automatically " is the keyword. It is not meant to be manually, for reasons already mentioned above.

An analogy

An analogy may illustrate the situation well. Imagine if the question were like this:

  

Why Set does not guarantee the order of the elements of the set?

Because according to the concept of sets there is no order, but there are implementations of the Set interface that maintains the order, which you can use when you need it.

    
22.12.2015 / 06:57