java - 垃圾收集的对象数

标签 java object inheritance garbage

给定:

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
     }
 }

当到达第 14 行时,有多少对象符合垃圾收集器的条件?

一个。 0 B.1 C.2 D.3 E.4 F.6

答案是 E。为什么?

最佳答案

这个问题,尤其是坚持 4 的那个特定“正确”答案,没有多大意义,因为它得出了几个关于 JVM 如何工作的假设,这些假设在最好的情况下是幼稚的,或者根本是错误的。

它做错的第一件事是假设知道曾经创建了多少对象。

main 方法创建了三个 Icelandic 实例,它们有一个继承字段 weight,初始化值为 1200L .值 1200L 使用 Long.valueOf 方法通过自动装箱转换为 Long 实例这是允许的,但不需要缓存经常请求的值。因此,我们无法预测此处创建的 Long 实例的数量,它可能是一个或三个,但如果无论出于何种原因缓存对所有调用都不起作用,甚至两个也是可能的。

然后代码正在处理包含三个实例的局部变量,并且应该在第 14 行“之后”仅包含这些实例中的一个,但是在该行之后没有与此状态可能相关的关联代码。该行之后唯一发生的事情是从 main 方法返回,因此在第 14 行之后所有局部变量都超出范围。

是否有一个执行点可以与“第 14 行之后”相关联但仍在方法 main 中,其中恰好有一个 Icelandic 实例在范围内取决于类文件中是否包含行调试信息以及编译器如何将字节码指令映射到这些行号。

如果编译器插入的 return 字节码指令与第 15 行无关,则在 main 方法中创建的所有实例可能会在第 14 行之后被垃圾回收,但保留请记住,Long 实例可能仍会从全局缓存中引用,因此不符合垃圾回收条件。我们根本无法预测。

JVM 执行还有另一个方面:优化。如果 JVM 对程序语义没有任何影响,则允许 JVM 执行“逃逸分析”并省略对象创建。在您的程序中,从 JVM 的角度来看,所有对象都是未使用的。所以另一个合法的执行场景是这个 main 方法从不创建任何对象,因此根本没有对象符合垃圾收集的条件。

关于java - 垃圾收集的对象数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26263054/

相关文章:

c++ - C++中有没有办法让派生类重写基类静态方法?

c++ - c++ 中的高性能代码(继承、指向函数的指针、if)

java - 如何使用 apache tika 阅读 pdf 书签?

javascript - 根据对象的一个​​属性对对象数组进行排序

java - 如何在菜单选项窗口中显示框架

javascript - 函数构造函数 - 使用原型(prototype)添加函数给出 - 未捕获的语法错误 : Unexpected token {

javascript - Object.defineProperty 不适用于窗口对象 IE11

c++ - 了解类共享指针及其在继承中的使用

java - 如何加快 Selenium 中的页面解析速度

java - Android 按下按钮时的一些 Action