3

This is an interview question but I'm not quite sure about the correct answer. Suppose we have some classes like:

public class A {
    public Object link;
    public A() {
        link = null;
    }
}

Then we create two instances:

A a1 = new A();
A a2 = new A();
a1.link = a2;
a2.link = a1;

Then we release the references:

a1 = null;
a2 = null;

Then the question is: as JVM would use GC mechanism. How would it handle this case? Will it instantly remove the two instances when it runs or just have the memory space signed and leave them alone? What if I have 1 million such instances that form a cycle and have no external references? Will the cleaning makes the GC thread hang?

NSF
  • 2,499
  • 6
  • 31
  • 55
  • 1
    Short answer: *No, it will not.* (The [standard] JVM is *not* reference counting; it examines *object reachability* only so cycles never cause an issue.) –  Nov 28 '12 at 03:41
  • The standard Java mark and sweep GC will have no trouble with those. – Hot Licks Nov 28 '12 at 03:42
  • See this related question - http://stackoverflow.com/questions/4891133/why-dont-most-jvm-gcs-use-refcounts – maerics Nov 28 '12 at 03:44
  • Well, the second question is actually asking: is the process of removing 1 million of instances in one pass gonna have performance related issue? – NSF Nov 28 '12 at 03:52

3 Answers3

3

The objects themselves can reference eachother with as many links (one million cycles as you mention) as you want. If there is no 'route' back to a thread, the objects are eligible for garbage collection, no matter how many other garbage eligible nodes they connect to.

Now this does not mean they WILL get collected, only that they're eligible. So if your garbage collector decides not to process them, then I suppose that could be considered a memory leak. You can't guarantee they'll disappear.

corsiKa
  • 81,495
  • 25
  • 153
  • 204
2

Cyclical references may cause memory leaks for naive implementations of certain garbage collection strategies such as reference counting. (Which is not to say that reference counting is naive but that poor implementations may suffer from the problem.)

However, this problem is well known to people who implement GCs and it can be avoided. Moreover, most modern JVMs use generational garbage collectors which typically do not suffer from such problems.

maerics
  • 151,642
  • 46
  • 269
  • 291
  • Actually, generational collectors *do* suffer from the problem to a degree. But it's accepted as a performance trade-off. Non-generational mark-and-sweep collectors have no trouble with cycles, though. – Hot Licks Nov 28 '12 at 03:44
  • Nit: Reference counting implementations, like Python, [*can* handle this case as well](http://stackoverflow.com/questions/8025888/does-python-gc-deal-with-reference-cycles-like-this). They can use "cycle detection" to handle such cases. –  Nov 28 '12 at 03:45
0

As per the current logic of code a1 has a member variable which points to a2 and a2 has ha member variable which points to a1. When you do a1 = null a1 becomes eligible for getting GCed. Same is case with a2. Now when GC runs then it tries to see what all objects are reachable starting from root and even though these two refer each other they become unreachable in chain starting from root (case of isolation) hence they get garbage collected without any issues.

Saurabh
  • 7,894
  • 2
  • 23
  • 31
  • a1 isn't eligible for garbage collection when that a1 reference is nulled because there's still a reference to it in a2, and a2 is still attached to the thread. Once a2 is nulled, the objects continue to reference eachother, but because no thread can reach them, they're eligible for garbage collection. So your statement of "When you do a1 = null a1 becomes eligible for getting GCed" is incorrect. – corsiKa Nov 28 '12 at 05:25