Why can’t I turn off the Garbage Collector?

September 6, 2012 by Nikita Salnikov-Tarnovski

Let’s start with a quick rewind to the early days of my career as a Java developer. I wanted to eliminate Garbage Collection (GC) pauses from a test that I was conducting. Lo and behold I was annoyed when I discovered that it couldn’t be done. Back then I left the issue for a “design error” and moved on with my life. Angry at James Gosling or whoever was responsible for the decision.

A couple of days ago I ran into a situation that reminded me of those old times. Luckily, the years gone by have accumulated some insight about JVM internals in me, and I thought I’d share my current thoughts in a form of a blog post.

To start off – some of you might remember Java 1.1 that we used back in late nineties. Back then you actually had the possibility to turn off the GC. At least in Solaris, where the Sun-provided version of the JVM offered a possibility to add a -noasyncgc option to your JVM startup parameters. The option was still supported until the release of JDK 1.4 for backward compatibility, but already starting from JDK 1.2 it didn’t do anything. Besides adding complexity to your startup scripts.

The option turned off the JVM-controlled garbage collector. You could still collect the unused objects by explicitly invoking System.gc() from your code. Sounds like the level of flexibility an experienced engineer could put into good use. So – why was this option removed?

In fact, the motivations behind this move start to make sense, when you consider the following:

  • By disabling the GC you essentially claim that you know how much memory your application would require during runtime. But what if you are wrong? Once the heap fills up, having the GC disabled would cause the death of your application.
  • Invoking System.gc() might not execute the garbage collection at all. In modern JVM’s it is nothing more but a recommendation to the JVM that “I think it is a good spot to run the GC”. And – your sysadmin might have disabled the System.gc() calls at all by specifying -XX:+DisableExplicitGC startup parameter.
  • If System.gc() is actually executed by the JVM, it results in a full garbage collection. This tends to be very expensive with large heaps and result in long pause times.
  • You will still not achieve predictable GC timing by invoking a System.gc(), especially in multithreaded applications.

Now, look at the points above and imagine an application that would run in a JVM without automatic GC. You would probably not want to bet your house on its behavior. The hair on my back immediately start rising when I try to picture a debugging session to trace down any performance issues with that application. So maybe mr. Gosling wasn’t making a design error after all.

But what if my stop-the-world pauses are intolerably long? And I really-really wish to turn the GC off? There actually are some possibilities:

  • There is a part of memory allocated by the JVM in which you can turn off the GC. If you wish you can prohibit GC on your class definitions by specifying -Xnoclassgc in your JVM options.
  • Depending on your application, you might get rid of full GC pauses in compaction phases by tweaking your young and tenured generation sizes. In those cases you can configure the JVM to run only concurrent GC cycles, which in most cases do not affect the performance.
  • You can allocate memory outside the heap. Those allocations obviously aren’t visible to the garbage collector and thus will not be collected. It might sound scary, but already from Java 1.4 we have access to the java.nio.ByteBuffer class which provides us a method allocateDirect() for off-heap memory allocations. This allows us to create large data structures, which is especially useful when running on a 32-bit architecture. This solution is not too uncommon – many BigMemory implementations are using ByteBuffers under the hood. Terracotta BigMemory and Apache DirectMemory for example.

However, I would advise you to turn to those solutions only if you are sure about what you are doing. In 99.9% of the cases the garbage collector will be smarter than you.

Enjoyed the post? We have a lot more under our belt. Subscribe to either our RSS feed or Twitter stream and enjoy.

Can't figure out what causes your OutOfMemoryError? Read more

ADD COMMENT

COMMENTS

I don’t quite see the point of turning off the garbage collection:nEither you do manage to write an application that does not allocate more memory after an initialization phase – and there will never be any garbage collection again. No point of turning it off. nOr your application allocates more and more memory. So it is not exactly a good idea to turn it off, either.nSo why would you want to do this?

Hans-Peter Störr

