Home | Contact Us | FAQ | Search & Site Map | Link to Us
Sign In | Join | Other 45 Sites in Network
HomeAnnouncementsWhite Papers
Discussion GroupsFirst AidDatabasesJavaBeansGUIJava 3DVirtual MachineCORBASecurityToolsGeneral
Java DirectoryOpen Source ProjectsSample Book ChaptersUser GroupsWeb Resources
Related Topics
Databases.NETMore Topics ...

Java Forum / General / June 2007

Tip: Looking for answers? Try searching our database.

Forcing System.gc()

Thread view: 
R. Vince - 07 Jun 2007 14:42 GMT
I have an app that, at one point, really bogs down as so many objects are
created and released in a lengthy process.

I am wondering if I may not be able to improve performance by System.gc() in
some "right" places in my code (wherever those might be!). It seems to me
though, that the gc facilities in Java are so good, that this is something
best left up to the JVM, and NOT mess with putting System.gc() in anyplace?

I am on WinXP / Vista and JRE 1.6.x. TIA, R. Vince
Eric Sosman - 07 Jun 2007 17:00 GMT
R. Vince wrote On 06/07/07 09:42,:
> I have an app that, at one point, really bogs down as so many objects are
> created and released in a lengthy process.
[quoted text clipped - 3 lines]
> though, that the gc facilities in Java are so good, that this is something
> best left up to the JVM, and NOT mess with putting System.gc() in anyplace?

   The usual wisdom is that the JVM has a more accurate
idea of the state of memory than you do.  Its decisions
about when to collect garbage, since they are made in
light of the actual run-time memory pressure, are likely
to be better than static decisions you make at coding
time without benefit of the JVM's knowledge.

   In very rare cases you might do better than the JVM,
because the knowledge advantage is not entirely one-sided.
The JVM has better information than you do on the current
state and recent history of memory, but has no knowledge
of the program's future behavior.  You may be able to
exploit your foreknowledge to choose a better moment for
GC than the JVM would if left to its own devices.

   ... but such cases are likely to be extremely rare.
About the only scenario I can come up with is a program
that runs in "waves:" it creates a huge population of
objects, then throws nearly all of them away, and then
repeats.  You might get some advantage by running GC in
the "troughs," just after the great object die-off and
before the ensuing population boom.  But that's "might"
as in "it's conceivable, I suppose," and not a promise of
any benefit -- it's not even a promise of no harm!

   Suggestion: Gather some statistics on the actual GC
behavior of your program.  If you find that GC is a problem,
your next step should be to find out why it runs so often
and so hard: Are you creating and discarding objects sub-
optimally, as in

    String s = "";
    for (String s2 : hugeCollectionOfStrings)
       s += s2;

Reducing "object churn" will probably do more to help with
GC than quite a lot of GC-centered fiddling.  (Memory
profilers may also be of help here.)

   If GC is still a problem even after you've done all you
can to use your objects intelligently, then and only then
should you resort to fiddling with the GC itself.  And if
you do, be sure to measure what happens and compare with
the original, pre-fiddling measurements: "tuning" GC may
actually have made things worse, and it may be necessary to
"de-tune" it just to recover the status quo ante.

Signature

Eric.Sosman@sun.com

Philipp Leitner - 07 Jun 2007 23:49 GMT
> I am wondering if I may not be able to improve performance by System.gc() in
> some "right" places in my code (wherever those might be!). It seems to me
> though, that the gc facilities in Java are so good, that this is something
> best left up to the JVM, and NOT mess with putting System.gc() in anyplace?

Probably. But you can never 'force' the JVM to do garbage collection.
System.gc() will only 'suggest' that now may be a good time to do GC
(but under certain circumstances, I think it has to do with system
load, the JVM might simply ignore the call). Anyway, I think the cost
for calling System.gc() is not huge, so perhaps I think it might be
worth a try.

I for myself remember having used System.gc() exactly once so far - in
one project I was running >200 Unit Tests, and every test case was
creating an in-memory representation of a WSDL file and compiled XML
Schemata using XMLBeans. At some point in the test run the JVM just
stopped with OutOfMemory. Putting a System.gc() at the end of every
single test case solved the problem just nice.

