Java 符合垃圾收集条件的对象
这个问题是从我这里提出来的。有多少对象符合垃圾收集的条件 根据凯西·塞拉的回答,它是Java 符合垃圾收集条件的对象,java,scjp,Java,Scjp,这个问题是从我这里提出来的。有多少对象符合垃圾收集的条件 根据凯西·塞拉的回答,它是C。这意味着有两个对象可以进行垃圾收集。我已经解释了答案。但是为什么c3不符合(GC)条件 当到达//Do stuff时,有多少对象符合GC条件 A:0 B:1 C:2 D:编译失败 E:不可能知道 F:在运行时引发异常 答复: C是正确的。只有一个纸板对象(c1)符合条件,但它有一个关联的Shortwrapper对象也符合条件 A、 基于上述情况,B、D、E和F不正确。(目标7.4) c3为null,因此
C
。这意味着有两个对象可以进行垃圾收集。我已经解释了答案。但是为什么c3
不符合(GC)条件
当到达//Do stuff
时,有多少对象符合GC条件
- A:0
- B:1
- C:2
- D:编译失败
- E:不可能知道
- F:在运行时引发异常
- C是正确的。只有一个纸板对象(c1)符合条件,但它有一个关联的
wrapper对象也符合条件Short
- A、 基于上述情况,B、D、E和F不正确。(目标7.4)
c3
为null
,因此那里显然没有符合垃圾收集条件的对象
请注意,只创建了两个硬纸板
对象,这两个对象位于以下行:
CardBoard c1 = new CardBoard();
CardBoard c2 = new CardBoard();
在引用杂耍之后,其中只有一个没有引用。从来没有
c3
指向的对象。构造函数只被调用了两次,两个对象,一个由c1
和c2
指向c3
只是一个引用,除了空指针外,它从未被分配过任何东西
当前指向null的引用c3
,不会超出范围并从堆栈中移除,直到主方法末尾的右括号被交叉
最初分配给
c1
的对象无法访问,因为c1
引用被设置为null,但是c2
引用尚未更改,因此分配给它的对象仍然可以通过c2
引用从此范围访问。如果您注意到代码中只创建了两个对象。c3从未初始化为对象,它是空引用。因此,只有一个“对象”符合垃圾收集的条件。让我们逐行分解:
CardBoard c1 = new CardBoard();
我们现在有两个对象,硬纸板
c1
指向和短
c1.story
。这两种方法都不适用于GC,因为c1
指向carboard
和carboard
变量的story
指向Short
CardBoard c2 = new CardBoard();
与上面类似,我们现在有四个对象,没有一个可用于GC
CardBoard c3 = c1.go(c2);
我们调用由c1
指向的纸板上的方法go,传递c2
的值,该值是对纸板
对象的引用。我们将参数设为null,但Java是按值传递的,这意味着c2
变量本身不受影响。然后返回空参数<代码>c3为空
,c1
和c2
不受影响。我们仍然有4个对象,没有一个可以被GC'd
c1 = null;
我们为空
c1
。先前指向的CardBoard
对象现在没有指向它的任何对象,可以对其进行GC。因为CardBoard
对象中的story
变量是指向Short
的唯一对象,并且因为CardBoard
对象符合GC的条件,所以Short
也符合GC的条件。这给了我们4个对象,其中2个可以是GC'd。符合GC条件的对象是以前由c1
和c1引用的对象。story
形式上正确的答案是我们不知道。我们不知道的原因是这句话:
Short story = 200;
这将编译为以下字节码:
CardBoard();
Code:
0: aload_0
1: invokespecial #1 // Method java/lang/Object."<init>":()V
4: aload_0
5: sipush 200
8: invokestatic #2 // Method java/lang/Short.valueOf:(S)Ljava/lang/Short;
11: putfield #3 // Field story:Ljava/lang/Short;
14: return
更新:for
Short.valueOf()
比我引用的1.8版本更神秘,但同样的逻辑适用:仅仅通过查看代码无法判断是否将返回Short
的新实例或缓存实例。严格来说c3
不符合GC条件,因为它不是一个对象。这是一个可以指向某个对象的变量。正确的答案是……有趣的是,有这么多的教程和练习讨论这类事情,但都是错误的。事实是,JVM根本不知道局部变量的范围。在过去,这通常意味着一些引用尽管超出范围,但没有被清除。今天,您可能会惊讶于这样一个事实:尽管对象“在范围内”,但它仍然被收集,请看…1)问题是关于java 6 2)如果不知道“//do stuff”可能包含什么内容,就无法推测编译器可能会对c2的未来可达性得出什么优化结论。java 6和java 8之间的规则没有改变。您甚至不能排除在实际的Java6实现中会发生这样的事情,只是,到目前为止还没有讨论过。如果您假设//do stuff
可能包含与可达性相关的操作,那么正确的答案是问题不完整。这更证明了,这样的问题是多么毫无意义…
CardBoard();
Code:
0: aload_0
1: invokespecial #1 // Method java/lang/Object."<init>":()V
4: aload_0
5: sipush 200
8: invokestatic #2 // Method java/lang/Short.valueOf:(S)Ljava/lang/Short;
11: putfield #3 // Field story:Ljava/lang/Short;
14: return
Short story = new Short(200);