The Artima Developer Community
Sponsored Link

Hmm...

Advertisement

Advertisement

This page contains an archived post to the Design Forum made prior to February 25, 2002. If you wish to participate in discussions, please visit the new Artima Forums.

Message:

Hmm...

Posted by Bill Venners on 13 Jan 1999, 1:59 PM

> I am working on a large java application that has started to suffer from memory leakeage. Upon using a profiling tool I noticed that some classes that I thought should be getting
> garbage collected were not. It appeared that the classes were not being garbage collected because listeners were not being cleared. However, I found it interesting that the classes
> that were not being collected were not in scope. For example, I had the the following:

> Class A contains a member of type Class B. Class A registers itself as a listener of Class B. Likewise, Class B contains a member of Class C, and Class B registers itself as a listener of Class C.

> When I was done with an instance of class A, I assumed all I needed to do to make my instance of class A and it's members candidates for garbage collection was to set my instance of class A to null. However, what I observed was that my instance of class A was garbage collected, but member instances of class B and C were left in memory.

> To eliminate this I was forced in to the following design.

> public class A
> {
> private B myB;

> ...Class A stuff

> public void prepareForGc()
> {
> // Code to remove listeners and any other weak references
> // Then call any other member's prepareForGc()
> myB.prepareForGc();
> }
> }

> public class B
> {
> private C myC;

> ...Class B stuff

> public void prepareForGc()
> {
> // Code to remove listeners and any other weak references
> // Then call any other member's prepareForGc()
> myC.prepareForGc();
> }
> }

> public class C
> {
> private C myC;

> ...Class C stuff

> public void prepareForGc()
> {
> // Code to remove listeners and any other weak references
> // Then call any other member's prepareForGc()
> }
> }

> Each class was responsible for removing listeners and other weak references inside of it's prepareForGc() method. Furthermore, each class needed to call any member's prepareForGc() method to ensure that each appropriate class down the chain was made ready for garbage collection to avoid possible memory leaks.

> In the article on finalization and cleanup one of the suggestions was to create a new method instead of overriding finalize() to handle cleanup. Is my usage of prepareForGc() what the article was suggesting, or have I missed the boat somewhere? This design seems like it could lead to maintenance problems down the road. Is there a better way to get rid of this type of memory leak? Should the JVM do a better job of garbage collecting in this type of scenario? All help and/or advice is highly appreciated.

>
Wierd. Actually, given my understanding of your program, you
shouldn't have to make the prepareForGC() at all. When you
release all references to A, any reference A contained will
no longer be "live." So its reference to B won't cause B to
be kept in memory. B may stay in memory even after A is GC'd,
because B could be referenced from somewhere else or the JVM
could just decide for the heck of it to GC A and not B.

The main question I believe you have is whether you need to
null out references in GCable objects and the answer is
you shouldn't have to do that. I suspect something else was
going on in your program, but I'm afraid I don't have an idea
what that something could be.

Because you have circular references between A, B, and C, if any
one of them is reachable, they'll all be reachable and won't be
available for GC. Perhaps somewhere you have a referece to one
of them?

bv



Replies:

Sponsored Links



Google
  Web Artima.com   
Copyright © 1996-2009 Artima, Inc. All Rights Reserved. - Privacy Policy - Terms of Use - Advertise with Us