views:

354

answers:

8

I have a piece of code that load a very big image in memory. So it seemed like a reasonable thing to call

System.gc();

before loading the image. From what I can tell it works with no issues.

Yesterday i decided to use a pretty useful piece of software called FindBugs that scans your code and reports back issues that might cause bugs or generally not advised strategies. The problem is that this piece of code i mentioned gets reported. The description is this:

... forces garbage collection; extremely dubious except in benchmarking code

And it goes on to elaborate :

Code explicitly invokes garbage collection. Except for specific use in benchmarking, this is very dubious.

In the past, situations where people have explicitly invoked the garbage collector in routines such as close or finalize methods has led to huge performance black holes. Garbage collection can be expensive. Any situation that forces hundreds or thousands of garbage collections will bring the machine to a crawl.

So my question is : Is it NOT OK to programmatically call the garbage collector in such a case? My code only calls it once and the method that it is in gets used rarely. And if it is not OK to call it then what should you do in a case where you need as much memory as possible before doing a very memory intensive operation and you need to free as much memory as posible prior to it?

+1  A: 

It's fine to call the garbage collector, you don't get any "problems" from it. However, I doubt it will significently boost performance, unless that call also deals with defragging the allocated data. I don't know that.

What you should do in this case is profile the code. Run it several times, see what sort of results you get.

Daniel Goldberg
+6  A: 

Typically the GC is smarter than you, so it's better to let it run whenever the runtime decides. If the runtime needs memory, it'll run the GC itself

nos
Problem is this is only after it tries allocating something. If you are in a situation where you "know" that you have a very disorganized memory layout and you are "know" you are about to require a large block of memory, you can just invoke the GC a few instructions earlier.
Daniel Goldberg
You never "know" for sure that you have a disorganized memory layout. The GC could have just run, for all you know. The "mark" part of mark-and-sweep takes resources and time even if you don't collect anything. That's why it's nearly always a net negative or (best case) break-even case to try and outsmart the GC.
Jason
The runtime and gc is free to change and move around objects in memory whenever it feels like it(objects are more like a pointer to a pointer if you come from the C world), you'll hardly ever "know" that you have a disorganized layout.
nos
+1  A: 

Typically, you should not interfere with the garbage collector. If it's necessary to free some memory before loading the image, then the garbage collector will do it for you.

Regardless, if you're only doing it once, it's probably not going to affect your performance drastically. Things done in loops are far more important.

Donnie DeBoer
+8  A: 

did you get any performance improvements with the System.gc()? i don't think so, since you probably dont have a lot of objects that needs to be collected before you load the image.

usually the garbage collector knows best when to run, so you shouldnt force it, unless you have a really really good reason to.

btw: calling System.gc() forces a "full" garbage collection, which means that all threads are stopped shortly. otherwise it will probably only make "small" garbage collections, which dont stop all threads.

run your program with -verbose:gc to see how many bytes are collected.

there is also lots of technical information on garbage collection here: http://java.sun.com/developer/technicalArticles/Programming/GCPortal/

clamp
System.gc() doesn't "force" anything. The VM is free to ignore it. The wording in Javadoc is "Calling the gc method *suggests* that the Java Virtual Machine expend effort toward recycling unused objects" (emphasis mine)
Adrian Mouat
-1 for FAILING to read the javadoc on System.gc() as Adrian said, it forces nothing. http://stackoverflow.com/questions/1147511/how-can-i-estimate-amount-of-memory-left-with-calling-system-gc/1149182#1149182 for real forcing gc
KitsuneYMG
+1  A: 

You already got plenty of good advice, which I will try not to reiterate.

If you actually get problems with the GC, like full stops of your application for a second, do the following: 1. check that there aren't any calls to System.gc(); 2. check out the various options for configuring the gc. There are tons of those around, and they are much more helpful, then forcing gc.

Jens Schauder
A: 

Ensure that the large objects can be gc'ed as early as possible. I.e. set variables to null and/or let them fall out of scope. THis helps!

Thorbjørn Ravn Andersen
A: 

Generally, no. It isn't appropriate to call System.gc(). However, I have had a few cases where it made sense.

In the software I write, there is a built-in performance tracking layer. It is mostly used during automated testing, but can be used in the field for diagnostic purposes. Between tests or after specific runs we will call System.gc a few times and then record the memory still present. It provides us with a basic memory foot print benchmark for watching memory consumption trend lines over time. While this can be done with some of the external JVM interfaces, it was easier to do it in place and exact numbers were not required.

On a much older system, we could have upwards of 72 separate JVMs (yeah, 72, there was a good reason for it at the time of construction). In that system, leaving the heap to free float on all 72 JVMs could yield some excessive (well beyond physical memory) total memory consumption. System.gc() was called between heavy data exercises to try and keep the JVM closer to average to keep the heap from growing (capping the heap could have been another direction, but then it would have required the implementers to configure more per site and be more aware of what was happening under the hood to get it right and not have the system fail under load).

Jim Rush
+1  A: 

If a memory allocation fails, a GC cycle is initiated and the allocation is tried again.