System.gc() does not force a garbage collection, contrary to what you might think. The Javadoc does not say it is a "blocking method", so there's no reason to assume it blocks in any way.
Normally you will never need to call System.gc(). You should leave garbage collection to the JVM and not mess with it yourself. The garbage collection algorithms built into the JVM are quite sophisticated and know how to do things as efficiently as possible - by messing with them, you can even make garbage collection less efficient.
To answer the question that was actually asked, System.gc() may block for as much or as little as a particular implementation feels like blocking. There are no real guarantees here, but it's reasonable to assume that System.gc() will probably not return immediately.
"I'm not back." - Bill Harding, Twister
Joined: Feb 23, 2004
So this means that frequent calls to System.gc() is not advisable. Correct ?
Joined: Jan 30, 2000
Correct. More generally, in most applications any call to System.gc() is not advisable. Nowadays most garbage collectors are optimised well to run on their own schedules, and calling gc() yourself more likely than not will end up reducing overall efficiency. PErsonally I do it only if I'm performing certain types of memory usage tests, where I don't care about overall efficiency but I do care about knowing how much memory is really, really needed at a given point in a program. That's not something you normally need to worry about though.
I disagree that you should 'never' call System.gc(). There are times when you're doing a copy/delete of a huge amount of data where it would appropriate, when the entire process was finished, to suggest garbage collection to the JVM via System.gc().
I think the clarified question here is "If System.gc() does actually cause garbage collection to take place, does it block while said garbage collection is taking place?"
I don't know the answer to this question. It's probably "It depends" but I don't know what it depends on.
Joined: Jan 30, 2000
Scott - I did say, in most applications. There can be exceptions. But Arnb was asking if "frequent" calls were inadvisable, and I'm saying that most of the time you shouldn't call it at all. If there's a good reason to call it, OK. Though I suspect many "good" reasons might turn out to be not so great if analyzed or tested carefully. If you're using generational garbage collection (and I believe that's pretty much standard now) the big danger with running gc() is that you might prematurely force many objects into tenured or permanent space, making them much harder to collect later.
Paul - I think the answer is still that there are no guarantees, and it depends on the JVM implementation, as well as the current status of how much memory is currently being used, and how long it's been since the last GC activity, and whether objects are allocated in eden space, tenured, or permanent.
Looking at the API, note the phrasing: "When control returns from the method call, the Java Virtual Machine has made a best effort to reclaim space from all discarded objects." That strongly suggests a blocking call. However "best effort" is ultimately meaningless - and to the extent it has meaning, that meaning is ignored by current implementations. Calling gc() two or three times in a row will usually collect more than is collected by one call - which tells me that the original effort wasn't really "best effort". Also, GC activities routinely go on in background threads anyway, in addition to going on in whatever thread might call System.gc(). So I don't think we can make any useful absolute statements here. When System.gc() is called, the thread will probably block until some amount of GC has been performed, which will probably free up a decent number of objects but not as many as could be freed up by repeated calls if you really wanted to. After gc() returns, additional GC may occur in another thread, just as it can at any point during JVM execution. But that's not a big effect generally.
Interested parties may wish to run tests using the -verbose:gc flag. You can also call System.gc(), then Thread.sleep() for a while, then System.gc() again, and see if any significant GC gets accomplished just after System.gc() returns. From my observations in the past I think the answer's usually no. Unless it's a multithreaded application and something happens in another thread which makes more objects available.