Java 执行“0”后,有多少对象符合垃圾收集条件;m1=零;m2=零&引用;?
执行Java 执行“0”后,有多少对象符合垃圾收集条件;m1=零;m2=零&引用;?,java,garbage-collection,Java,Garbage Collection,执行m1=null后,我很难理解m2=null。有多少对象可以进行垃圾收集 public class MyTest { MyTest m; void show() { System.out.println("Hello this is show method."); } public static void main(String args[]) { MyTest m1 = new MyTest(); MyTes
m1=null后,我很难理解代码>m2=null代码>。有多少对象可以进行垃圾收集
public class MyTest {
MyTest m;
void show() {
System.out.println("Hello this is show method.");
}
public static void main(String args[]) {
MyTest m1 = new MyTest();
MyTest m2 = new MyTest();
MyTest m3 = new MyTest();
m1.m = m2;
m2.m = m3;
m3.m = m1;
m1 = null;
m2 = null;
// Question here: How many objects will be eligible for garbage collection?
}
}
无,因为它们仍然可以通过您在那里通过m3
Zero构建的循环引用访问
对象引用关系图如下所示:
您可以看到,引用是循环的。从main
到m3
的引用使m3
对象保持活动状态。反过来,m3
使m1
保持活动状态,从而使m2
远离GC
请注意,如果将m3
设置为null
,则所有三个对象都将同时符合GC的条件,尽管它们中的每一个都存在循环引用。GC足够聪明,可以找出所有引用都来自符合GC条件的对象,并收集所有三个对象。瞧!GC不会在这里收集任何东西!让我们看看这里到底发生了什么。当您创建MyTest
的m1
、m2
和m3
三个对象时,对象的创建方式如下(假设对象引用id从410开始):
初始化时
m1.m = m2;
m2.m = m3;
m3.m = m1;
这些对象现在看起来像:
m1 MyTest (id=410)
m MyTest (id=412)
m2 MyTest (id=412)
m MyTest (id=414)
m3 MyTest (id=414)
m MyTest (id=410)
m MyTest (id=412)
m MyTest (id=414)
m MyTest (id=410)
.
.
. (This is circular)
但在将m1
和m2
重新初始化为null
后,对象看起来如下所示:
m1 null
m2 null
m3 MyTest (id=414)
m MyTest (id=410)
m MyTest (id=412)
m MyTest (id=414)
m MyTest (id=410)
.
.
.
看,m1
和m2
现在是null
,但它们的引用在m3
中仍然有效 可能所有3个。在/
标记之后没有引用变量,因此优化器有权在此时将它们从框架中删除。您是如何快速绘制的+1从技术上讲,GC不够聪明,无法找出循环引用,但它通过标记GC根中的可访问对象来工作,从而避免了循环引用问题…@Codebender回避问题足够聪明;-)@Codebender实际上,它必须在某种程度上找出循环引用,因为它(可能)遍历整个对象图,并且当它遇到循环时,它的算法不会崩溃。我认为OP的关注点在其他地方!但无论如何,你是对的+我想起了陈雷蒙的优秀文章。但是,我不确定javagc是否有类似的规则。Java规范可能有一个成文的承诺,即不使用根引用收集对象。@Brian:Java在这方面和C#一样聪明。必须强调的是,对对象实例数据的最后一次实际访问不一定是程序顺序中的最后一次访问,因为优化器可能会生成保存寄存器中实际字段值的代码,即使在处理对象数据时也不需要对象。在问题的示例中,没有一个赋值具有实际效果,因此所有对象都可能在创建后立即被收集,或者根本不会被创建。另请参见…m3 to garbage collector“这不是您要查找的两个实例!”@rakeb.mazharul:有趣吗?这个问题的可达性方面是非常简单的,在“三个房子由一个环路中的单向街道连接。我可以从房子a开车到哪一个?”的层次上,如果你想对任何非平凡的垃圾收集程序的内存行为进行推理,这种事情需要是第二天性。优化带来了一些复杂性,但公认的答案甚至没有提到这一点,我怀疑大多数选民是否注意到了这一点。每个答案都是“三”或“零”。这个问题无法回答,因为我们不知道args数组中有多少个对象。人们认为数组及其元素不是对象吗?@EricLippert但m1、m2或m3元素都不在args数组中。并且args数组中的所有元素都是可访问的,所以我看不出args数组如何影响GC的对象数。@taemyr,它们必须可以从活根访问。为什么args还活着?GC可以知道它从未被使用过,因此可能是死的。
m1 null
m2 null
m3 MyTest (id=414)
m MyTest (id=410)
m MyTest (id=412)
m MyTest (id=414)
m MyTest (id=410)
.
.
.