The only case I can think of where this might actually happen as you describe, is if you're using WeakReferences (or expired SoftReferences, which are broadly similar in this situation) to refer to objects that you still want to keep. The objects the might get into a state where they're collectable by the GC; but until it actually runs, you'll still be able to reach them through your references. Calling System.gc()
, even though it doesn't have any guaranteed semantics, might cause the collector to run and harvest all these weakly-reachable objects.
That seems unlikely, though, because
- Accidentally using WeakReferences for strongly-reachable objects doesn't seem like an easy mistake to fall into. Even if you're using libraries, I find it hard to think of a case where you might feasibly end up using weak references by mistake.
- If this did happen, the behaviour of the application would be undefined anyway. Garbage collections could happen at any time, so you'd likely see inconsistent behaviour without the System.gc() call. You'd always have some bit of code that runs just after a collection anyway and so couldn't find its referent object.
- System.gc() doesn't theoretically do anything so it shouldn't be causing this.
That last point is the important one - why are you calling System.gc() anyway, when it is almost always counterproductive to call? I don't believe that you have a legitimate need to call it, it doesn't do anything you can rely on, and apparently it's breaking your application.
So if your app works fine without making the call, then just stop making it.
I would still consider inspecting how your app fits together though, because this is not going to be the actual cause of the problem and you likely have a deeper issue which is very fragile and just waiting to break on you later.
EDIT: Another possible reason for this could be simple timing. Calling System.gc()
is likely to take a non-negligible amount of time. During this period, other threads could progress and change state in a way that the GCing thread isn't expecting. Hence when it returns from the call, the state of the world breaks its expectations and hence logic errors result. Again, this is just a guess, but is more plausible than the WeakReference one.