Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Java: reliably calling GC?

In some library found on google code I came across this util method:

public static void gc(){
    Object obj = new Object();
    WeakReference ref = new WeakReference<Object>(obj);
    obj = null;
    while(ref.get()!=null)
    System.gc();
}

Its doc says it provides a reliable way to call GC, because calling System#gc() is just a hint without any guarantees. I showed it my senior, and he said I should think about why this method is invalid. I read some articles on weak references but I'm still confused. Can somebody show me the point?

like image 300
gyorgyabraham Avatar asked Feb 20 '26 14:02

gyorgyabraham


2 Answers

I have direct experience with the supposed "safe GC" idiom you have posted.

It doesn't work.

The reason is quite simple: just the fact that a weak ref is cleared is not a signal that the object has been collected; it only means that it has become unreachable through any strong or soft reference. In my experience this signal arrives before the object is reclaimed.

A better attempt would be to use a Phantom reference, which at least ensures that the object has entered the finalizable state, but once again, it can still be occupying the heap, and in practice it still is occupying it. Another explanation could be that this particular object, obviously residing in Eden space, did get reclaimed, but the GC run which did it was not exhaustive and there is more memory to reclaim in other generations.

On the other hand, I have very reliably used this trivial idiom:

for (int i = 0; i < 3; i++) { System.gc(); Thread.sleep(500); }

Try it and see if it works for you. The sleep part is optional: it is needed only if System.gc() uses concurrent sweeping.

If you object to the apparent fickleness of this approach, just remember that any approach to explicit GC-ing is fickle. This one is at least honest about it—and just happens to work on actual systems. It is, naturally, non-portable and can cease to work at any time for a large array of reasons. Even so, it is the best you'll ever get.

like image 68
Marko Topolnik Avatar answered Feb 22 '26 04:02

Marko Topolnik


The point is, that System.gc() does not need to clean up all weak references. And consider some Java virtual machines too. If System.gc for once (the first time) does decide to not clean that reference, it is very likely to the next call. Hence you have a possibly infinite loop. Probably depending on other threads changing the state for the garbage collection to terminate the loop.

So: once is enough.

like image 24
Joop Eggen Avatar answered Feb 22 '26 02:02

Joop Eggen



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!