Java如何解决垃圾收集中的保留周期?

时间:2014-01-08 11:03:45

标签: java garbage-collection

我知道保留周期(至少在Objective-C和Swift中)是两个对象声称彼此拥有权(他们互相引用)。在Objective-C中,我们可以通过声明其中一个weak来解决问题。

根据我的阅读和理解,Java GC不受保留周期的影响,我们不必担心weak引用。它是如何解决的?

5 个答案:

答案 0 :(得分:23)

Java垃圾收集器通过从对象树的根查找“可到达”对象来工作。如果无法访问它们(如果它们没有外部对象引用),则可以丢弃整个对象图。

基本上它只是遍历树从根节点到叶节点并标记它遇到的所有对象。未被堆中标记对象占用的任何内存被扫描(标记为空闲)。这称为mark and sweep。 img src

Mark and sweep in action

这不能在中轻松完成,因为它使用reference counting,而不是标记和扫描has it's flaws

没有保留周期的原因是因为如果它们没有链接到任何地方的“树”,它们就不会被标记并且可以被丢弃。

答案 1 :(得分:4)

垃圾收集器从根开始查找可到达的对象(通常是:调用堆栈上的变量或全局变量)。因此,如果两个对象相互引用但无法访问,则不会将其标记为“实时”并将被收集。

答案 2 :(得分:0)

  

顾名思义,垃圾收集是指删除对象   它们已不再使用。无论如何,这是一个众所周知的事实   对于其范围对象,Java将对象存储在堆中。因此,如果我们保持   在不清除堆的情况下创建对象时,我们的计算机可能会运行   超出堆空间,我们得到“Out of Memory”错误。垃圾收集   Java中是一种由Java控制和执行的机制   虚拟机(JVM)释放所占用的堆空间   不再使用的物体。与C ++相比,垃圾   java中的集合从内存管理中重温了开发人员   相关活动。 JVM在a的帮助下执行此过程   恶魔线程称为“垃圾收集器”。垃圾收集器   线程首先调用对象的finalize方法。这表演   对所述对象的清理活动。作为开发者,我们不能   强制JVM运行垃圾收集器线程。虽然有   方法,例如Runtime.gc()或System.gc(),但这些都不能保证   垃圾收集器线程的执行。这些方法习惯了   将垃圾收集请求发送到JVM。这取决于Java   虚拟机何时启动垃圾收集过程。

看看这个东西

How Garbage Collection works in Java

答案 3 :(得分:0)

在基本术语中,垃圾收集的工作原理是从多个预定义的根中遍历对象图。任何无法从这些根访问的东西都是垃圾,因此引用另一个对象的一个​​对象是无关紧要的,除非可以从一个或多个根访问它们。

所有这些都在How Garbage Collection Really Works中详细解释。

答案 4 :(得分:0)

跟踪垃圾收集器的行为可以被视为类似于保龄球馆置瓶机的行为,它会自动清扫所有被撞倒的瓶,而不会破坏仍然站立的瓶。置瓶机并没有试图识别被撞倒的瓶,而是抓住所有仍然站立的瓶,将它们从通道中提起,然后在通道表面上运行一个清扫杆,将可能碰巧在那里的所有瓶都清除掉。知道或关心他们在哪里。

跟踪 GC 通过访问一组特定的“根”对象引用(它们被认为总是“可达”)和通过可达对象中保存的引用可达的对象来工作。 GC 会标记这些对象并以某种方式保护它们的内容。一旦所有这些对象都被访问过,系统就会访问一些“特殊”对象(例如弱引用或幻引用的列表,或对具有终结器的对象的引用)和其他可以从它们访问但不能从普通根引用访问的对象,然后将任何未经保护的存储视为有资格重复使用。

系统需要特别处理那些可以从特殊对象到达但不能从普通对象到达的对象,否则就不需要关心有资格收集的“普通”对象。如果一个对象没有终结器并且不是弱引用或幻引用的目标,则 GC 可能会重用其关联的存储,而无需费心查看其中的任何一个。 GC 无需担心无法通过任何根引用访问的一组对象可能持有彼此的引用的可能性,因为即使这些引用存在,GC 也不会费心检查这些引用。