Last Updated: February 25, 2016
·
3.499K
· austinkeeley

Java code smell: System.gc()

I've found a lot of questions on Stack Overflow that go something like this:

My Java program keeps crashing because it's running out of memory, but I'm calling System.gc() to do manual garbage collection. What's wrong?

Java's automatic garbage collection is a wonderful thing and it's enabled developers to focus on writing code instead of tracking down bugs, but I feel like we now have a generation of programmers who don't understand the subtle details of memory management. If you do Java development (or any kind of managed memory language development), you should at least take some time to understand the rules of garbage collection.

Garbage collection implementation is largely dependent on your JVM, but the rules of when objects are eligible for collection are the same. Here's Oracle's documentation on this:

An object is eligible for garbage collection when there are no more references to that object. References that are held in a variable are usually dropped when the variable goes out of scope. Or, you can explicitly drop an object reference by setting the variable to the special value null. Remember that a program can have multiple references to the same object; all references to an object must be dropped before the object is eligible for garbage collection.

The only thing I'd like to add to that is to point out that the object becomes eligible for garbage collection. It does not actually get collected. Your JVM is going to figure out the best time to actually do the garbage collection.

That brings us back to System.gc(). The Javadocs for this method say that it "runs the garbage collector". That's a little misleading. If you read the details, we learn that it only suggests to the JVM that it should do garbage collection. Furthermore, even if the suggestion is taken, the garbage collection will probably happen asynchronously, so you might not have more memory available instantly.

If you find System.gc() in your code, that's probably something you want to flag for review. It's not necessarily bad, but it shows that there's a problem there that's being solved in a way that may or may not be stable. It might work today, but it could fail the next time it's run. Here's a few alternatives:

  1. Re-read those rules of garbage collection eligibility. You might be holding on to references to objects without realizing it.
  2. Adjust your JVM memory arguments and run profiling tools to figure out what's going on and why you seem to be running out of memory.

Let's all recognize that System.gc() isn't an absolute solution and you can't rely on it as a fix and it's probably a sign that you have some less-than-good code on your hands.

Alright, well I've managed to write this whole thing without making any kind of joke about garbage collection and code smell, so I think I should just stop now.

1 Response
Add your response

It's worth to say that OOM is being thrown by GC. So the call System.gc() doesn't make sence.

over 1 year ago ·