问题描述
假设我有一个双向链表。我创建它: MyList list = new MyList();
然后,我添加一些节点,使用它,之后决定丢弃旧的列表,如下所示:
list = new MyList();
由于我刚创建了一个新列表,旧内存区域内的节点仍然指向对方。这是否意味着具有旧节点的区域不会被垃圾收集?我需要让每个节点都为空,所以它们是GC'd吗?
不,你不知道。 Java GC处理循环引用就好。
从概念上讲,每次GC运行时,都会查看系统中所有活动的根引用:
- 每个堆栈帧中的局部变量
- this在每个实例方法栈帧中引用
- 实际上,所有静态变量(实际上它们都被
Class
>对象引用,这些对象又被ClassLoader
s,但现在忽略它。)
使用这些已知实时对象,它检查添加到列表中的字段。它递归到那些被引用的对象中,等等,直到找到系统中的每个活动对象。然后垃圾收集它没有被认为是活的所有东西。
您的循环引用节点是相互引用的,但没有活动对象指的是它们,因此它们有资格进行垃圾回收。
请注意,这是一个简洁的 >概念上起作用。实际上,它们非常复杂,具有世代,压缩,并发问题等。
Suppose I have a doubly linked list. I create it as such:
MyList list = new MyList();
Then I add some nodes, use it and afterwards decide to throw away the old list like this:
list = new MyList();
Since I just created a new list, the nodes inside the old memory area are still pointing to each other. Does that mean the region with the old nodes won't get garbage collected? Do I need to make each node point to null so they're GC'd?
解决方案No, you don't. The Java GC handles cyclic references just fine.
Conceptually, each time the GC runs, it looks at all the "live" root references in the system:
- Local variables in every stack frame
- "this" references in every instance method stack frame
- Effectively, all static variables (In fact these are really referenced by
Class
objects, which are in turn referenced byClassLoader
s, but lets ignore that for the moment.)
With those "known live" objects, it examines the fields within them, adding to the list. It recurses down into those referenced objects, and so on, until it's found every live object in the system. It then garbage collects everything that it hasn't deemed to be live.
Your cyclically referenced nodes refer to each other, but no live object refers to them, so they're eligible for garbage collection.
Note that this is a grossly simplified summary of how a garbage collector conceptually works. In reality they're hugely complicated, with generations, compaction, concurrency issues and the like.
这篇关于关于Java垃圾收集的问题的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!