/philipp
Twisted - 08 Jun 2007 02:13 GMT
> I for myself remember having used System.gc() exactly once so far - in
> one project I was running >200 Unit Tests, and every test case was
> creating an in-memory representation of a WSDL file and compiled XML
> Schemata using XMLBeans. At some point in the test run the JVM just
> stopped with OutOfMemory. Putting a System.gc() at the end of every
> single test case solved the problem just nice.

Looks like a bug in the JVM you were using. If it required too much
memory, it should have had OOME no matter what. On the other hand, if
it didn't, it shouldn't have no matter what. All reclaimable garbage
is supposed to be reclaimed before OOME is thrown; the JLS specifies
this, absent unusual and non-default GC-behavior commandline options
to the JVM. So the GC at the end of every single test should just have
changed one large pause where the OOME would *otherwise* have been
thrown into lots of little pauses sprinkled throughout the testing
routine. It should not have prevented an OOME, just a large pause.
Matt Humphrey - 08 Jun 2007 02:19 GMT
|> I am wondering if I may not be able to improve performance by System.gc() in
| > some "right" places in my code (wherever those might be!). It seems to me
[quoted text clipped - 14 lines]
| stopped with OutOfMemory. Putting a System.gc() at the end of every
| single test case solved the problem just nice.

Can you explain how your request for gc would prevent an OutOfMemory error?
I thought that OutOfMemory occurs only when gc cannot reclaim any more--it
is never necessary to request gc to prevent OutOfMemory.

Cheers,
Matt Humphrey matth@ivizNOSPAM.com http://www.iviz.com/
Philipp Leitner - 08 Jun 2007 11:10 GMT
> Can you explain how your request for gc would prevent an OutOfMemory error?
> I thought that OutOfMemory occurs only when gc cannot reclaim any more--it
> is never necessary to request gc to prevent OutOfMemory.

No, I can't. I really didn't think much about it so far, but it
definitely worked.

/philipp
Patricia Shanahan - 08 Jun 2007 14:15 GMT
>> Can you explain how your request for gc would prevent an OutOfMemory error?
>> I thought that OutOfMemory occurs only when gc cannot reclaim any more--it
>> is never necessary to request gc to prevent OutOfMemory.
>
> No, I can't. I really didn't think much about it so far, but it
> definitely worked.

Here's one random explanation...

Suppose one of the objects has a finalizer that creates some new
objects. That would be fine if it were finalized while there is plenty
of free memory, as would be the case with a System.gc call at the end of
every cycle of the program.

Patricia
Lew - 08 Jun 2007 15:11 GMT
> Suppose one of the objects has a finalizer that creates some new objects.

What a dark and evil notion.

I catch grief for finalizers that release resources, just in case the regular
methods didn't.

Now that you have me imagining, I conceive of finalizers that spawn new
threads with their own service cycles, external connections, ...

I hope I awaken soon.

Signature

Lew

Matt Humphrey - 08 Jun 2007 17:46 GMT
| >> Can you explain how your request for gc would prevent an OutOfMemory error?
| >> I thought that OutOfMemory occurs only when gc cannot reclaim any more--it
[quoted text clipped - 9 lines]
| of free memory, as would be the case with a System.gc call at the end of
| every cycle of the program.

That's brilliant.  If the OOM is inevitable, early gcs could delay it.  If
it's not inevitable they could prevent it.

I was thinking that early gcs might affect how objects enter generations,
but supposedly that wouldn't matter because the gc before a OOM would always
be as thorough as possible.

Cheers,
Matt Humphrey matth@ivizNOSPAM.com http://www.iviz.com/
Eric Sosman - 08 Jun 2007 18:13 GMT
Matt Humphrey wrote On 06/07/07 21:19,:
> |> I am wondering if I may not be able to improve performance by System.gc()
> in
[quoted text clipped - 22 lines]
> I thought that OutOfMemory occurs only when gc cannot reclaim any more--it
> is never necessary to request gc to prevent OutOfMemory.

   Might a really memory-hungry finalize() cause such
a thing?  I imagine that if finalization uses a lot of
memory, running GC early could schedule deceased objects
for finalization while memory is still plentiful, while
postponing GC until memory is scarce might leave too
little for the finalizers' use.  (I hasten to add that
I don't say things *would* play out this way, just that
it seems to me that they might -- I'm entirely ready to
be corrected by someone who knows better.)

   A memory-hungry finalizer seems an awfully silly
thing to write -- but that doesn't mean nobody writes
them ...

