简体   繁体   English

SCJP 模拟问题:有多少对象有资格进行垃圾回收?

[英]SCJP Mock Question: How many objects are eligible for garbage collection?

I was asked a question (on this site http://scjptest.com/ ): How many objects are eligible for garbage collection in this code sample at the line // some code goes here?有人问我一个问题(在此站点http://scjptest.com/ 上):在此代码示例中,有多少对象符合垃圾回收条件,位于 // some code goes here?

class A {
    private B b;
    public A() {
        this.b = new B(this);
    }
}

class B {
    private A a;
    public B(A a) {
        this.a = a;
    }
}

public class Test { 
    public static void main(String args[]) {
        A aa = new A();
        aa = null;
        // some code goes here
    }
}

The correct answer is: "The objects referenced by a and b are eligible for garbage collection.".正确答案是:“a 和 b 引用的对象符合垃圾回收条件。”。 But why?但为什么? they contain loop references to each other, they are accessible to each other.它们包含相互的循环引用,它们可以相互访问。

Thank you!谢谢!

they contain loop references to each other, they are accessible to each other.它们包含相互的循环引用,它们可以相互访问。

Yes, but they aren't anymore accessible from anywhere else, so they can't be seen and used in the program anymore.是的,但它们不再可以从其他任何地方访问,因此无法再在程序中看到和使用它们。

Early GCs had problems collecting such self-referencing object groups but with modern generational collectors it is a solved problem.早期的 GC 在收集此类自引用 object 组时存在问题,但对于现代世代收集器来说,这是一个已解决的问题。

In brief, the GC can walk through the web of references from the known static and stack objects, and either简而言之,GC 可以遍历来自已知 static 和堆栈对象的引用的 web,以及

  • copy all objects found to a new memory pool, automatically leaving behind any "dead" objects (this is the "young generation" strategy), or将找到的所有对象复制到新的 memory 池中,自动留下任何“死”对象(这是“年轻一代”策略),或者
  • mark all objects found, so that once the whole web of references is walked traversed, it can delete all unmarked objects (this is the "old/tenured generation" strategy).标记找到的所有对象,这样一旦遍历了整个 web 引用,它就可以删除所有未标记的对象(这是“老/老一代”策略)。

That's because java has a generational garbage collector so it can collect groups of objects that have references between them, but not from the main application.那是因为 java 有一个分代垃圾收集器,因此它可以收集在它们之间有引用的对象组,但不能从应用程序收集。

There is a more in depth explanation here .这里有更深入的解释。

As far as I remember (and I might be wrong) this wasn't the case with old versions of java (such as java 1.2), in which the cyclic dependencies had to be cleared manually in order for the GC to collect them.据我记得(我可能错了),旧版本的 java(例如 java 1.2)并非如此,其中必须手动清除循环依赖项才能让 GC 收集它们。

The GC can remove so called "island of objects" if none of the objects from that "island" (or group) cannot be accessed from any thread !如果无法从任何线程访问该“岛”(或组)中的任何对象,GC 可以删除所谓的“对象岛”!

In your example you create an object A that has link to another object B. But the object B is not "reference-able" by anyone expect A. You can view the two objects as an island.在您的示例中,您创建了一个 object A 链接到另一个 object B。但是 object B 不是任何人都可以“引用”的 A。您可以将这两个对象视为一个岛。 When A is gone, GC will be smart enough to figure out that B cannot be referenced by any other thread and thus you will have 2 objects being removed.当 A 消失时,GC 将足够聪明地确定 B 不能被任何其他线程引用,因此您将删除 2 个对象。

let's draw the scenario to understand clearly.让我们绘制场景以清楚地理解。

A a = new A() 

a ------------this points to object------------> A() "1st object" a ------------this 指向对象------------> A() "第一个对象"

in A()'s constructor you instantiate an instance of B() "2nd object"在 A() 的构造函数中,您实例化 B()“第二个对象”的实例

inside the class B instance is just pointing to the A() above, so no new object created. class B 实例内部只是指向上面的 A(),因此没有创建新的 object。 At the point you assigned a null value to "a" variable, no reference will be pointing to A() object.在您将 null 值分配给“a”变量时,没有引用将指向 A() object。 Now you have 2 objects eligible for GC.现在您有 2 个符合 GC 条件的对象。 Don't worry about the class referencing each other, just focus on the declaration inside your main method.不要担心 class 相互引用,只需关注 main 方法中的声明。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM