почему этот код Java не может использовать escape-анализ?

мой код здесь =>

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

я не мог понять почему


person lovezhy    schedule 03.11.2019    source источник
comment
Вы можете показать нам результат. Я не совсем понимаю вашу проблему здесь   -  person roottraveller    schedule 03.11.2019
comment
Размещенный код не будет компилироваться. foo присваивается значение, но никогда не объявляется, а метод getX() в классе Point упоминается, но никогда не определяется. Если вы ожидаете, что мы вам поможем, опубликуйте свой самый последний и актуальный код.   -  person mario_sunny    schedule 03.11.2019
comment
@roottraveller привет, я загружаю фото. Распределение var pointHolder было устранено, но выделение new Point(x + 2,42) не устранено.   -  person lovezhy    schedule 03.11.2019
comment
Что вы имеете в виду, не был устранен - ​​вы имеете в виду, не освобожден?   -  person mario_sunny    schedule 03.11.2019
comment
@mario_sunny согласно escape analysis, область действия new Point() находится в методе test4, поэтому выделение new Point() следует исключить.   -  person lovezhy    schedule 03.11.2019
comment
Escape-анализ выполняется как часть компиляции JIT, а не компиляции байт-кода Java.   -  person Johannes Kuhn    schedule 03.11.2019
comment
@JohannesKuhn да, это результат jitwatch после компиляции jit.   -  person lovezhy    schedule 03.11.2019
comment
Это все еще байт-код. Посмотрите на реальную сборку.   -  person Johannes Kuhn    schedule 03.11.2019
comment
@JohannesKuhn, вы хотите увидеть ассемблерный код?   -  person lovezhy    schedule 03.11.2019


Ответы (1)


Escape Analysis в компиляторе HotSpot C2 достаточно прост. Он никогда не пытался обнаружить все возможные объекты, которые не выходят за пределы области компиляции. В частности, в настоящее время он не поддерживает многоуровневое дерево ссылок.

В вашем примере ссылка на недавно выделенный Point назначается полю объекта: PointHolder.point. JIT рассматривает это назначение как экранирование объекта Point и, таким образом, не устраняет выделение.

Одним из особых исключений является упаковка-распаковка: HotSpot специально обрабатывает методы упаковки-распаковки. Например. он по-прежнему сможет устранить выделение объекта Integer, когда он назначается полю IntegerHolder.

Однако эта проблема не является чем-то неразрешимым — это скорее упущенная возможность оптимизации. Graal JIT в этом смысле лучше — в данном примере он действительно устраняет выделение как Point, так и PointHolder.

person apangin    schedule 04.11.2019