Forcing System.gc()

Discussion in 'Java' started by R. Vince, Jun 7, 2007.

  1. R. Vince

    R. Vince Guest

    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
    R. Vince, Jun 7, 2007
    #1
    1. Advertising

  2. R. Vince

    Eric Sosman Guest

    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.
    >
    > 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?


    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.

    --
    Eric Sosman, Jun 7, 2007
    #2
    1. Advertising

  3. > 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
    Philipp Leitner, Jun 7, 2007
    #3
  4. R. Vince

    Twisted Guest

    On Jun 7, 6:49 pm, Philipp Leitner <> wrote:
    > 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.
    Twisted, Jun 8, 2007
    #4
  5. "Philipp Leitner" <> wrote in message
    news:...
    |> 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.

    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 http://www.iviz.com/
    Matt Humphrey, Jun 8, 2007
    #5
  6. R. Vince wrote:
    > 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.


    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
    =?ISO-8859-1?Q?Arne_Vajh=F8j?=, Jun 8, 2007
    #6
  7. > 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
    Philipp Leitner, Jun 8, 2007
    #7
  8. Philipp Leitner wrote:
    >> 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
    Patricia Shanahan, Jun 8, 2007
    #8
  9. R. Vince

    Lew Guest

    Patricia Shanahan wrote:
    > 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.

    --
    Lew
    Lew, Jun 8, 2007
    #9
  10. "Patricia Shanahan" <> wrote in message
    news:f4bkqf$icv$...
    | Philipp Leitner wrote:
    | >> 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.

    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 http://www.iviz.com/
    Matt Humphrey, Jun 8, 2007
    #10
  11. R. Vince

    Eric Sosman Guest

    Matt Humphrey wrote On 06/07/07 21:19,:
    > "Philipp Leitner" <> wrote in message
    > news:...
    > |> 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.
    >
    > 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.


    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 ...

    --
    Eric Sosman, Jun 8, 2007
    #11
  12. R. Vince

    Mark Space Guest

    Matt Humphrey wrote:

    > 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...
    Mark Space, Jun 8, 2007
    #12
  13. R. Vince

    Twisted Guest

    On Jun 8, 3:33 pm, Mark Space <> wrote:
    > Matt Humphrey wrote:
    > > 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...


    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.
    Twisted, Jun 8, 2007
    #13
  14. R. Vince

    Mark Space Guest

    Twisted wrote:

    >
    > 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.
    Mark Space, Jun 9, 2007
    #14
  15. R. Vince

    Stefan Ram Guest

    Stefan Ram, Jun 9, 2007
    #15
  16. R. Vince

    Twisted Guest

    On Jun 8, 9:39 pm, -berlin.de (Stefan Ram) wrote:
    > Mark Space <> writes:
    > >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.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.
    Twisted, Jun 9, 2007
    #16
  17. Mark Space wrote:
    > Twisted wrote:
    >> 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.


    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
    =?ISO-8859-1?Q?Arne_Vajh=F8j?=, Jun 9, 2007
    #17
  18. R. Vince

    Twisted Guest

    On Jun 9, 2:32 pm, Arne Vajhøj <> wrote:
    > 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 !


    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).
    Twisted, Jun 10, 2007
    #18
  19. Twisted wrote:

    >
    >
    > 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
    David Gourley, Jun 11, 2007
    #19
  20. R. Vince

    Twisted Guest

    On Jun 11, 5:20 pm, David Gourley <>
    wrote:
    > 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...


    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.)
    Twisted, Jun 12, 2007
    #20
    1. Advertising

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

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. mdb
    Replies:
    3
    Views:
    4,154
    =?Utf-8?B?TmVpbA==?=
    Sep 20, 2004
  2. DonQ
    Replies:
    2
    Views:
    900
    Amontec Team, Laurent Gauch
    Feb 28, 2004
  3. Jluis
    Replies:
    7
    Views:
    513
    Just an Illusion
    Jun 11, 2004
  4. Matt North

    'X' - Forcing Unknown

    Matt North, Nov 16, 2004, in forum: VHDL
    Replies:
    2
    Views:
    538
  5. Earl Teigrob
    Replies:
    3
    Views:
    342
    Alvin Bruney [MVP]
    Mar 4, 2004
Loading...

Share This Page