Java 用于垃圾回收的对象数
鉴于:Java 用于垃圾回收的对象数,java,object,inheritance,garbage,Java,Object,Inheritance,Garbage,鉴于: 接口动物{void makeNoise();} 马类器具{ 长重=1200L; public void makeNoise(){System.out.println(“whinny”);} } 公共级冰岛马{ public void makeNoise(){System.out.println(“vinny”);} 公共静态void main(字符串[]args){ 冰岛语i1=新冰岛语(); 冰岛语i2=新冰岛语(); 冰岛语i3=新冰岛语(); i3=i1;i1=i2;i2=null
接口动物{void makeNoise();}
马类器具{
长重=1200L;
public void makeNoise(){System.out.println(“whinny”);}
}
公共级冰岛马{
public void makeNoise(){System.out.println(“vinny”);}
公共静态void main(字符串[]args){
冰岛语i1=新冰岛语();
冰岛语i2=新冰岛语();
冰岛语i3=新冰岛语();
i3=i1;i1=i2;i2=null;i3=i1;//重要的东西在这里
interface Animal { void makeNoise(); }
class Horse implements Animal {
Long weight = 1200L;
public void makeNoise() { System.out.println("whinny"); }
}
public class Icelandic extends Horse {
public void makeNoise() { System.out.println("vinny"); }
public static void main(String[] args) {
Icelandic i1 = new Icelandic();
Icelandic i2 = new Icelandic();
Icelandic i3 = new Icelandic();
i3 = i1; i1 = i2; i2 = null; i3 = i1; //<-- line 14
}
}
因此,i3
立即失去其引用,因此原始对象已准备好收集
i1
和i3
参考i2
因此i1s原始对象已准备好收集
然后,i2
将丢失其引用,因此所有3个都为null并被垃圾收集
我个人同意3。这是一个非常发人深省的问题。所以每个对象都有一个长对象,所以当每个冰岛对象都被标记为垃圾收集时,它指向的Long
值也是如此。因此:
Icelandic i1 = new Icelandic();
Icelandic i2 = new Icelandic();
Icelandic i3 = new Icelandic();
i3 = i1; i1 = i2; i2 = null; i3 = i1;
原始i3对象丢失,原始i1值丢失。i1和i3都指向原始i2,使其保持活动状态(i2指向null,使其不活动)。这将留下2个对象标记为垃圾收集(原始i1和原始i3)以及它们指向的Long
值,为您提供了4个标记为垃圾收集的项。在第14行之后,只有原始i2对象处于活动状态,没有指向原始i1和i3的引用,因此它们符合垃圾收集器的条件,并且该对象有一个基类型,一个长字段,将其丢失到,因此2*2=4;
我会选择冰岛的2个对象(对象1和对象3)。
因为每个冰岛人都持有一个长对象,它给了我们4。这个问题,特别是坚持4这个特定的“正确”答案,没有多大意义,因为它对JVM如何工作提出了一些假设,这些假设在最好的情况下是幼稚的,或者根本是错误的
它做错的第一件事是假设知道有多少对象被创建过
main
方法创建了三个Icelandic
实例,其中继承的字段weight
初始化为1200L
值。该值1200L
通过使用允许但不需要频繁缓存请求的方法自动装箱转换为Long
实例因此,我们无法预测此处创建的Long
实例的数量,可能是一个或三个,但如果缓存不适用于所有调用,无论出于何种原因,甚至可能是两个
然后,代码将处理包含这三个实例的局部变量,并假定“after”只包含其中一个实例第14行但是在该行之后没有关联的代码,该状态可能与之相关。该行之后发生的唯一事情是从main
方法返回,因此在第14行之后,所有局部变量都超出范围
是否存在可与“第14行之后”关联的执行点但是仍然在方法main
中,Icelandic
的一个实例在范围内,这取决于类文件中是否包含行调试信息,以及编译器如何将字节码指令映射到这些行号
如果编译器插入的return
字节码指令未与第15行关联,则在main
方法中创建的所有实例可能会在第14行之后被垃圾收集,但请记住,Long
实例可能仍会从全局缓存引用,因此不符合垃圾收集的条件n、 我们根本无法预测
JVM执行还有另一个方面:优化。JVM可以执行“转义分析”如果对象创建对程序语义没有任何影响,则删除对象创建。在您的程序中,从JVM的角度来看,所有对象都是未使用的。因此,另一种合法的执行场景是,此main
方法从不创建任何对象,然后根本没有符合垃圾收集条件的对象。我们是在谈论bef吗还是在第14行执行之后?在第14行主方法关闭+1之后。然而,扮演魔鬼代言人的角色,我认为正确的答案实际上应该是“3或4,取决于实现”。尽管JLS声明-128和127之间的原始值必须始终被保留,因此必须保留相同的对象,但它也声明理想情况下,装箱一个给定的原语值p,总是会产生一个相同的引用。"因此,给定的兼容JVM实现很容易使那些Long
值成为同一个对象,在这种情况下,只有三个实际对象才有资格收集!@berry120不是2个还是4个?如果所有三个长对象都引用同一个对象,那么只有两个Icelandic
对象将获得GCd,因为他们的权重
都指向了活的冰岛人仍在使用的长的
参考。我同意这不是一个好问题,但鉴于OP给出了正确的答案,我相信这是与之一致的理由。@KevinDiTraglia哦,当然,我只是把它作为附录指出而已!
Icelandic i1 = new Icelandic();
Icelandic i2 = new Icelandic();
Icelandic i3 = new Icelandic();
i3 = i1; i1 = i2; i2 = null; i3 = i1;