Почему значения кеширования класса Integer в диапазоне от -128 до 127?
Что касается моего предыдущего вопроса, Почему == сравнения с Integer.valueOf(String) дают разные результаты для 127 и 128?, мы знаем, что Integer
class
имеет кеш, который хранит значения между -128
и 127
.
Просто интересно, почему между -128 и 127?
Документация Integer.valueOf() заявила, что она " кэширует часто запрашиваемые значения". Но действительно ли значения между -128
и 127
требуются для реального? Я думал, что часто запрашиваемые ценности очень субъективны.
Есть ли возможная причина этого?
В документации также указано: ".. и может кэшировать другие значения за пределами этого диапазона."
Как это можно достичь?
Ответы
Ответ 1
Просто интересно, почему между -128 и 127?
Более широкий диапазон целых чисел может быть кэширован, но по крайней мере те, которые находятся между -128 и 127, должны быть кэшированы, потому что это предусмотрено Спецификация языка Java (акцент мой):
Если значение p в боксе равно true, false, байту или char в диапазоне от \u0000 до\u007f или int или коротком числе между -128 и 127 (включительно), то пусть r1 и r2 - результаты любых двух бокс-преобразований p. Всегда бывает, что r1 == r2.
Обоснование этого требования объясняется в том же параграфе:
В идеале, бокс данного примитивного значения p всегда будет давать идентичную ссылку. На практике это может оказаться невозможным с использованием существующих методов внедрения. Правила выше - прагматичный компромисс. Последнее заключительное предложение требует, чтобы определенные общие значения всегда помещались в неразличимые объекты. [...]
Это гарантирует, что в большинстве распространенных случаев поведение будет желательным, не налагая чрезмерного штрафа за производительность, особенно на небольшие устройства. Менее ограниченные памятью реализации могут, например, кэшировать все char и короткие значения, а также значения int и long в диапазоне от -32K до + 32K.
Как я могу кэшировать другие значения за пределами этого диапазона.?
Вы можете использовать опцию -XX:AutoBoxCacheMax
JVM, которая на самом деле не задокументирована в списке доступных параметров JVM Hotspot. Однако в комментарии содержатся в классе Integer
по строке 590:
Размер кеша может контролироваться опцией -XX:AutoBoxCacheMax=<size>
.
Обратите внимание, что это специфичная реализация и может быть или не быть доступной на других JVM.
Ответ 2
-128 до 127 - размер по умолчанию. Но javadoc также говорит, что размер кеша Integer может быть, управляемый параметром -XX:AutoBoxCacheMax=<size>
. Обратите внимание, что он устанавливает только высокое значение, низкое значение всегда -128. Эта функция была введена в 1.6.
Что касается причин -128 до 127 - это диапазон значений байтов, и естественно использовать его для очень маленького кеша.
Ответ 3
Причиной кэширования небольших целых чисел, если это то, о чем вы просите, является то, что многие алгоритмы используют небольшие числа в своих вычислениях, поэтому избегать затрат на создание объектов для этих значений имеет смысл.
Затем возникает вопрос, какие целые числа кэшируются. Опять же, говоря вообще, частота, с которой используются постоянные значения, имеет тенденцию к уменьшению по мере увеличения абсолютного значения константы - каждый тратит много времени, используя значения 1 или 2 или 10, относительно мало кто использует значение 109 очень интенсивно; меньше производительности будет зависеть от того, насколько быстро можно получить Integer для 722.. Java выбрала выделение 256 слотов, охватывающих диапазон значащего байтового значения. Это решение, возможно, было проинформировано, анализируя программы, существовавшие в то время, но так же вероятно, что они были чисто произвольными. Это разумный объем пространства для инвестиций, к нему можно быстро получить доступ (маска, чтобы узнать, имеет ли значение в диапазоне кеша, а затем быстрый поиск таблицы для доступа к кешу), и это, безусловно, будет охватывать наиболее распространенные случаи.
Другими словами, я думаю, что ответ на ваш вопрос: "Это не так субъективно, как вы думали, но точные границы - это в основном решение о правиле большого пальца... и экспериментальными доказательствами было то, что это было достаточно хорошо."
Ответ 4
Максимальное целочисленное значение, которое можно кэшировать, можно настроить с помощью системного свойства i.e java.lang.Integer.IntegerCache.high
(-XX:AutoBoxCacheMax
). Кэш реализован с использованием массива.
private static class IntegerCache {
static final int high;
static final Integer cache[];
static {
final int low = -128;
// high value may be configured by property
int h = 127;
if (integerCacheHighPropValue != null) {
// Use Long.decode here to avoid invoking methods that
// require Integer autoboxing cache to be initialized
int i = Long.decode(integerCacheHighPropValue).intValue();
i = Math.max(i, 127);
// Maximum array size is Integer.MAX_VALUE
h = Math.min(i, Integer.MAX_VALUE - -low);
}
high = h;
cache = new Integer[(high - low) + 1];
int j = low;
for(int k = 0; k < cache.length; k++)
cache[k] = new Integer(j++);
}
private IntegerCache() {}
}