Кэш память, Классы обёртки (Wrapper type)

Почти на всех видео уроках по теме классы обёртки упоминается память кэш.
я знаю что:

Integer n = 12;

в этом случае (значение от -128 до 127) выполнится boxing и значение 12 запишется в кэш,
но где находится этот кэш?
Я знаю в структуре Java такие памяти как Стек(stack), Куча(heap) и Пул-Строк(pool string) для строковых значений. Является ли кэш памятью процессора? Или это кэш - структура Java, как пул строк например, и она лежит где то в куче, мне не известно, помогите пожалуйста разобраться.


Ответы (2 шт):

Автор решения: Damir Hakimof
  1. Этот кэш создаётся при запуске программы и хранится в куче. Это просто часть кучи, где хранятся объекты.

  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++ программистам :) )

→ Ссылка
Автор решения: Alex Krass

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

В контексте кэш 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);
}
→ Ссылка