do self references cause memory leaks in Java?

Discussion in 'Java' started by Novice, Jul 14, 2003.

  1. Novice

    Novice Guest

    Hi, I am doing some work with Java and C++ and am curious as to whether self
    references in Java cause memory leaks.

    For example:

    class Test{
    Object foo =this;
    }

    If I instantiate Test, the reference count of any Test object will never
    become zero (as it always keeps a reference to itself) so long as the foo
    variable is never re-assigned.

    Does this present a problem for Java's garbage collection?

    Thanks,
    Novice
     
    Novice, Jul 14, 2003
    #1
    1. Advertising

  2. Novice

    Adam Maass Guest

    "Novice" <> wrote:
    > Hi, I am doing some work with Java and C++ and am curious as to whether

    self
    > references in Java cause memory leaks.
    >
    > For example:
    >
    > class Test{
    > Object foo =this;
    > }
    >
    > If I instantiate Test, the reference count of any Test object will never
    > become zero (as it always keeps a reference to itself) so long as the foo
    > variable is never re-assigned.
    >
    > Does this present a problem for Java's garbage collection?
    >


    Garbage collection in Java does not use reference counting. Rather, most
    simple gc systems use a mark-and-sweep method.

    -- Adam Maass
     
    Adam Maass, Jul 14, 2003
    #2
    1. Advertising

  3. Novice

    Novice Guest

    "Adam Maass" <> wrote in message
    news:...
    |
    | "Novice" <> wrote:
    | > Hi, I am doing some work with Java and C++ and am curious as to whether
    | self
    | > references in Java cause memory leaks.
    | >
    | > For example:
    | >
    | > class Test{
    | > Object foo =this;
    | > }
    | >
    | > If I instantiate Test, the reference count of any Test object will never
    | > become zero (as it always keeps a reference to itself) so long as the
    foo
    | > variable is never re-assigned.
    | >
    | > Does this present a problem for Java's garbage collection?
    | >
    |
    | Garbage collection in Java does not use reference counting. Rather, most
    | simple gc systems use a mark-and-sweep method.
    |

    Is there somewhere I can find this documented?

    The impression I get from the very high level documents I've read on
    java.sun.com's website is:
    "The Java runtime environment has a garbage collector that periodically
    frees the memory used by objects that are no longer referenced."

    So if an object references itself and never stops referencing itself that
    object will always have at least one reference.

    Thanks,
    Novice
     
    Novice, Jul 14, 2003
    #3
  4. Novice

    Novice Guest

    In fact I found this article:
    http://java.sun.com/docs/books/performance/1st_edition/html/JPAppGC.fm.html

    on the sun website and it says that:
    "Circular strong references don't necessarily cause memory leaks."

    This statement doesn't seem to indicate that all objects which are no longer
    referenced (except by themselves) will be removed/deleted.

    In fact, it goes on further to say:
    "although the VM might not actually collect these objects for an indefinite
    amount of time"

    Which to me says that the VM may not remove/delete these objects from memory
    until the VM is shut-down.

    Is there any reason to believe otherwise?

    Thanks,
    Novice
     
    Novice, Jul 14, 2003
    #4
  5. Novice

    Novice Guest

    |
    | The VM might not collect any object for an indefinite amount of time. So
    yes,
    | uncollected objects may remain in memory until the VM is shut down.
    |

    This to me is a problem - I mean server programs would eventually run out of
    memory if they made use of classes with circular dependencies...

    Can anyone provide any clarification on this?

    Or do most people know to try to avoid circular dependencies?

    Thanks,
    Novice
     
    Novice, Jul 14, 2003
    #5
  6. Novice

    Adam Maass Guest

    "Novice" <> wrote:
    > "Adam Maass" <> wrote:
    > |
    > | "Novice" <> wrote:
    > | > Hi, I am doing some work with Java and C++ and am curious as to

    whether
    > | self
    > | > references in Java cause memory leaks.
    > | >
    > | > For example:
    > | >
    > | > class Test{
    > | > Object foo =this;
    > | > }
    > | >
    > | > If I instantiate Test, the reference count of any Test object will

    never
    > | > become zero (as it always keeps a reference to itself) so long as the
    > foo
    > | > variable is never re-assigned.
    > | >
    > | > Does this present a problem for Java's garbage collection?
    > | >
    > |
    > | Garbage collection in Java does not use reference counting. Rather, most
    > | simple gc systems use a mark-and-sweep method.
    > |
    >
    > Is there somewhere I can find this documented?


    OK, this isn't exactly crystal-clear from the specs, but here's the
    definition of an object's lifecycle:

    http://java.sun.com/docs/books/jls/second_edition/html/execution.doc.html#74701

    And here's the definition of the term "reachable," which is part of the
    lifecycle definition:

    http://java.sun.com/docs/books/jls/second_edition/html/execution.doc.html#44762


    The short answer is that an object that refers to itself may be garbage
    collected if there are no references to it from any live thread.

    Java garbage collection does not use (a naive implementation of)
    reference-counting.



    -- Adam Maass
     
    Adam Maass, Jul 14, 2003
    #6
  7. In article <bev5h3$18a$>,
    Novice <> wrote:
    >
    >This to me is a problem - I mean server programs would eventually run out of
    >memory if they made use of classes with circular dependencies...


    The VM will always do garbage collection - and a complete garbage
    collection if necessary - before reporting an out of memory condition.

    The case of not having had anything collected until program shutdown
    will only occur for programs that did not run out of memory during
    execution.

    >Can anyone provide any clarification on this?
    >
    >Or do most people know to try to avoid circular dependencies?


    Circular dependencies aren't a problem. If you're using an
    experimental VM, of course, you might want to make a point out of
    checking its documentation on this point.

    I believe some older VMs did conservative GC, which is a bit of a
    mess.

    Cheers
    Bent D
    --
    Bent Dalager - - http://www.pvv.org/~bcd
    powered by emacs
     
    Bent C Dalager, Jul 14, 2003
    #7
  8. Novice

    Phillip Lord Guest

    >>>>> "Novice" == Novice <> writes:

    Novice> | The VM might not collect any object for an indefinite
    Novice> amount of |time. So yes, uncollected objects may remain in
    Novice> memory until the VM is shut |down.
    Novice> |

    Novice> This to me is a problem - I mean server programs would
    Novice> eventually run out of memory if they made use of classes
    Novice> with circular dependencies...

    Novice> Can anyone provide any clarification on this?

    Novice> Or do most people know to try to avoid circular
    Novice> dependencies?


    No. The JVM does not have to collect objects until it feels it wants
    to. Maybe never.

    However it is required to free all available memory before it throws
    an out of memory error.

    So, for instance, a JVM might choose not to GC until it runs short of
    memory. This makes sense, as GC is expensive. Why do it if you don't
    need to. If you are running out of memory, of course, this is a
    different issue. Then you do need to.

    In short, don't worry about circular dependencies. They will not cause
    the GC problems. And generally don't worry about when objects that are
    our of scope, are actually GC'd. Its an implementation issue, and it
    will differ between JVM's.

    Cheers

    Phil
     
    Phillip Lord, Jul 15, 2003
    #8
  9. Novice

    Ian deSouza Guest

    I think it might be worthwhile talking about the mark-and-sweep GC
    that you had previously mentioned. Mark-and-sweep involves the GC
    first looking at the main program and looking for object references
    there, and "marking" them as valid. It then looks at the references
    that those hold, marking them, and so on.

    After it completes the marking, it then deletes the objects that
    weren't marked, (since it has has a complete list of all the new'ed
    objects), first calling finalize on the objects before removing the
    memory.

    Mark-and-sweep been in place since at least 1.1 (maybe before)..

    "Adam Maass" <> wrote in message news:<>...
    > "Novice" <> wrote:
    > > "Adam Maass" <> wrote:
    > > |
    > > | "Novice" <> wrote:
    > > | > Hi, I am doing some work with Java and C++ and am curious as to

    > whether
    > self
    > > | > references in Java cause memory leaks.
    > > | >
    > > | > For example:
    > > | >
    > > | > class Test{
    > > | > Object foo =this;
    > > | > }
    > > | >
    > > | > If I instantiate Test, the reference count of any Test object will

    > never
    > > | > become zero (as it always keeps a reference to itself) so long as the

    > foo
    > > | > variable is never re-assigned.
    > > | >
    > > | > Does this present a problem for Java's garbage collection?
    > > | >
    > > |
    > > | Garbage collection in Java does not use reference counting. Rather, most
    > > | simple gc systems use a mark-and-sweep method.
    > > |
    > >
    > > Is there somewhere I can find this documented?

    >
    > OK, this isn't exactly crystal-clear from the specs, but here's the
    > definition of an object's lifecycle:
    >
    > http://java.sun.com/docs/books/jls/second_edition/html/execution.doc.html#74701
    >
    > And here's the definition of the term "reachable," which is part of the
    > lifecycle definition:
    >
    > http://java.sun.com/docs/books/jls/second_edition/html/execution.doc.html#44762
    >
    >
    > The short answer is that an object that refers to itself may be garbage
    > collected if there are no references to it from any live thread.
    >
    > Java garbage collection does not use (a naive implementation of)
    > reference-counting.
    >
    >
    >
    > -- Adam Maass
     
    Ian deSouza, Jul 15, 2003
    #9
  10. Novice

    Roedy Green Guest

    On Mon, 14 Jul 2003 17:01:33 -0400, "Novice" <>
    wrote or quoted :

    >This to me is a problem - I mean server programs would eventually run out of
    >memory if they made use of classes with circular dependencies...


    You are imagining Java gc works by reference counting where circular
    references are a problem. See
    http://mindprod.com/jgloss/reference.html and
    http://mindprod.com/jgloss/garbagecollection.html
    for how Java's mark sweep or generational gc works.

    --
    Canadian Mind Products, Roedy Green.
    Coaching, problem solving, economical contract programming.
    See http://mindprod.com/jgloss/jgloss.html for The Java Glossary.
     
    Roedy Green, Jul 16, 2003
    #10
  11. Novice

    Doug Pardee Guest

    "Steve Horsley" <_SPAM.net> wrote:
    > A full Garbage Collection will only run when the VM doesn't have enough
    > memory to create a new Object when required. A short-lived program or a
    > program that dives into a tight loop without creating and discarding many
    > objects may never trigger a full GC.


    This is only true for certain environments.

    The JVM specification declares that the behavior of the garbage
    collector is not defined, and the JVM implementor has a free hand. The
    only requirements are that there be a garbage collector, and that it
    make its best effort to reclaim memory before throwing the
    OutOfMemoryError.

    Most of us are using Sun JVMs, and Sun has documented their GCs fairly
    well. It's worth the trip to the Sun Web site to read the facts,
    rather than relying on conjecture.

    Modern Sun JVMs use multiple heaps, with separate garbage collectors
    on each. These typically DO run on an as-needed basis, but in many
    cases a "full GC" is never triggered even in a program that creates
    and discards many objects.

    On the other hand, if you're using RMI, the Distributed Garbage
    Collector will force a "full GC" on a regular basis. By default, the
    DGC triggers a full garbage collection every 60 seconds.

    > This is why finalize() cannot be
    > relied on to clean up resources - the program may terminate normally
    > without the finalizers ever running.


    Again, not *necessarily* true. It is true for the default situation,
    but if you call System.runFinalizersOnExit(true) at some point, the
    finalizers will always be executed. Heh... unless someone calls
    System.runFinalizersOnExit(false) after you've called it with "true"
    :)
     
    Doug Pardee, Jul 16, 2003
    #11
  12. Novice

    Doug Pardee Guest

    (Ian deSouza) wrote:
    > I think it might be worthwhile talking about the mark-and-sweep GC
    > that you had previously mentioned.
    > [snip]
    > Mark-and-sweep been in place since at least 1.1 (maybe before)..


    Historically, Sun JVMs have not used mark-and-sweep GCs.

    The older Sun JVMs used mark-and-compact. The difference is that
    mark-and-sweep leaves a checkerboarded heap.

    Modern Sun JVMs (since 1.2.something) use multiple heaps, divided into
    two generations for user objects and a third generation for system
    objects. The two user generations use separate garbage collectors. The
    young generation uses a single-pass "copying" garbage collector: all
    live objects are copied from Eden and the current survivor space into
    the new survivor space and possibly the tenured generation, and then
    Eden and the current survivor space are declared empty, and the new
    survivor space becomes the current survivor space. The tenured
    generation uses mark-and-compact.

    As of 1.4.1, Sun's JVMs have added some additional GC options, one of
    which is a low-latency, mostly concurrent, mark-and-sweep GC for the
    tenured generation. Its operation is a six-phase process that is a
    *bit* more complicated than an ordinary mark-and-sweep. See the FAQ
    reference below.

    A couple of useful references:
    http://java.sun.com/docs/hotspot/gc1.4.2/faq.html
    http://java.sun.com/docs/hotspot/gc1.4.2/
     
    Doug Pardee, Jul 16, 2003
    #12
  13. Novice

    S. Balk Guest

    > Hi, I am doing some work with Java and C++ and am curious as to whether
    self
    > references in Java cause memory leaks.
    >
    > For example:
    >
    > class Test{
    > Object foo =this;
    > }
    >
    > If I instantiate Test, the reference count of any Test object will never
    > become zero (as it always keeps a reference to itself) so long as the foo
    > variable is never re-assigned.
    >
    > Does this present a problem for Java's garbage collection?


    why don't you stress-test this little class by generating trillions of
    objects, and watch the GC-log
     
    S. Balk, Jul 16, 2003
    #13
  14. Novice

    Roedy Green Guest

    On Wed, 16 Jul 2003 10:44:22 +0200, "S. Balk"
    <0spam.nl> wrote or quoted :

    >watch the GC-log


    how would he to that?

    --
    Canadian Mind Products, Roedy Green.
    Coaching, problem solving, economical contract programming.
    See http://mindprod.com/jgloss/jgloss.html for The Java Glossary.
     
    Roedy Green, Jul 16, 2003
    #14
  15. On Tue, 15 Jul 2003 21:47:11 -0700, Doug Pardee wrote:

    > "Steve Horsley" <_SPAM.net> wrote:


    >> This is why finalize() cannot be
    >> relied on to clean up resources - the program may terminate normally
    >> without the finalizers ever running.

    >
    > Again, not *necessarily* true. It is true for the default situation,
    > but if you call System.runFinalizersOnExit(true) at some point, the
    > finalizers will always be executed. Heh... unless someone calls
    > System.runFinalizersOnExit(false) after you've called it with "true"
    > :)


    runFinalizerdOnExit() is deprecated as "inherently unsafe".

    Steve
     
    Steve Horsley, Jul 16, 2003
    #15
  16. Novice

    S. Balk Guest

    > >watch the GC-log
    >
    > how would he to that?


    by using java -verbose:gc



    another way is to set the maximum amount of allocatable memory to a very low
    value, for example 2MB, then create 4 million objects with references to
    itself and wait for an OutOfMemoryError, although this is a quite dirty way
    of testing ofcourse
     
    S. Balk, Jul 17, 2003
    #16
  17. : I ran this through JProfiler (anybody want to fund me so I can buy a
    : license? I'm still doing backpayments on my 20' plasma tv).

    Use a free profiler instead or keep switching between optimizeit, jprobe and
    jprofiler.

    : class SelfReferent
    : {
    : Object refrerer;
    : SelfReferent(Object referent)
    : {
    : referer = referent;
    : }
    : }

    Ok, this code does not compile, refrerer is mispelled. So obviously this
    is not the code you used.

    : If I run this test, and call System.gc() manually on JProfile, there are
    : still 8 allocations left on the heap (240 bytes). While this doesn't
    : seem serious, it is a problem if such code is present in a long-running
    : server process. This is reproducible.

    If I fix your spelling error and run it with jdk/1.4.2 and my profiler, jmp,
    I see that my jvm does not call GC before the test is over so I have
    1000 instances of SelfReferent and 1000 instances of SelfReference.
    After calling GC all of them dissapears. So my jvm does seem to handle this
    case in a good way.

    (to test this I added a System.in.read (); in main, after the call to test).

    : So I must say that self references aren't a problem, but circular
    : dependencies are.

    Self references are not a problem, neither is circular references.
    As someone already said, can you be sure that jprofiler-GC does a
    full GC.
    Also: when did you get the numbers? your test case exits very quickly so
    had the GC been completed before your jvm was shut down?

    /robo
     
    Robert Olofsson, Jul 17, 2003
    #17
  18. In article <>,
    dhek bhun kho <> wrote:
    >> Do you have reason to believe that JProfile's manual GC does a
    >> complete GC?

    >
    >Yes. The manual states it, according to the manual they use JVMPI to
    >interact with the JVM. Or I might have found a 'bug' in their software. I
    >tried sample sizes from 10-10000; and keep getting a few left over
    >objects. This does not happen if I use the non-circular dependent version.


    I'm not familiar with JVMPI so I'll just assume they know what they're
    talking about <g>

    >What am I doing wrong?


    Nothing that I can think of.

    >> Also, your program should be terminating long before you have any
    >> chance of running a manual GC. Are you sure you're not just looking at
    >> a static heap image representing the state your program was in as it
    >> was about to terminate?

    >
    >I don't think so. The profiler keeps the VM alive after the main method
    >exits.


    Does it do this in some mystical magical way or has it just fired up
    its own non-daemon thread to keep it all ticking merrily on? If it's
    magical, that might affect how things are collected (or not) I
    suppose.

    >If I do not call gc() manually (of which I do not know how it is really
    >invoked, would have to check JVMPI documentation) then _all_
    >allocations are still visible (after the main method has finished). This
    >happens with both versions of the minimal test code.
    >
    >When I do call the gc() method, all allocations disappear for the self
    >referring version and for the circular dependent one a few allocations are
    >still there. When I wrap the object referred to by the new call within a
    >SoftReference object, no allocations remain after calling the garbage
    >collector through the profiler.


    I'm out of ideas then.

    >I must admit that this is not the most ideal and idealistic test at all.
    >Do you know by chance, how to 100% certain? TIA.


    I have generally accepted that garbage collection is (apparantly)
    non-deterministic and that however much I try to threaten it or yell
    at it, it will still collect in its own good time. I tend to use
    OptimizeIt to track down memory leaks and find my efforts constantly
    frustrated by the fact that even when I have correctly unregistered
    all my listeners, diposed all my windows, etc., it will still take up
    to several minutes for the GC to catch on - even after hitting the
    "collect" button in the profiler.

    I don't really know how to get around this. Try to let the thing sit
    for a couple of hours before checking on it again I suppose :)

    Cheers
    Bent D
    --
    Bent Dalager - - http://www.pvv.org/~bcd
    powered by emacs
     
    Bent C Dalager, Jul 17, 2003
    #18
  19. In article <bf5gmq$hda$>,
    Robert Olofsson <> wrote:
    >: I ran this through JProfiler (anybody want to fund me so I can buy a
    >: license? I'm still doing backpayments on my 20' plasma tv).
    >
    >Use a free profiler instead or keep switching between optimizeit, jprobe and
    >jprofiler.


    Are you aware of any decent free ones?

    >If I fix your spelling error and run it with jdk/1.4.2 and my profiler, jmp,
    >I see that my jvm does not call GC before the test is over so I have
    >1000 instances of SelfReferent and 1000 instances of SelfReference.
    >After calling GC all of them dissapears. So my jvm does seem to handle this
    >case in a good way.


    Did you fix the "this"-bug in order to get circular references?

    Cheers
    Bent D
    --
    Bent Dalager - - http://www.pvv.org/~bcd
    powered by emacs
     
    Bent C Dalager, Jul 17, 2003
    #19
  20. (Bent C Dalager), Thu, 17 Jul 2003 07:17:03 +0000:

    > In article <bf5gmq$hda$>,
    > Robert Olofsson <> wrote:
    >>: I ran this through JProfiler (anybody want to fund me so I can buy a
    >>: license? I'm still doing backpayments on my 20' plasma tv).
    >>
    >>Use a free profiler instead or keep switching between optimizeit, jprobe and
    >>jprofiler.

    >
    > Are you aware of any decent free ones?


    None. Are you aware of any decent free ones? :)

    >>If I fix your spelling error and run it with jdk/1.4.2 and my profiler, jmp,


    Jmp? Which one is that?

    >>I see that my jvm does not call GC before the test is over so I have
    >>1000 instances of SelfReferent and 1000 instances of SelfReference.
    >>After calling GC all of them dissapears. So my jvm does seem to handle this
    >>case in a good way.


    Thanks for running the test case.

    The JProfiler automatically starts the memory profiling while launching
    the JVM. It overrides the system.exit() and keeps the main thread alive
    (how I do not know, it could be an extra thread or blocking i/o). Because
    gc() is not called before the VM exits, all allocations are still there
    and only 'vanish'/' freed' when I hit gc() manually through the profiler.

    I'm starting to think that the results I found are an artifact. I would
    have to test it again on another profiler just to be sure. I'm using the
    1.4.1_03 version. On the other hand : 240 bytes won't kill a server.

    Greets
    Bhun.
     
    dhek bhun kho, Jul 17, 2003
    #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. Ralf W. Grosse-Kunstleve
    Replies:
    16
    Views:
    612
    Lonnie Princehouse
    Jul 11, 2005
  2. Ralf W. Grosse-Kunstleve
    Replies:
    18
    Views:
    613
    Bengt Richter
    Jul 11, 2005
  3. Ralf W. Grosse-Kunstleve
    Replies:
    2
    Views:
    421
    Dan Sommers
    Jul 12, 2005
  4. falcon
    Replies:
    0
    Views:
    397
    falcon
    Jul 31, 2005
  5. Replies:
    6
    Views:
    549
Loading...

Share This Page