Garbage collection

C

Crouchez

When exactly does it run? Is it a scheduled thing or when memory hits a
certain point? And what effect does manually calling System.gc() have on the
process?
 
A

Andreas Leitgeb

Crouchez said:
When exactly does it run? Is it a scheduled thing or when memory hits a
certain point? And what effect does manually calling System.gc() have on the
process?

You can consider the GC a friend of yours:
You can tell him: now, and now, and then again now is a
good time to clean up, but he's neither obliged to do
so every time, nor obliged to wait until your next hint.
Casually he will say: well, I wouldn't have done it right
now, but if you think ... - That's why System.gc() even
exists. :)

Situations, where "minding GC's business" was really
necessary are rare, but still existing.
 
E

Eric Sosman

Crouchez said:
When exactly does it run? Is it a scheduled thing or when memory hits a
certain point? And what effect does manually calling System.gc() have on the
process?

Different JVM's have different policies about when and how
to carry out garbage collection. So the answer to "exactly
when" is "whenever it likes," and the answer to "is it scheduled
or is it triggered" is "yes." All you can truly rely on is that
the JVM will not throw OutOfMemoryError without attempting a
garbage collection first.

System.gc() does what its Javadoc says: It "suggests" that
the JVM collect some garbage, and the JVM will make a "best
effort" to do so before the method returns. However, there's no
precise definition of what a "best effort" is: If the JVM decides
that a garbage collection would be inconvenient at the moment,
its "best effort" might amount to ignoring the "suggestion."

The prevailing wisdom is that System.gc() is very seldom a
good idea, particularly in code that is expected to run on a
variety of different JVM implementations with different garbage
collectors. In limited circumstances when the code is running on
one well-researched version of one specific JVM it may make sense,
but that's about it. Calling System.gc() is, in essence, making
a static decision based on predicted conditions instead of letting
the JVM make a dynamic decision based on actual conditions. You
may be smarter than the JVM, but the JVM has much more information
than you do.
 
W

Wojtek

Eric Sosman wrote :
The prevailing wisdom is that System.gc() is very seldom a
good idea, particularly in code that is expected to run on a
variety of different JVM implementations with different garbage
collectors. In limited circumstances when the code is running on
one well-researched version of one specific JVM it may make sense,
but that's about it. Calling System.gc() is, in essence, making
a static decision based on predicted conditions instead of letting
the JVM make a dynamic decision based on actual conditions. You
may be smarter than the JVM, but the JVM has much more information
than you do.

True, though I have code which does call it. The code manipulates
images in a Web server environment. Image processing takes a LOT of
memory, so I put in a counter which which calls System.gc() every ten
runs. That way the user doing the tenth manipulation takes the
(possible) time hit.
 
M

Mike Schilling

Eric said:
The prevailing wisdom is that System.gc() is very seldom a
good idea, particularly in code that is expected to run on a
variety of different JVM implementations with different garbage
collectors. In limited circumstances when the code is running on
one well-researched version of one specific JVM it may make sense,
but that's about it. Calling System.gc() is, in essence, making
a static decision based on predicted conditions instead of letting
the JVM make a dynamic decision based on actual conditions. You
may be smarter than the JVM, but the JVM has much more information
than you do.

As always, there are exceptions. Say you have a program that:

1. Interacts with the user
2. When asked to, runs some time and memory-intensive processing
3. Interacts with the user some more

It makes sense to call System.gc() at the end of step 2, so that the
time required for the GC doesn't interrupt the user interaction.
 
E

Eric Sosman

Mike said:
As always, there are exceptions. Say you have a program that:

1. Interacts with the user
2. When asked to, runs some time and memory-intensive processing
3. Interacts with the user some more

It makes sense to call System.gc() at the end of step 2, so that the
time required for the GC doesn't interrupt the user interaction.

Note that I wrote "very seldom," not "never."

You, I think, should have written "may make sense" instead
of "makes sense." The fact that Step 2 is time-intensive is
irrelevant, and the fact that it is memory-intensive matters
only if (1) a lot of garbage has accumulated and (2) a collection
is imminent anyhow. Both (1) and (2) are difficult or impossible
to know at coding time, when you're deciding whether to call
System.gc() or not. Also, if the first thing the user does in
Step 3 is click the "Quit" button, the time spent on anticipatory
GC is very likely wasted.
 
L

Lew

Crouchez said:
So it [GC schedule] varies depending on what type of VM you're using?

It varies depending on the type of VM, on the options applied to the VM (all
commercial VMs have a host of GC-tuning options), and on the run-time profile
of the code running in the VM.
 
M

Mike Schilling

Eric said:
Note that I wrote "very seldom," not "never."

You, I think, should have written "may make sense" instead
of "makes sense." The fact that Step 2 is time-intensive is
irrelevant,

Not at all. If the user is already expecting to wait for the
processing to complete, the added wait for GC becomes invisible, which
is the point.
and the fact that it is memory-intensive matters
only if (1) a lot of garbage has accumulated and (2) a collection
is imminent anyhow.

The point is that, the wait at the end of 2 being invisible to the
user, it's worth doint to avoid a visible wait later. An insurance
premium, if you like.
 
L

Lew

Mike said:
Not at all. If the user is already expecting to wait for the
processing to complete, the added wait for GC becomes invisible, which
is the point.


The point is that, the wait at the end of 2 being invisible to the
user, it's worth doint to avoid a visible wait later. An insurance
premium, if you like.

An insurance premium where the insurance company makes no promise to pay off a
claim. If memory was getting tight, the JVM likely already scheduled the GC
before you called gc(), and if it wasn't, it'll perhaps ignore the request.

and anyway, what's the big deal if memory isn't tight? If the JVM doesn't
ignore the gc() request, you just invoked a GC where there would have been
*no* delay otherwise, because there would've been no collection.

There are many ways to tune GC to avoid excessive pauses. Calling gc() really
isn't one of them.

The simplest is to exploit Java's memory style idiomatically - keep the
lifetime of objects very short so that they get collected from the young
generation. If you never incur a full GC, you probably will never see long
pauses.

Note that the size and number of the objects don't matter. Dead objects don't
incur overhead in young-generation collections, so you can allocate a shipload
of massive objects as long as you dereference them quickly.

Beyond that, how many dozen GC-related parameters are there for the JVM?
<http://blogs.sun.com/watt/resource/jvm-options-list.html>
I counted four dozen before I decided that made the point. And that's just
for Sun.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,769
Messages
2,569,580
Members
45,054
Latest member
TrimKetoBoost

Latest Threads

Top