关于我的 OCA 考试的垃圾收集问题

Question about Garbage Collection for my OCA Exam

class CardBoard {
    Short story = 200;

    CardBoard go(CardBoard cb){
        cb = null;
        return cb;
    }

    public static void main(String[] args){
        CardBoard c1 = new CardBoard();
        CardBoard c2 = new CardBoard();
        CardBoard c3 = c1.go(c2);
        c1 = null;
// When this line is reached, what is eligible for the GC.
    }
}

有人可以解释一下这里发生了什么吗?我了解 c1Short 有资格使用垃圾收集器。但是 c2 会发生什么,为什么 c3 也不能用呢?我可能会在这里监督一些事情,但我很高兴能够帮助我解决这个话题的每一个输入。我的 OCA 考试是下周,我仍然对这些东西感到困扰。

编辑:符合 GC 条件的评论。

考虑到 Java 是按值传递,我们知道 Java 不是传递对象,而是传递对象的引用。

因此,当您执行 CardBoard c3 = c1.go(c2); 时,方法 go(Cardboard cb) 只是将 c2 的引用值复制到 cb,因此 c2 不会受到 cb = null; 的伤害。因此,c2 不符合 GC 的条件。

c3 永远不会被构造为一个对象,它只是一个初始化为 null 的 CardBoard 类型的变量。因此,它不能被垃圾收集,因为它甚至没有在堆上创建。

也许可视化所涉及的对象会有所帮助。在 main 中的第一条语句之后,我们有:

         +-----------+        +-------+
         | CardBoard |   ---> | Short |
c1 ----> |-----------|  /     |-------|
         |  story    | /      |  200  |
         +-----------+        +-------+

在 main 中的第二个语句之后,我们有:

         +-----------+        +-------+
         | CardBoard |   ---> | Short |
c1 ----> |-----------|  /     |-------|
         |  story    | /      |  200  |
         +-----------+        +-------+

         +-----------+        +-------+
         | CardBoard |   ---> | Short |
c2 ----> |-----------|  /     |-------|
         |  story    | /      |  200  |
         +-----------+        +-------+

(理论上也有可能是两个CardBoard共享了Short对象,Short.valueOf的Javadoc说:

This method will always cache values in the range -128 to 127, inclusive, and may cache other values outside of this range.

但是,JDK 实现仅在 -128 到 127 范围内缓存,因此我们将假设继续前进)

进入 go() 方法后,我们有:

         +-----------+        +-------+
         | CardBoard |   ---> | Short |
c1 ----> |-----------|  /     |-------|
         |  story    | /      |  200  |
         +-----------+        +-------+

         +-----------+        +-------+
         | CardBoard |   ---> | Short |
c2 ----> |-----------|  /     |-------|
     --> |  story    | /      |  200  |
    /    +-----------+        +-------+
   / 
  /
cb

在离开 go() 之前,我们有:

         +-----------+        +-------+
         | CardBoard |   ---> | Short |
c1 ----> |-----------|  /     |-------|
         |  story    | /      |  200  |
         +-----------+        +-------+

         +-----------+        +-------+
         | CardBoard |   ---> | Short |
c2 ----> |-----------|  /     |-------|
         |  story    | /      |  200  |
         +-----------+        +-------+
    
  
cb --x    

在 main 中的第 3 个语句之后,我们有:

         +-----------+        +-------+
         | CardBoard |   ---> | Short |
c1 ----> |-----------|  /     |-------|
         |  story    | /      |  200  |
         +-----------+        +-------+

         +-----------+        +-------+
         | CardBoard |   ---> | Short |
c2 ----> |-----------|  /     |-------|
         |  story    | /      |  200  |
         +-----------+        +-------+
    

c3 --x

在离开 main() 之前,我们有:

         +-----------+        +-------+
         | CardBoard |   ---> | Short |
c1 -x    |-----------|  /     |-------|
         |  story    | /      |  200  |
         +-----------+        +-------+

         +-----------+        +-------+
         | CardBoard |   ---> | Short |
c2 ----> |-----------|  /     |-------|
         |  story    | /      |  200  |
         +-----------+        +-------+
    

c3 -x    

正如我们所见,在分配的 4 个对象中,2 个保持可达,2 个符合回收条件。