ChatGPT解决这个技术问题 Extra ChatGPT

执行“m1=null; m2=null;”后有多少对象符合垃圾回收条件?

执行 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 到垃圾收集器“这不是您要查找的两个实例!”
@rakeb.mazharul:有趣吗?问题的可达性方面非常简单,在“三个房子由单向街道连接成一个循环。我可以从房子 A 开车到哪些?”的水平上。如果您要推理任何重要的垃圾收集程序的内存行为,那么这种事情就需要成为第二天性。由于优化有一些复杂性,但接受的答案甚至没有提到这一点,我怀疑大多数选民都注意到了。
每个答案都说“三”或“零”。这个问题无法回答,因为我们不知道 args 数组中有多少对象。人们是否认为数组及其元素不是对象?
@EricLippert 但是元素 m1,m2 或 m3 都不在 args 数组中。并且 args 数组中的所有元素都是可访问的,所以我看不到 args 数组如何影响可用于 GC 的对象数量。
@taemyr,它们必须可以从活生生的根中访问。为什么args还活着? GC 可以知道它从未被使用过,因此可能已经死亡。

C
Codebender

零。

对象引用图如下所示:

https://i.stack.imgur.com/gcJai.png

可以看到引用是循环的。从 mainm3 的引用使 m3 对象保持活动状态。反过来,m3 使 m1 保持活动状态,从而使 m2 远离 GC。

请注意,如果您将 m3 设置为 null,则所有三个对象都将同时符合 GC 条件,尽管每个对象都存在循环引用。 GC 足够聪明,可以确定所有引用都来自符合 GC 条件的对象,并收集所有三个。


你怎么画得这么快? +1
从技术上讲,GC 不够聪明,无法找出循环引用,但它通过从 GC 根标记可访问对象来工作,因此避免了循环引用问题......
@Codebender 避免这个问题足够聪明;-)
@Codebender实际上它必须在某种程度上找出循环引用,因为它(可能)遍历整个对象图,并且它的算法在遇到循环时不会崩溃。
m
mazhar islam

可能所有 3 个。 // 标记后没有引用任何变量,因此优化器此时有权将它们从框架中删除。


我认为OP的关注点在其他地方!但无论如何你是对的! +1
我想起了 Raymond Chen 的优秀文章,blogs.msdn.com/b/oldnewthing/archive/2010/08/10/10048149.aspx。但是,我不确定 Java GC 是否有类似的规则。 Java 规范可能有一个书面承诺,即不收集具有根引用的对象。
@Brian:在这方面,Java 与 C# 一样聪明。必须强调的是,对对象实例数据的最后一次实际访问不一定是程序顺序中的最后一次访问,因为优化器可能会生成将实际字段值保存在寄存器中的代码,即使在处理其对象时也不需要对象数据。在问题的示例中,没有任何分配具有实际效果,因此所有对象可能在创建后立即被收集,或者从一开始就永远不会被创建。另请参阅finalize() called on strongly reachable object in Java 8
P
Peter Mortensen

瞧! GC 不会在这里收集任何东西!让我们看看这里到底发生了什么。当您创建 MyTestm1m2m3 三个对象时,对象的创建如下所示(假设对象引用 id 从 410 开始):

m1    MyTest  (id=410)
    m    null
m2    MyTest  (id=412)
    m    null
m3    MyTest  (id=414)
    m    null

当你初始化

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)

但是在将 m1m2 重新初始化为 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)
                .
                .
                .

看,m1m2 现在是 null,但它们的引用在 m3 中仍然存在!


A
Aron_dc

无,因为它们仍然可以通过您通过 m3 在那里构建的循环引用访问


关注公众号,不定期副业成功案例分享
关注公众号

不定期副业成功案例分享

领先一步获取最新的外包任务吗?

立即订阅