Reputation: 2608
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?
Upvotes: 3
Views: 301
Reputation: 200148
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.
Upvotes: 7
Reputation: 328556
Code that tries to force GC is usually a sign for an underlying bigger problem (i.e. design issue or missing knowledge on the developers part).
I have seen a few use cases where calling System.gc()
in production code actually makes sense, for example, before printing the current memory usage - it doesn't matter if the values are off but we'd like to improve chances the values are as small as possible. Of course, we knew that GC was enabled - we used this to automatically detect memory leaks on a QA system.
In general, calling System.gc()
yells "my code is buggy and I don't know how to fix it!".
Upvotes: 0
Reputation: 7630
Programmatic we need to ensure that, when a obj is removed then its corresponding entry should be removed. Only then, that object becomes a candidate for garbage collection. Otherwise, even though it is not used at run-time, this stale object will not be garbage collected.
The object to which this reference refers, or null if this reference object has been cleared. As your object reference of WeakReference class. so it will not give null. but after removing gc., it provide null.
Object obj = new Object();
WeakReference ref = new WeakReference<Object>(obj);
obj = null;
if(ref.get()!=null)
{
System.gc();
System.out.println("remove ref");
}
if(ref.get()!=null){
System.out.println("not execute");
}
Output:
remove ref
Don't assign null value to obj.
Object obj = new Object();
WeakReference ref = new WeakReference<Object>(obj);
if(ref.get()!=null)
{
System.gc();
System.out.println("remove ref");
}
if(ref.get()!=null){
System.out.println("execute");
}
Output:
remove ref
execute
Upvotes: 0
Reputation: 8205
The point is that your thread will stop and wait until the weak reference is cleared, thus "simulating" garbage collection. There's no guarantee when (or indeed even IF) this will actually happen.
You could be stuck waiting on this while
for a long, long time.
Upvotes: 0
Reputation: 30216
There is no way to guarantee a GC call because just as the documentation says System.gc
is just a hint that can be ignored by the system.
So assume that the JVM ignores System.gc
- in that case the whole thing just loops until some other part of the systems causes a GC. If you run single-threaded or nobody else allocates much memory you basically create an inifite loop here.
Upvotes: 1
Reputation: 109547
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.
Upvotes: 2