Сколько места занимает Integer?
Комментарии (1)
Ответ сгенерирован нейросетью и может содержать ошибки
Сколько места занимает Integer?
Краткий ответ
Integer в Java занимает 16 байт (на большинстве современных JVM), хотя само значение может занимать:
- Как примитив int: 4 байта
- Как объект Integer: 12-16 байт (зависит от JVM и сборщика мусора)
Примитив int vs Объект Integer
Примитив int (4 байта)
int value = 42; // Занимает 4 байта
Мемория:
┌─────────────────────┐
│ 42 (32-bit) │
└─────────────────────┘
0x0000002A
Объект Integer (12-16 байт)
Integer value = 42; // Занимает 12-16 байт
Мемория (64-bit JVM):
┌─────────────────────────────┐
│ Object Header (8 bytes) │ Хеш код, класс, флаги блокировки
├─────────────────────────────┤
│ Значение int (4 bytes) │ 42
├─────────────────────────────┤
│ Padding (4 bytes) │ Выравнивание памяти
└─────────────────────────────┘
Всего: 16 байт
Детальное объяснение
Object Header в Java
64-bit JVM:
- Mark Word: 8 bytes (хеш код, возраст, состояние блокировки)
- Class Pointer: 8 bytes (указатель на класс)
= 16 байт overhead
32-bit JVM:
- Mark Word: 4 bytes
- Class Pointer: 4 bytes
= 8 байт overhead
Integer класс
public final class Integer extends Number implements Comparable<Integer> {
private final int value; // 4 байта
// Плюс 12 байт Object Header
// Итого: 16 байт на 64-bit JVM
}
Практические примеры
Использование примитива (эффективно)
public class IntDemo {
int value = 42; // 4 байта
public void processInts() {
int a = 1;
int b = 2;
int c = a + b; // Вычисляется быстро в CPU регистре
int[] array = new int[1000000]; // 4MB памяти
// Никакого Object Header overhead
}
}
Использование объекта (неэффективно)
public class IntegerDemo {
Integer value = 42; // 16 байт (4x больше!)
public void processIntegers() {
List<Integer> list = new ArrayList<>();
for (int i = 0; i < 1000000; i++) {
list.add(i); // Каждый Integer = 16 байт
}
// Использовано 16MB памяти вместо 4MB!
// Плюс лишние обращения к памяти (cache misses)
}
}
Сравнение памяти: int array vs List<Integer>
int[] array = new int[1000000];
Память: 4 байта × 1,000,000 = 4 MB
Доступ: O(1), sequential memory
Скорость: БЫСТРО
List<Integer> list = new ArrayList<>(); // 1M элементов
Integer объекты: 16 байт × 1,000,000 = 16 MB
ArrayList overhead: ~48 байт
Указатели в array: 8 байт × 1,000,000 = 8 MB
Всего: 24+ MB
Доступ: O(1), но scattered memory (cache misses)
Скорость: МЕДЛЕННО
Integer Caching (Важный оптимизация)
// Java кэширует Integer объекты от -128 до 127!
Integer a = 100;
Integer b = 100;
System.out.println(a == b); // true! (Один и тот же объект)
Integer c = 200;
Integer d = 200;
System.out.println(c == d); // false (Разные объекты)
// Это почему:
Integer e = Integer.valueOf(100); // Вернёт кэшированный объект
Integer f = new Integer(100); // Создаст новый объект
System.out.println(e == f); // false
System.out.println(e.equals(f)); // true
// Кэширование реализовано так:
public static Integer valueOf(int i) {
if (i >= IntegerCache.low && i <= IntegerCache.high)
return IntegerCache.cache[i + (-IntegerCache.low)];
return new Integer(i);
}
// Где IntegerCache.low = -128, high = 127
// Кэш хранит 256 готовых Integer объектов
Измерение памяти в Java
import org.openjdk.jol.core.ClassLayout;
public class MemorySizeTest {
public static void main(String[] args) {
// Используем JOL (Java Object Layout) для точных измерений
Integer value = 42;
System.out.println(ClassLayout.parseInstance(value).toPrintable());
// Вывод:
// java.lang.Integer object internals:
// OFFSET SIZE TYPE DESCRIPTION
// 0 12 (object header)
// 12 4 int Integer.value
// 16 0 (loss due to the next object alignment)
// Instance size: 16 bytes
}
}
JVM параметры, влияющие на размер
# Сжатые ссылки (Compressed OOPs) — уменьшает размер объектов
java -XX:+UseCompressedOops MyApp
# Без сжатия (полные 64-bit ссылки)
java -XX:-UseCompressedOops MyApp
# По умолчанию сжатие включено на современных JVM
Практические выводы
Используй примитивы когда возможно
// ПЛОХО
List<Integer> integers = new ArrayList<>();
for (int i = 0; i < 1000000; i++) {
integers.add(i); // Каждый элемент 16 байт
}
// Память: 16+ MB
// ХОРОШО
int[] integers = new int[1000000];
for (int i = 0; i < 1000000; i++) {
integers[i] = i; // Каждый элемент 4 байта
}
// Память: 4 MB
Используй специализированные коллекции
// Для больших наборов примитивов
import it.unimi.dsi.fastutil.ints.IntArrayList;
IntArrayList list = new IntArrayList(1000000);
for (int i = 0; i < 1000000; i++) {
list.add(i); // Каждый элемент 4 байта (внутри использует int[])
}
// Память: 4 MB
Мониторинг памяти
Runtime runtime = Runtime.getRuntime();
long beforeMemory = runtime.totalMemory() - runtime.freeMemory();
List<Integer> list = new ArrayList<>();
for (int i = 0; i < 1000000; i++) {
list.add(i);
}
long afterMemory = runtime.totalMemory() - runtime.freeMemory();
long used = afterMemory - beforeMemory;
System.out.println("Используется памяти: " + used / 1024 / 1024 + " MB");
На собеседовании
Хороший ответ:
"Integer как объект занимает 16 байт на 64-bit JVM (12-16 в зависимости от версии JVM и выравнивания памяти), в то время как примитив int занимает только 4 байта.
Этот overhead происходит из-за Object Header (8 байт на метаданные), плюс сам int (4 байта), плюс padding для выравнивания.
Это критически важно для производительности при работе с большими массивами. Например, List<Integer> с миллионом элементов займёт 16MB, в то время как int[] займёт только 4MB. Кроме того, примитивные массивы работают быстрее благодаря лучшей локальности памяти (cache locality).
Также важно помнить, что Java кэширует Integer объекты от -128 до 127, поэтому Integer.valueOf(100) и Integer.valueOf(100) вернут один и тот же объект."