Signature

Eric.Sosman@sun.com

Mark Space - 08 Jun 2007 20:33 GMT
> Can you explain how your request for gc would prevent an OutOfMemory error?
> I thought that OutOfMemory occurs only when gc cannot reclaim any more--it
> is never necessary to request gc to prevent OutOfMemory.

Would it be possible that long running code without garbage collection
left the heap so fragmented that the largest available memory block
wouldn't hold some object that needed to be allocated?  That's all I can
think of.  I don't know enough about JVM and memory allocation to know
if this is even a likely scenario...
Twisted - 08 Jun 2007 20:53 GMT
> > Can you explain how your request for gc would prevent an OutOfMemory error?
> > I thought that OutOfMemory occurs only when gc cannot reclaim any more--it
[quoted text clipped - 5 lines]
> think of.  I don't know enough about JVM and memory allocation to know
> if this is even a likely scenario...

Shouldn't be. The thorough GC tried before throwing OOME should
compact all the surviving objects into one or two contiguous blocks
(maybe two with generational GC). Heap fragmentation is for C++
programmers to fret about. ;)

As for a finalizer allocating memory, I'd sort of assumed an absence
of such questionable code. If there is one, though, it could explain a
thing or two. And demonstrate why finalizers are evil, and should only
ever be used to make sure file handles and such are (eventually)
released and never to do anything more complicated than close a stream
here or null out a reference there.
Mark Space - 09 Jun 2007 01:45 GMT
> Shouldn't be. The thorough GC tried before throwing OOME should
> compact all the surviving objects into one or two contiguous blocks
> (maybe two with generational GC). Heap fragmentation is for C++
> programmers to fret about. ;)

Useful to know, thanks. ^_^  I suppose then that Java references can't
be pointers at all, because moving objects in the heap would invalidate
those pointers.  And going through the code and updating all references
on the fly seems... ugly, to say the least.  Maybe references work
something like handles in the old Mac OS?  Pointers to pointers, where
the second pointer is the thing that gets updated when objects on the
heap are re-allocated or moved.
Stefan Ram - 09 Jun 2007 02:39 GMT
>I suppose then that Java references can't be pointers at all,
>because moving objects in the heap would invalidate those pointers.

     »(...) reference values (...) are pointers«

   JLS3, 4.3.1.

http://java.sun.com/docs/books/jls/third_edition/html/typesValues.html#4.3.1
Twisted - 09 Jun 2007 04:05 GMT
> >I suppose then that Java references can't be pointers at all,
> >because moving objects in the heap would invalidate those pointers.
[quoted text clipped - 4 lines]
>
> http://java.sun.com/docs/books/jls/third_edition/html/typesValues.htm...

Either it uses double indirection, or (more likely) it updates all the
references when it compacts an object. It can do this -- the gc will
have found those references when mapping the object graph and deciding
whether the object was garbage or not.
Arne Vajhøj - 09 Jun 2007 19:32 GMT
>> Shouldn't be. The thorough GC tried before throwing OOME should
>> compact all the surviving objects into one or two contiguous blocks
[quoted text clipped - 8 lines]
> the second pointer is the thing that gets updated when objects on the
> heap are re-allocated or moved.

I think that it is left to the JVM implementation to decide
how is will do it.

Note that it already to go through a lot of stuff to find out
what can be GC'ed.

Possibility of reuse !

Arne
Twisted - 10 Jun 2007 05:16 GMT
On Jun 9, 2:32 pm, Arne Vajh?j <a...@vajhoej.dk> wrote:
> I think that it is left to the JVM implementation to decide
> how is will do it.
[quoted text clipped - 3 lines]
>
> Possibility of reuse !

Certainty of reuse. Sun's VM (the defacto reference implementation)
definitely does do this. With generational GC, it determines if an
object is still live, then copies live objects to a growing contiguous
block of them in memory, which becomes the mature generation or some
such terminology. At the time it copies a particular object it has
pointers to that object's inbound references in memory, from when it
determined its reachability, and on copying it diddles them to point
to the object's new location, presumably while suspending the running
code (so-called "stop the world" gc). It may do incremental GCs that
don't copy objects or "stop the world" depending on settings, with
more thorough, "stop the world" compacting collections when necessary
(due to fragmentation, for instance).
David Gourley - 11 Jun 2007 22:20 GMT
> Shouldn't be. The thorough GC tried before throwing OOME should
> compact all the surviving objects into one or two contiguous blocks
> (maybe two with generational GC). Heap fragmentation is for C++
> programmers to fret about. ;)

