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

Какие знаешь виды памяти в Java?

2.0 Middle🔥 241 комментариев
#JVM и управление памятью#Основы Java

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

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

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

Виды памяти в Java

Java использует управляемую память с автоматической сборкой мусора (GC). Понимание типов памяти критично для оптимизации производительности и избежания утечек памяти.

1. Heap (Кучa) — основная память для объектов

Heap — это общее хранилище для всех объектов, выделяемое при запуске JVM.

// Все объекты хранятся в Heap
String name = new String("John");  // Объект String в Heap
List<String> names = new ArrayList<>();  // List объект в Heap
names.add("Alice");  // Строка также в Heap

// Размер Heap задается при запуске JVM
// java -Xms512m -Xmx2g Application
// -Xms512m — начальный размер Heap (512 MB)
// -Xmx2g — максимальный размер Heap (2 GB)

Структура Heap:

Heap
├── Young Generation (молодое поколение)
│   ├── Eden Space (где рождаются объекты)
│   └── Survivor Spaces (S0, S1)
└── Old Generation (старое поколение)
    └── (долгоживущие объекты)

2. Stack (Стек) — память для примитивов и ссылок

Stack — это вызовной стек, где хранятся локальные переменные и ссылки на объекты.

public void calculateSum() {
    int a = 10;  // Примитив a в Stack
    int b = 20;  // Примитив b в Stack
    
    String str = "hello";  // Ссылка str в Stack, объект в Heap
    List<Integer> list = new ArrayList<>();  // Ссылка list в Stack
    
    // После выхода из метода a, b, str, list удаляются из Stack
}

// Stack размер задается
// java -Xss1m Application
// -Xss1m — размер Stack для каждого потока (1 MB)

Отличие Heap от Stack:

ХарактеристикаHeapStack
РазмерБольшойМаленький
СкоростьМедленнееБыстрее
УправлениеGC управляетАвтоматический выход
ПотокобезопасностьРазделяется между потокамиУникален для каждого потока
СодержимоеОбъектыПримитивы, ссылки
ПереполнениеOutOfMemoryError: Java heap spaceStackOverflowError

3. StackOverflowError — переполнение Stack

// Бесконечная рекурсия вызывает StackOverflowError
public static void recursiveMethod() {
    recursiveMethod();  // Каждый вызов добавляет frame в Stack
}
// Exception in thread "main" java.lang.StackOverflowError

4. Метапространство (Metaspace) — память для метаданных

Metaspace хранит информацию о классах: их структура, методы, константы (Java 8+).

// Размер Metaspace
// java -XX:MetaspaceSize=128m -XX:MaxMetaspaceSize=512m Application

// Утечка в Metaspace — частая проблема при использовании динамической
// загрузки классов (reflection, proxies, CGLib)
public class ClassLoaderLeak {
    public static void main(String[] args) {
        while (true) {
            try {
                // Динамическая загрузка класса
                ClassLoader loader = new URLClassLoader(
                    new URL[]{new URL("file:lib/")},
                    ClassLoader.getSystemClassLoader()
                );
                Class<?> clazz = loader.loadClass("SomeClass");
                // Утечка: класс в памяти, даже если ClassLoader не используется
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }
}

5. PermGen (Permanent Generation) — устаревшее

PermGen использовался до Java 8 для хранения метаданных классов.

// Java 7 и ранее
// java -XX:PermSize=128m -XX:MaxPermSize=256m Application

// Java 8+ заменена на Metaspace (неограниченный размер)

6. Code Cache — память для JIT компилятора

Code Cache хранит скомпилированный машинный код.

// java -XX:InitialCodeCacheSize=40m -XX:ReservedCodeCacheSize=240m Application

// Если Code Cache переполнена, JIT прекращает компиляцию
// и производительность падает

7. Off-Heap память — память вне Heap

// Использование DirectByteBuffer для работы с памятью вне Heap
import java.nio.ByteBuffer;

public class OffHeapMemory {
    public static void main(String[] args) {
        // Allocate 10 MB off-heap
        ByteBuffer buffer = ByteBuffer.allocateDirect(10 * 1024 * 1024);
        
        buffer.putInt(42);
        buffer.putFloat(3.14f);
        
        // Используется на низком уровне (NIO, Unsafe API)
    }
}

// Плюсы Off-Heap:
// - Не подлежит GC
// - Быстрый доступ
// - Полезно для больших буферов

// Минусы:
// - Сложнее в управлении
// - Риск утечек памяти
// - Нет автоматической очистки

8. Native Memory — память для JVM внутренностей

// Native Memory используется для:
// - Thread стеков
// - JVM внутренние структуры
// - Native библиотеки (JNI)
// - GC служебные структуры

// Мониторинг Native Memory
// jcmd <pid> VM.native_memory summary

9. Сборка мусора (Garbage Collection)

// Mark and Sweep алгоритм
public class GarbageCollectionExample {
    public static void main(String[] args) {
        // Создаем объект
        String str = new String("Hello");
        
        // Переназначаем ссылку
        str = new String("World");
        // Первый объект "Hello" больше не имеет ссылок
        // GC пометит его и удалит
        
        // Явный запрос GC (не гарантирован)
        System.gc();
    }
}

// Типы GC
// 1. Serial GC — один поток (для небольших приложений)
// 2. Parallel GC — многопоточный (по умолчанию Java 8+)
// 3. G1GC — для предсказуемого времени остановки
// 4. ZGC — ultra-low latency
// 5. Shenandoah — для больших Heap'ов

10. Мониторинг памяти

import java.lang.management.ManagementFactory;
import java.lang.management.MemoryMXBean;
import java.lang.management.MemoryUsage;

public class MemoryMonitor {
    public static void main(String[] args) {
        MemoryMXBean memoryBean = ManagementFactory.getMemoryMXBean();
        
        // Heap Memory
        MemoryUsage heapUsage = memoryBean.getHeapMemoryUsage();
        System.out.println("Heap Used: " + heapUsage.getUsed() / 1024 / 1024 + " MB");
        System.out.println("Heap Max: " + heapUsage.getMax() / 1024 / 1024 + " MB");
        
        // Non-Heap Memory
        MemoryUsage nonHeapUsage = memoryBean.getNonHeapMemoryUsage();
        System.out.println("Non-Heap Used: " + nonHeapUsage.getUsed() / 1024 / 1024 + " MB");
    }
}

11. Типичные проблемы с памятью

// Memory Leak — утечка памяти
public class MemoryLeakExample {
    private static final List<String> cache = new ArrayList<>();
    
    public void addToCache(String value) {
        cache.add(value);  // Элементы никогда не удаляются!
    }
}

// OutOfMemoryError
public class OutOfMemoryExample {
    public static void main(String[] args) {
        List<byte[]> list = new ArrayList<>();
        while (true) {
            list.add(new byte[1024 * 1024]);  // 1 MB array
            // В итоге java.lang.OutOfMemoryError: Java heap space
        }
    }
}

Итог

Основные виды памяти в Java:

  1. Heap — для объектов (управляется GC)
  2. Stack — для примитивов и ссылок (автоматический)
  3. Metaspace — для метаданных классов
  4. Code Cache — для JIT скомпилированного кода
  5. Off-Heap — внешняя память
  6. Native Memory — для JVM внутренностей

Понимание этих механизмов критично для разработки высокопроизводительных Java приложений и диагностики проблем с памятью.