Re: calling System.gc to suggest garbage collection
Peter Duniho wrote:
To the extent that a smaller working set reduces paging, anything Java
can do to reduce the amount of memory it actually accesses would be
productive. But that is already a basic goal, even ignoring
page-swapping issues. GC is more costly the more objects that need to
be inspected, even if all those objects are already swapped-in.
And in fact, the Java GC implementation has features intended to address
that goal of reducing memory accesses (e.g. object generations).
Young-generation collections don't touch dead objects.
<http://www.ibm.com/developerworks/library/j-jtp01274.html>
"copying collectors do not visit dead objects, a heap with a large number of
temporary objects, which is a common situation in Java applications, costs
very little to collect; simply trace and copy the live objects to a survivor
space and reclaim the entire heap in one fell swoop."
The same article discusses why one should *not* call 'System.gc()':
"... developers often mistakenly think they are helping the garbage collector
is the use of System.gc() ... Unfortunately, System.gc() triggers a full
collection, which includes tracing all live objects in the heap and sweeping
and compacting the old generation. This can be a lot of work."
<http://www.javaworld.com/javaworld/jw-01-2002/jw-0111-hotspotgc.html>
"The HotSpot JVM uses a two-machine-word object header, rather than the
three-word header found in most other JVMs. This saves as much as 10 percent
of the heap size for typical applications while accelerating the code to scan
all objects.
"The HotSpot JVM also eliminates the concept of handles. This reduces memory
usage and speeds processing. In the HotSpot JVM, object references are
implemented as direct pointers, providing C-speed access to instance variables."
Inasmuch as Java already does what it can to reduce the number of
objects it has to inspect during a GC pass, it thus also is already
doing what it can to reduce the active working set, reducing page swapping.
In what writers call "typical" usage patterns, it is claimed that 90-98% of
objects are dead before they get promoted to the tenured generation. That
means the young-generation collector only needs to visit 2-10% of the objects
in the nursery to do a collection.
Whether that qualifies in your mind as "virtual-memory-swap aware", I'm
not sure. But I think it's safe to say that the Sun developers who are
responsible for the JVM and its memory management implementation fully
expect Java to be running on systems with virtual memory management and
a swap file, and do take that into account to the extent that they can.
To respond to Roedy's question, everything I've read about the 'System.gc()'
call suggests that it's unwise to use. OTOH, I've heard anecdotes in the
field that suggest that it is useful, though none of those anecdotes seem to
come with descriptions of alternatives rejected, such as tuning the JVM's GC
parameters [1]. Some of those anecdotes related to situations where memory
was inappropriately retained ("packratted") and 'gc()' was a band-aid approach
that missed the real problem.
Simple logic suggests to me that hard-coded 'gc()' calls cannot "know" when
memory is tight, but the JVM always will. That means that 'gc()' will never
do better than regular GC at creating free memory when it's needed. As to
making it faster, if memory is not tight then triggering a 'gc()' is
unnecessary and therefore not "faster" in any useful sense. If memory is
tight, the JVM will trigger a GC anyway, so asking for it does not help. If
'gc()' doesn't help when memory is not tight, nor when memory is tight, then
there's never a need to call it.
If you think that 'gc()' might help, run the program in question twice under
load for a long time with the 'gc()' calls in place, once without the option
"-XX:-DisableExplicitGC" and once with. Measure the difference.
[1]
<http://java.sun.com/docs/hotspot/gc5.0/gc_tuning_5.html>
<http://java.sun.com/javase/technologies/hotspot/gc/gc_tuning_6.html>
--
Lew