2

我的代码在这里=>

class PointHolder {
    private Point point;

    public PointHolder(Point point) {
        this.point = point;
    }
    //getter
}
class Point {
    private int x;
    private int y;

    public Point(int x, int y) {
        this.x = x;
        this.y = y;
    }
    //getter setter
}

public class Escape {
    public static void main(String[] args) {
        for (int i = 0; i < 20000; i++) {
            test4(i);
        }
    }
    static int foo;
    public static void test4(int x) {
        PointHolder pointHolder = new PointHolder(new Point(x + 2, 42));
        foo = pointHolder.getPoint().getX();
    }
}

使用 jitwatch,我可以看到 pointHolder 没有被分配,但new Point(x+2, 42)仍然被分配。

一个

es2

我不知道为什么

4

1 回答 1

1

HotSpot C2 编译器中的逃逸分析相当简单。它从未尝试检测所有未超出编译范围的可能对象。特别是,它目前不处理多级参考树。

在您的示例中,对新分配的引用Point分配给对象字段:PointHolder.point。JIT 将此分配视为Point对象的转义,因此不会消除分配。

一个特殊的例外是装箱拆箱:HotSpot 专门处理装箱拆箱方法。Integer例如,当它被分配给一个IntegerHolder字段时,它仍然能够消除对象的分配。

不过,这个问题并不是无法解决的——而是错失了优化的机会。Graal JIT 在这方面更好 - 在给定的示例中,它确实消除了PointPointHolder分配。

于 2019-11-04T17:14:58.653 回答