How does Java Garbage Collection work with Circular References?

From my understanding, garbage collection in Java cleans up some object if nothing else is 'pointing' to that object.

My question is, what happens if we have something like this:

class Node {
    public object value;
    public Node next;
    public Node(object o, Node n) { value = 0; next = n;}
}

//...some code
{
    Node a = new Node("a", null), 
         b = new Node("b", a), 
         c = new Node("c", b);
    a.next = c;
} //end of scope
//...other code

a , b , and c should be garbage collected, but they are all being referenced by other objects.

How does the Java garbage collection deal with this? (or is it simply a memory drain?)


Java's GC considers objects "garbage" if they aren't reachable through a chain starting at a garbage collection root, so these objects will be collected. Even though objects may point to each other to form a cycle, they're still garbage if they're cut off from the root.

See the section on unreachable objects in Appendix A: The Truth About Garbage Collection in Java Platform Performance: Strategies and Tactics for the gory details.


yes Java Garbage collector handles circular-reference!

How?

There are special objects called called garbage-collection roots (GC roots). These are always reachable and so is any object that has them at its own root.

A simple Java application has the following GC roots:

  • Local variables in the main method
  • The main thread
  • Static variables of the main class
  • 在这里输入图像描述

    To determine which objects are no longer in use, the JVM intermittently runs what is very aptly called a mark-and-sweep algorithm . It works as follows

  • The algorithm traverses all object references, starting with the GC roots, and marks every object found as alive.
  • All of the heap memory that is not occupied by marked objects is reclaimed. It is simply marked as free, essentially swept free of unused objects.
  • So if any object is not reachable from the GC roots(even if it is self-referenced or cyclic-referenced) it will be subjected to garbage collection.

    Ofcourse sometimes this may led to memory leak if programmer forgets to dereference an object.

    在这里输入图像描述

    Source : Java Memory Management


    A garbage collector starts from some "root" set of places that are always considered "reachable", such as the CPU registers, stack, and global variables. It works by finding any pointers in those areas, and recursively finding everything they point at. Once it's found all that, everything else is garbage.

    There are, of course, quite a few variations, mostly for the sake of speed. For example, most modern garbage collectors are "generational", meaning that they divide objects into generations, and as an object gets older, the garbage collector goes longer and longer between times that it tries to figure out whether that object is still valid or not -- it just starts to assume that if it has lived a long time, chances are pretty good that it'll continue to live even longer.

    Nonetheless, the basic idea remains the same: it's all based on starting from some root set of things that it takes for granted could still be used, and then chasing all the pointers to find what else could be in use.

    Interesting aside: may people are often surprised by the degree of similarity between this part of a garbage collector and code for marshaling objects for things like remote procedure calls. In each case, you're starting from some root set of objects, and chasing pointers to find all the other objects those refer to...

    链接地址: http://www.djcxy.com/p/27154.html

    上一篇: Python垃圾收集器文档

    下一篇: Java垃圾收集如何与循环引用一起工作?