You can garbage collect in Java simply by calling System.gc()
but sometimes this \"stalls\" the application. Is it a bad idea to garbage collect like this and a
I can't beat @haylem answer's clarity and force, sorry. But let me add that there are a lot of (better) ways to manage memory in Java. There is, for example, WeakReference and collections which handle these, like WeakHashMap. These are deterministic ways to handle memory, though explicit calls to GC are not, as per the javadoc
Calling the gc method suggests that the Java Virtual Machine expend effort toward
recycling unused objects in order to make the memory they currently occupy available
for quick reuse. When control returns from the method call, the Java Virtual Machine
has made a best effort to reclaim space from all discarded objects.
I totally agree that explicitely calling the garbage collector is not recommended in general. It can stall the application for several seconds and sometimes minutes. This is usually not an issue if you are dealing with a background service, but if it is exposed to users, they will have a bad experience.
However, there are extreme cases when you will want to do this: when memory is running really short and the application could crash. But a lot can be done is the application's design and implementation to avoid those situations.
One of the features of Java I love when it comes to recollecting memory and avoid memory leak are WeakReference objects. They are your friends.
Yes, most times it is a very bad idea to call System.gc(). There are exceptions but they are few and it is mostly better to spend the time making sure you are not doing things that hurt performance in a GC environment and to study and make sure you understand how a gc works than to try to handle it yourself by explicitly calling System.gc().
As others have said, calling System.gc()
is usually a mistake. (Not always ... )
Assuming that you have one of those rare use-cases where calling System.gc()
is likely to be beneficial, there are two cases to consider:
If your JVM is using a classical "stop the world" collector, then running it in a separate thread will make no difference. The GC stops all application threads for the duration.
If your JVM is running a concurrent collector, then running it in a separate thread may be a good idea. It is true that all collectors have a phase in which all threads are stopped, but calling System.gc()
is documented as returning after "the Java Virtual Machine has made a best effort to reclaim space from all discarded objects". So running it in a separate thread will allow the current thread to do something else. However, you need to be careful to avoid launching multiple threads that each call System.gc()
; i.e. the code that is responsible for launching the thread needs to keep track of any previous GC threads.
Except if you have a very good reason for it. And even if you think you do, you probably don't.
If you kept reading, I'm assuming you have a really awesomely good (albeit probably twisted) reason to attempt to screw around with the GC, even though it is very likely to be a lot clever than you are at determining when it should collect memory. Also, keep in mind that by calling it explicitely you confuse it and screw up its heuristics, so it gets less clever than it was before. All because you attempted to outsmart it.
If you do this for a very good reason, or in a case where you really want to ensure that you start an intensive code section with the best memory state possible, you need to know this probably won't work: calls to System.gc()
do not guarantee a garbage collection to take place, as mentioned by its Javadoc (emphasis mine):
Calling the gc method suggests that the Java Virtual Machine expend effort toward recycling unused objects.
-XX:+DisableExplicitGC
(if your JVM supports it) to prevent those crazy calls of doing any harm (credit to Fredrik in the comments)grep
for calls to System.gc()
and its equivalents and get rid of them.See Grooveek's answer for other useful suggestions (like using WeakReference
s).
Depending on your use case, maybe experimenting with other GC implementations might help: CMC, G1, ParallelGC, etc... If you want to avoid "stalls", I have had very good results with G1 since its introduction in the latest Java SE 6 updates and since the Java 7 release, running intensive enterprise applications for long-running periods.
Just be aware that JVM tuning is a very complicated art.
You can flip through these for a lot more details:
* Use with care: sometimes not perfectly up-to-date, doesn't document everything, and lists a lot of experimental features, or HotSpot-only features.
Apart from what was already said so far, the whole idea is horribly flawed because you sadly miss one important detail:
While a full GC is running the application will be stopped! (at least currently on a modern Hotspot VM - and what else would you be using?)
There's a concurrent mark & sweep implementation in hotspot (though afaik not activated by default), but that incurs some extra overhead and still has to stop all threads before doing the sweep. So basically unimportant from which thread you do System.gc() the VM will wait for all threads to reach a safe point, stop them and then do the collection. So using a thread is completely useless.