Подтвердить что ты не робот

Влияние автобоксинга на производительность

Обычно компилятор генерирует код для выполнения бокса и распаковки. Но что делает компилятор, если значения в штучной упаковке не нужны? Является ли (стандартным) стандартным компилятором Oracle достаточно умным, чтобы оптимизировать его?

Взгляните на этот метод:

public static void requireInRange(int index, Object[] array) {
    if(index < 0 || index >= array.length)
        throw new IndexOutOfBoundsException();
}

Единственной релевантной информацией является array.length, поэтому было бы бесполезно помещать каждое значение массива, например. Как в этом коде:

int[] anArray = {3, 4, 2};
requireInRange(3, anArray);

Будет ли компилятор действительно вставлять код для бокса для каждого значения массива?

4b9b3361

Ответ 1

В вашем коде нет автобоксинга. Фактически, учитывая:

public static void requireInRange(int index, Object[] array) {
   ...
}

int[] anArray = {3, 4, 2};
requireInRange(3, anArray); // DOES NOT COMPILE!!!

В то время как int может быть autoboxed к Integer, int[] НЕ получает autoboxed до Integer[] от Java. Вы можете писать библиотечные функции для этого, но язык не будет облегчать это преобразование.

Это на самом деле является источником многих путаниц в отношении, например, Arrays.asList(anIntArray) "сломан", потому что вместо возврата List<Integer> то, что возвращается, на самом деле является одноэлементным List<int[]>.


Но как насчет производительности???

Цитата из Руководство по языку Java/Autoboxing:

Нельзя использовать автобоксинг и распаковку для научных вычислений или другой чувствительный к производительности численный код. Integer не является заменой int; autoboxing и unboxing размывают различие между примитивными типами и ссылочными типами, но они не устраняют его.

Короче говоря, всякий раз, когда происходит автобоксинг, производительность определенно занимает немного хита. Некоторые вещи помогают облегчить это, например. механизм кеширования, встроенный в эти типы. Вот почему вы получаете следующее:

    System.out.println(
        ((Integer) 0) == ((Integer) 0)
    );
    // true

    System.out.println(
        ((Integer) 10000) == ((Integer) 10000)
    );
    // false (implementation-specific)

Что произошло здесь, когда 0 автоматически помещается в бокс, новый экземпляр Integer фактически не создается: значения в определенном диапазоне кэшируются для целей autoboxing, чтобы помочь производительности. 10000 в большинстве случаев реализации, вероятно, выпадает из этого диапазона, но некоторые реализации JVM позволяют вам указать диапазон кеша, если это необходимо.


Но я просто хочу получить длину массива!!!

Существует множество способов облегчить работу requireInRange с любыми типами массивов. К сожалению, работа с Java-массивом примитивов часто означает много повторений. Это означает предоставление перегрузок для int[], boolean[], byte[], Object[] и т.д. Отдельно.

Более краткий вариант - использовать отражение, но у этого есть свои плюсы и минусы. Вообще говоря, отражение не должно быть предпочтительным решением для большинства сценариев.

Сказав, что java.lang.reflect.Array имеет int getLength(Object array) static, который может возвращать длину ЛЮБОГО массива. Это не типы (например, большинство механизмов отражения); передавая компиляцию без массива, но бросает IllegalArgumentException во время выполнения.

Связанные вопросы

Ответ 2

Будет ли компилятор действительно вставлять код для бокса каждого значения массива?

Компилятор отклонит код, потому что int[] не может быть передан в метод, который принимает параметр Object[].

Автобоксирование происходит только для отдельных примитивных значений, никогда для целых массивов.

Ответ 3

Если вы сомневаетесь, вы можете предположить, что компилятор не оптимизирует код. Как правило, он выполняет буквальный перевод кода.

Кроме того, если вы сомневаетесь, предположим, что JVM делает очень хорошую работу по оптимизации кода во время выполнения. Я бы не предполагал, что это имеет значение, если у вас нет веских причин (например, профилировщик), чтобы подозревать, что это проблема.