Why does calling System.gc not guarantee running the Garbage Collector?

Asked

Viewed 959 times

17

Why the developer does not have full control over the Garbage Collector?

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

3 answers

10


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

To specification the language does not give details about the functioning of the GC, does not require it to work or stop working at a given time, that it is implemented with a specific technique, which is concurrent or not, synchronous or not, does not specify how its response time should be, so little when it must 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 doesn’t break the language specification. And GC is one of the things that changes most in Java. The wicked say she needs to have an increasingly better GC because it generates a lot of junk (and it’s true). When reading this the GC may be different and this may be worth more or less.

Generations

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

If his user, the programmer, forces a collection, he is just throwing "live" data from one generation to the next and currently there are 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 that GC should avoid. For this the best to do is to prevent the die from getting there, or that it only occurs when it really is needed, when the die has a really long life time.

Calling the GC anticipates your call and can throw an object to the last generation without need, and then collections will cost more often.

I could go into more detail, but it’s not that important. GC was made so you don’t worry about how it works internally.

Several implementations

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

Note that there are Gcs for Java that are simpler than this. They can always run and can be effective, but don’t count on this.

The problem is precisely in non-standard behavior. You cannot specify a standard behavior for different needs, otherwise certain implementations will be impossible. And you can’t specify something that will work sometimes. The specification takes the safe way to say it guarantees nothing, so no one program thinking they can benefit from some GC behavior.

You can even have settings that change GC behavior.

Therefore it is dangerous to program on the basis of "worked on my machine" or "I tested and it worked". It has to program based on the specification.

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

Getting full control of memory

If you need to control your memory more than that, don’t use Java. Each language has its philosophy, strengths and weaknesses. Java has never worried about parsimonious use of memory, its strong is at another point, which is not having to worry about memory management.

8

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

https://docs.oracle.com/javase/7/docs/api/java/System.html#gc%28%29

Now of course it raises the question: why the language was designed so?

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

When control Returns from the method call, the Java Virtual Machine has 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 up the garbage that was. That means the call is synchronous. Expensive process + synchronous call = your application wait too long to actually continue running.

This can be problematic, so in different scenarios, the JVM can decide that not doing the full garbage collection is the best choice. JVM can also be manually configured to ignore the 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 GC during the loading screen, rather than waiting for it to run and pause the entire system when the user is actually playing. That’s why the call continues to exist. Just don’t trust it with the correctness of your application.

6

TL;DR

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

Every warranty limits how it can be implemented.

Let’s go in pieces...

Why call the System.gc does not guarantee execution of Garbage Collector?

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

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

Simpler and synchronous GC implementations run when calling System.gc(), but note that this is an implementation behavior and not the specification.

Why developer does not have full control over Garbage Collector?

You can’t 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 which is the implementation of a certain JVM that is running 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 the 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 cited above.

An analogy

An analogy might well illustrate the situation. Imagine if the question were so:

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

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

Browser other questions tagged

You are not signed in. Login or sign up in order to post.