Кэш память, Классы обёртки (Wrapper type)
Почти на всех видео уроках по теме классы обёртки упоминается память кэш.
я знаю что:
Integer n = 12;
в этом случае (значение от -128 до 127) выполнится boxing и значение 12 запишется в кэш,
но где находится этот кэш?
Я знаю в структуре Java такие памяти как Стек(stack), Куча(heap) и Пул-Строк(pool string) для строковых значений.
Является ли кэш памятью процессора? Или это кэш - структура Java, как пул строк например, и она лежит где то в куче, мне не известно, помогите пожалуйста разобраться.
Ответы (2 шт):
Этот кэш создаётся при запуске программы и хранится в куче. Это просто часть кучи, где хранятся объекты.
Пул объектов: Для Integer кэш реализован как массив объектов Integer, который хранит ссылки на уже созданные объекты для значений от -128 до 127. Когда вы создаёте объект Integer в этом диапазоне, Java просто возвращает ссылку на уже существующий объект из этого кэша.
Когда вы пишете:
Integer n1 = 12;
Integer n2 = 12;
Java проверяет, есть ли уже объект Integer, представляющий значение 12 в кэше. Если он есть, n1 и n2 будут ссылаться на один и тот же объект. Если бы вы использовали значение вне этого диапазона, например, 128 или -129, Java создала бы новый объект в куче, и ссылки n1 и n2 указывали бы на разные объекты.
(Знакомая тема C/C++ программистам :) )
Кэш — промежуточный буфер с быстрым доступом, где хранится наиболее вероятная запрашиваемая информация. В общем-то кэш может быть реализован разными способами и в разных местах сам по себе.
В контексте кэш Java для Integer, подразумеваются наиболее дорогие операции выделения и освобождения памяти. Память под Integer значения от -128 до 127 выделяется заранее в куче, как под самые часто используемые значения. Как он выглядит и где находится? Да прямо в исходном коде реализации Integer класса.
Вон он, приватный статический внутренний класс IntegerCache со статическими полями массивов для хранения.
public final class Integer extends Number
implements Comparable<Integer>, Constable, ConstantDesc {
...
/**
* Cache to support the object identity semantics of autoboxing for values between
* -128 and 127 (inclusive) as required by JLS.
*
* The cache is initialized on first usage. The size of the cache
* may be controlled by the {@code -XX:AutoBoxCacheMax=<size>} option.
* During VM initialization, java.lang.Integer.IntegerCache.high property
* may be set and saved in the private system properties in the
* jdk.internal.misc.VM class.
*
* WARNING: The cache is archived with CDS and reloaded from the shared
* archive at runtime. The archived cache (Integer[]) and Integer objects
* reside in the closed archive heap regions. Care should be taken when
* changing the implementation and the cache array should not be assigned
* with new Integer object(s) after initialization.
*/
private static class IntegerCache {
static final int low = -128;
static final int high;
static final Integer[] cache;
static Integer[] archivedCache;
static { ... }
private IntegerCache() {}
}
}
В этом случае (значение от -128 до 127) выполнится boxing и значение 12 запишется в кэш
Память выделена заранее, значения записаны заранее, чтобы на них не тратить время в дальнейшем, поэтому его диапазон такой маленький. Запись заранее сформированных объектов в статическом конструкторе в участке кода:
// Use the archived cache if it exists and is large enough
if (archivedCache == null || size > archivedCache.length) {
Integer[] c = new Integer[size];
int j = low;
for(int i = 0; i < c.length; i++) {
c[i] = new Integer(j++);
}
archivedCache = c;
}
cache = archivedCache;
Еще можно заметить, что там используется archivedCache и механизм Class Data Sharing (CDS), который позволяет нескольким JVM сохранять и обмениваться памятью, тем самым ускоряя запуск и экономя память. Поэтому изначально происходит попытка чтения из CDS, если не получилось, то объекты кэша формируются и записываются в массивы.
Там же ниже использование кэша в методе valueOf
@IntrinsicCandidate
public static Integer valueOf(int i) {
if (i >= IntegerCache.low && i <= IntegerCache.high)
return IntegerCache.cache[i + (-IntegerCache.low)];
return new Integer(i);
}