I don’t quite see the point of turning off the garbage collection:nEither you do manage to write an application that does not allocate more memory after an initialization phase – and there will never be any garbage collection again. No point of turning it off. nOr your application allocates more and more memory. So it is not exactly a good idea to turn it off, either.nSo why would you want to do this?

Hans-Peter Störr

@itoctopusnnYou are right, the compiler is not smart enough to know when to trigger the garbage collector. It is, however, smart enough to manage your memory without using a GC at all! See Clang LLVM ARC (automatic reference counting).nnhttp://en.wikipedia.org/wiki/Automatic_Reference_Counting

Dimitris

I remember when I first took a course in Java (many a years ago) the teacher told us that Java’s ultimate strength is garbage collection. I knew he was wrong back then and I know he was wrong now. Garbage collection should be done by the programmer, and not by the compiler itself – simply because the compiler is just not that smart to do this work. I guess (bad) garbage collection was the reason why Java wasn’t used in developing games until PCs started to have a lot of memory.

itoctopus

Garbage collection is done by the Garbage collector which is part of the jvm not the compiler. Game development is and has been stuck with c combined with c++ because of the tool chains, engines and existing developers experience being in c/c++. Changing this will take a long time – it’s similar to OS development, you can write those in various other languages which can yield great advantages such as eliminating the need for kernel/user space. Change takes time garbage collection has very little to do with it and even so you can design you application with it in mind and than it really isn’t a problem.nnAs for Java specifics, since sun never had any real interest in it any tooling, libraries and interfacing had to come out of the spare time of enthusiastic developers.

Michael

I also used to think I was smarter than other people who has spent a lot more time than me on solving tricky problems.nnI know better now.nnGarbage collected languages are a huge step forward in letting developers focus on solving application problems. I am happy to forego the joy(lessness) of C++ development caused by low level memory management details. When I was less experienced I revelled in this sort of stuff but I now realise that I am wasting my time appeasing a language that is not suitable for development by anything other than a priesthood that can hold 5 contradictory thoughts in their heads at the same time. I prefer to focus on getting the job done, not appeasing the language.nnIn contrast I find working in C fun even with its memory management.nnRemember, if you really want to turn off garbage collection, you always have the option of working in a different language.

Gordon Milne

Your teacher is right, and you are still wrong. It is proven that even the most modern platforms prefer garbage collection.nNew iOS, .NET, Python, PHP, Go, all JVM languages, etc.nnIt’s not the compiler vs programmer, compiler vs runtime.nnThe runtime knows better than the compiler. The runtime knows better than programmer.nnProgrammer has little idea what actually compiler does. Compiler has little idea what the runtime actually does.nnFYI, for bulk random allocations and deallocations, the efficient garbage collector always wins over the C/C++ malloc in term of efficiency. nSome people garbled and had no idea that the efficiency and response time (what they call stop world) is a 2 different things. nnGarbage collection for efficiency, programmer controlled for deterministic response time.

Daniel Baktiar

Can't figure out what causes your OutOfMemoryError? Read more

Latest
Recommended
You cannot predict the way you die
When debugging a situation where systems are failing due to the lack of resources, you can no longer count on anything. Seemingly unrelated changes can trigger completely different messages and control flows within the JVM. Read more
Tuning GC - it does not have to be that hard
Solving GC pauses is a complex task. If you do not believe our words, check out the recent LinkedIn experience in garbage collection optimization. It is a complex and tedious task, so we are glad to report we have a whole lot simpler solution in mind Read more
Building a nirvana
We have invested a lot into our continuous integration / delivery infrastructure. As of now we can say that the Jenkins-orchestrated gang consisting of Ansible, Vagrant, Gradle, LiveRebel and TestNG is something an engineer can call a nirvana. Read more
Creative way to handle OutOfMemoryError
Wish to spend a day troubleshooting? Or make enemies among sysops? Registering pkill java to OutOfMemoryError events is one darn good way to achieve those goals. Read more