0

Let's suppose I have such code:

public class OuterClass{
    InnerClass myInnerClass = new InnerClass();
    public class InnerClass{

    }
}
// somewhere I have created an OuterClass instance:
OuterClass outerClass = new OuterClass();
// do something
// ...
outerClass = null;

The question: is it enough to set only the outerClass to null to avoid the memory leak? InnerClass has a reference to OuterClass, and OuterClass has a reference to InnerClass. Thus, as both of these objects have references to them, they cannot be garbage collected!

Lev Leontev
  • 2,538
  • 2
  • 19
  • 31
  • 2
    Cyclic references can exist also in other linked data structures, and everything will go okay. _Only issue:_ If an inner class is Serializable also the outer class should be so that `OuterClass.this` will not be null after restoring. – Joop Eggen Mar 08 '19 at 12:49
  • 2
    Have you checked this? https://stackoverflow.com/questions/407855/how-does-java-garbage-collector-handle-self-reference – Balázs Nemes Mar 08 '19 at 12:51
  • Yeah, thanks everybody. I just thought that GC cannot deal with cyclic references – Lev Leontev Mar 08 '19 at 12:52
  • @JoopEggen if the outer class is not serializable, the serialization of an inner class instance will already fail, so you never get to the point of restoring. It would be a different issue with customized `writeObject` methods, but then, the code would *always* fail. But besides that, you should avoid making inner classes serializable in the first place or well, avoid serialization in general. – Holger Mar 11 '19 at 12:53
  • @Holger I once encountered exactly this problem, an `OuterClass.this` being null, and indeed a non-serializable `OuterClass`. But yeah, the compiler should have detected that, so probably something ugly led to that code. Thanks, one worry less. – Joop Eggen Mar 12 '19 at 08:38
  • @JoopEggen the compiler wouldn’t produce an error at this, a warning in the best case if it has an audit for this scenario. But serializing would fail at runtime with the default serialization mechanism. As said, a custom `writeObject` could write the object’s state without trying to serialize the outer object, however, it’s always possible to write a custom `writeObject` method that forgets to write the outer object and, even worse, there is no in-language mechanism to restore the outer object in a `readObject` counterpart anyway (as `OuterClass.this` is not assignable). – Holger Mar 12 '19 at 08:46
  • @Holger I can no longer recall details, just the shock in the debugger. I appreciate the technical explanation. And now there is one wild ghost less swirring around in my dusty atticks. – Joop Eggen Mar 12 '19 at 09:03

1 Answers1

1

If no one else has a reference to that myInnerClass instance, then there is no "leak" (which is a pretty strong word here in the first place).

As long as any live object still has a reference to myInnerClass that inner class instance cannot be garbage-collected (It is after all, still accessible and in use) -- and that inner class instance would also keep its outer class instance alive (as that is indirectly reachable from the inner instance).

This is not different from how the garbage collector works in general. It is not thrown off by reference cycles. It reliably collects the whole cycle when it cannot be reached from a "live root" anymore.

Thilo
  • 257,207
  • 101
  • 511
  • 656