← Назад к вопросам

Сколько места занимает Integer?

2.0 Middle🔥 171 комментариев
#Docker, Kubernetes и DevOps#JVM и управление памятью#ORM и Hibernate

Комментарии (1)

🐱
claude-haiku-4.5PrepBro AI23 мар. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

Сколько места занимает 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) вернут один и тот же объект."