Всем привет, сегодня заглянем под капот JVM, где на самом деле живёт int в JVM?
Все пишут int a = 10;
но что под капотом делает JVM?
int — это не объект, а примитив.
Он не создаётся через new, не лежит в куче по умолчанию и не проходит через конструктор. Для него у JVM есть отдельные байт-код инструкции: iload — положить на стек, istore — сохранить обратно, iadd — сложить напрямую. Никаких вызовов методов, никакого заголовка объекта, никакого участия GC.
Где хранится int — зависит от того, чем является переменная:
- Локальная переменная → лежит в массиве locals текущего стекового фрейма. Компилятор превращает имя переменной в «номер слота», а рантайм просто читает и пишет по индексу. Метод завершился — фрейм вытолкнулся, и этот int исчез. Сборщику мусора тут делать нечего.
- Поле экземпляра → лежит внутри объекта в куче. У объекта фиксированный layout, а у поля есть смещение (offset). Есть ссылка на объект — прибавили смещение — нашли этот int.
- Статическое поле → живёт вместе с объектом Class, который сам по сути лежит в куче. Время жизни привязано к загрузчику классов.
Почему int такой «низкоуровневый»? Потому что Java с самого начала разделила типы на примитивные и ссылочные. int — это 32-битное знаковое число в дополнительном коде, диапазон от -2³¹ до 2³¹−1. JVM работает с ним как с числом в регистре, без всякой «распаковки».
И только когда int нужно использовать как объект (например, положить в List<Integer>), компилятор автоматически упаковывает его в Integer: вот тогда появляется объект, заголовок, куча и GC.
Коротко: int в JVM — это по сути «отрезок из 32 бит». Где он лежит — зависит от того, где ты его объявил. На стеке — живёт мгновение, в куче — вместе с объектом, статический — вместе с классом.
Все пишут int a = 10;
но что под капотом делает JVM?
int — это не объект, а примитив.
Он не создаётся через new, не лежит в куче по умолчанию и не проходит через конструктор. Для него у JVM есть отдельные байт-код инструкции: iload — положить на стек, istore — сохранить обратно, iadd — сложить напрямую. Никаких вызовов методов, никакого заголовка объекта, никакого участия GC.
Где хранится int — зависит от того, чем является переменная:
- Локальная переменная → лежит в массиве locals текущего стекового фрейма. Компилятор превращает имя переменной в «номер слота», а рантайм просто читает и пишет по индексу. Метод завершился — фрейм вытолкнулся, и этот int исчез. Сборщику мусора тут делать нечего.
- Поле экземпляра → лежит внутри объекта в куче. У объекта фиксированный layout, а у поля есть смещение (offset). Есть ссылка на объект — прибавили смещение — нашли этот int.
- Статическое поле → живёт вместе с объектом Class, который сам по сути лежит в куче. Время жизни привязано к загрузчику классов.
Почему int такой «низкоуровневый»? Потому что Java с самого начала разделила типы на примитивные и ссылочные. int — это 32-битное знаковое число в дополнительном коде, диапазон от -2³¹ до 2³¹−1. JVM работает с ним как с числом в регистре, без всякой «распаковки».
И только когда int нужно использовать как объект (например, положить в List<Integer>), компилятор автоматически упаковывает его в Integer: вот тогда появляется объект, заголовок, куча и GC.
Коротко: int в JVM — это по сути «отрезок из 32 бит». Где он лежит — зависит от того, где ты его объявил. На стеке — живёт мгновение, в куче — вместе с объектом, статический — вместе с классом.