But there is one big, big assumption here: that the only cause of OOME
is exhausting the (Java) heap.  Actually this is one of my biggest
annoyances about Java, especially 32-bit implementations.

You can get OOME attempting to create a thread if there isn't memory to
create the thread's stack (which is actually a native memory issue).

You can get OOME from some mixed language classes if the *native* memory
can't get created associated with instances of those classes (there are
some of these in the java library that allocate native memory as well as
Java memory - always close these objects and don't leave for finalisation).

The annoying thing is I've seen situations where OOME is caused by
unfinalized objects with native memory associated which exhaust the
process's address space (without* causing a garbage collect (as garbage
collection is triggered by behaviour of the Java heap, not the overall
address space of the process).  It would be good to have some kind of
setting to trigger a garbage collect if a process's size hit some kind
of threshold as well...

Dave
Twisted - 12 Jun 2007 04:07 GMT
On Jun 11, 5:20 pm, David Gourley <d...@NOSPAM.gourley.plus.com>
wrote:
> The annoying thing is I've seen situations where OOME is caused by
> unfinalized objects with native memory associated which exhaust the
[quoted text clipped - 3 lines]
> setting to trigger a garbage collect if a process's size hit some kind
> of threshold as well...

This is real screwy. The JVM *should* stop the world and do a complete
gc and finalization and repeat gc and finalization until nothing new
shows up as garbage, when it is about to throw OOME *for any reason*,
and then retry the allocation, before then actually throwing OOME.
(This would require, I suppose, JNI code to call a malloc-substitute
that does this stuff behind the scenes and retries before returning
NULL, or in C++ a custom operator-new that does likewise before
throwing bad_alloc. If malloc and new are already substituted with
versions that generate OOME in the JVM automatically on failure in the
JNI environment, then this is (comparatively) trivial. Otherwise it
may well be nontrivial and likely will not be back-compatible with
legacy JNI-using code.)
Arne Vajhøj - 08 Jun 2007 03:28 GMT
> I have an app that, at one point, really bogs down as so many objects are
> created and released in a lengthy process.
[quoted text clipped - 5 lines]
>
> I am on WinXP / Vista and JRE 1.6.x.

It is most likely that the JVM is much better than your code
to determine what is optimal times to GC and that explicit
calls to System.gc will decrease performance.

Have you tried experimenting with the -X and -XX JVM parameters
that controls GC ?

Arne
Roedy Green - 15 Jun 2007 10:57 GMT
>I am wondering if I may not be able to improve performance by System.gc() in
>some "right" places in my code (wherever those might be!). It seems to me
>though, that the gc facilities in Java are so good, that this is something
>best left up to the JVM, and NOT mess with putting System.gc() in anyplace?

Try it.  It might ignore you anyway. At worst it will go slower, and
you take them out.
--
Roedy Green Canadian Mind Products
The Java Glossary
http://mindprod.com
Thomas Schodt - 15 Jun 2007 11:32 GMT
> I have an app that, at one point, really bogs down as so many objects are
> created and released in a lengthy process.
[quoted text clipped - 3 lines]
> though, that the gc facilities in Java are so good, that this is something
> best left up to the JVM, and NOT mess with putting System.gc() in anyplace?

One scenario where you might get a better responsiveness
is calling gc() when a Java GUI application is minimized (or loses focus).

If you don't, imagine the OS swapping the memory out and when you switch
back to the application
one of the first things that happens is the JVM decides it needs to
do a gc run - a lot of that heap must first be swapped back in.


Free Magazines

Get these publications absolutely FREE for up to 12 months. There are no hidden fees and no obligation. Simply choose a title, complete the application form and submit it. Read more ...

Oracle MagazineNetwork ComputingComputer WorldBio-IT WorldeWeekInformation WeekInfosecurity
 
Sign In
Join
My Latest Posts
My Monitored Threads
My Blog
My Photo Gallery
My Profile
My Homepage

Start New Thread
Enable EMail Alerts
Rate this Thread



©2008 Advenet LLC   Privacy Policy - Terms of Use
This website includes both content owned or controlled by Advenet as well as content owned or controlled by third parties.