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

Что очищает Garbage Collector: Heap или Stack?

1.0 Junior🔥 191 комментариев
#JVM и управление памятью#Основы Java

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

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

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

Что очищает Garbage Collector: Heap или Stack?

Garbage Collector (GC) очищает только HEAP, а не Stack. Это фундаментальное различие в управлении памятью Java, которое критично для понимания производительности приложений.

Stack vs Heap: краткое сравнение

ХарактеристикаStackHeap
ОчисткаАвтоматическая (при выходе из scope)Garbage Collector
УправлениеLIFO (Last In First Out)Автоматическое управление GC
СкоростьОчень быстро (просто moves pointer)Медленнее (GC требует ресурсов)
РазмерМеньше (обычно 1-8 MB)Больше (может быть гигабайты)
МногопоточностьКаждый поток имеет свой StackShared между всеми потоками
ИсключенияStackOverflowError если переполненOutOfMemoryError если переполнен

Stack — автоматическая очистка

Stack очищается автоматически при выходе из области видимости (scope) метода.

public void example() {
    int x = 10;              // Добавляется в Stack
    String name = "Alice";   // Ссылка добавляется в Stack (сам объект в Heap)
    
    {
        int y = 20;          // Добавляется в Stack
        String city = "NYC"; // Ссылка в Stack
    }                        // y и city автоматически удаляются из Stack
    
    // x и name всё ещё в Stack
}                            // Метод завершился — x и name удалены из Stack

// STACK ОЧИЩАЕТСЯ АВТОМАТИЧЕСКИ — НЕ НУЖЕН GC

Механизм очистки Stack:

Стек растёт вверх по мере добавления переменных.
При выходе из scope — Stack Pointer просто передвигается вниз.
Очистка занимает O(1) операцию (просто движение указателя).

Heap — управление Garbage Collector

Heap содержит объекты, и только GC отвечает за их удаление.

public void example() {
    User user = new User("Alice");  // Ссылка user в Stack
                                    // Объект User создан в Heap
    
    List<String> names = new ArrayList<>();  // Ссылка names в Stack
                                             // ArrayList объект в Heap
    names.add("Bob");                        // String "Bob" в Heap
}                                           // ВЫХОД ИЗ МЕТОДА

// Stack: user и names удалены (автоматически)
// Heap: User и ArrayList объекты ОСТАЮТСЯ в памяти!
//       Их удалит GARBAGE COLLECTOR, когда найдёт, что они не используются

Кто удаляет объекты из Heap

Ответ: Garbage Collector. Давайте разберём, как это происходит.

public class GCExample {
    public static void main(String[] args) {
        // Iteration 1
        User user1 = new User("Alice");  // Объект создан в Heap
        System.out.println(user1.getName());
        user1 = null;  // Ссылка на user1 удалена
                       // Объект User("Alice") теперь недостижим
                       // GC может очистить этот объект
        
        // Iteration 2
        User user2 = new User("Bob");    // Новый объект в Heap
        System.out.println(user2.getName());
        user2 = null;  // Ещё один объект доступен для GC
        
        // GC запустится в какой-то момент
        // Он найдёт user1 и user2 объекты (они не referenced)
        // И удалит их из Heap
    }
}

Визуально:

END OF METHOD 1:
┌─────────────────┐
│   STACK         │
├─────────────────┤
│  (empty)        │  ← user1 удалена (автоматически)
└─────────────────┘

┌─────────────────┐
│   HEAP          │
├─────────────────┤
│ User("Alice")   │  ← Не referenced, GC удалит позже
│ User("Bob")     │  ← Не referenced, GC удалит позже
└─────────────────┘

Когда запускается GC

GC запускается автоматически в разные моменты:

  1. После нехватки памяти — когда свободной памяти в Heap меньше определённого порога
  2. Явный вызовSystem.gc() (не гарантирует запуск)
  3. Периодически — в зависимости от GC алгоритма
public void memoryPressure() {
    // Создаём много объектов
    for (int i = 0; i < 1000000; i++) {
        User user = new User("User " + i);
        // GC может запуститься во время цикла
        // когда Heap заполнится
    }
}

// Явный вызов (не рекомендуется в production)
System.gc(); // Запрос к JVM на запуск GC (может не сработать)

Практический пример: различие очистки

public class MemoryExample {
    static class User {
        String name;
        User(String name) { this.name = name; }
    }
    
    public static void main(String[] args) {
        // STACK
        int age = 30;                   // Stack: 4 bytes (int)
        
        // HEAP
        User user = new User("Alice");  // Stack: ссылка (8 bytes)
                                        // Heap: User объект (~50+ bytes)
        
        // Вывод информации о памяти
        long memoryBefore = Runtime.getRuntime().totalMemory() -
                           Runtime.getRuntime().freeMemory();
        System.out.println("Memory used: " + memoryBefore);
        
        // УДАЛЕНИЕ ССЫЛКИ
        user = null;  // Stack: ссылка удалена
                      // Heap: объект остался, но сейчас недостижим
        
        age = 0;      // Stack: переменная перезаписана
        
        // В этот момент:
        // Stack: очищен автоматически и мгновенно
        // Heap: User объект ждёт GC
        
        // Запрос GC (может работать асинхронно)
        System.gc();
        
        long memoryAfter = Runtime.getRuntime().totalMemory() -
                          Runtime.getRuntime().freeMemory();
        System.out.println("Memory used after GC: " + memoryAfter);
    }
}

Пример: что происходит с объектами

List<User> users = new ArrayList<>();  // users в Stack, List объект в Heap

for (int i = 0; i < 100; i++) {
    User user = new User("User " + i);  // user в Stack (переиспользуется)
                                         // User объекты в Heap
    users.add(user);                     // ArrayList сохраняет ссылки
}

// После цикла:
// Stack: user переменная перезаписана (i уже нет)
//        users ссылка всё ещё существует
// Heap: 100 User объектов в ArrayList (referenced, GC не трогает)
//       ArrayList растёт, занимает больше памяти

users.clear();  // Очищаем List

// После clear():
// Stack: users ссылка остаётся
// Heap: 100 User объектов теперь не referenced (GC удалит)
//       ArrayList объект остаётся пустым в Heap

Проблемы с управлением памятью

Memory Leak (утечка памяти)

public class MemoryLeak {
    static List<User> cache = new ArrayList<>();  // Static — никогда не чистится
    
    public void addUser(User user) {
        cache.add(user);  // Объекты остаются в памяти навсегда
    }
    
    // Даже если user больше не используется
    // GC не сможет очистить, т.к. cache держит ссылку
}

// Решение:
public class MemoryLeakFixed {
    static Map<String, User> cache = new WeakHashMap<>();  // Weak references
    // или
    static Map<String, User> cache = new LRUCache<>(1000);  // Limited size cache
}

Stack Overflow

public void recursion(int n) {
    recursion(n + 1);  // Бесконечная рекурсия
}

// StackOverflowError: Stack переполнен локальными переменными
// (не Heap, так как переменные добавляются в Stack)

Gc Tuning: контроль за GC

# Запуск с разными GC алгоритмами
java -XX:+UseG1GC -Xmx4G -Xms4G MyApp      # G1GC для больших Heap
java -XX:+UseSerialGC MyApp                 # Serial GC для малых приложений
java -XX:+UseParallelGC -XX:ParallelGC Threads=4 MyApp  # Parallel GC

Итоговая таблица: кто, что и когда очищает

МестоТип данныхКогда удаляетсяКто удаляетСкорость
StackПримитивы, ссылкиПри выходе из scopeJVM (automatically)Очень быстро
HeapОбъектыПосле GC запускаGarbage CollectorМедленнее

Вывод

Stack очищается автоматически при выходе из области видимости
Heap очищается Garbage Collector когда объекты недостижимы
GC только для Heap — Stack работает детерминированно
GC запускается автоматически когда Heap заполнится или по расписанию
Память в Stack высвобождается мгновенно, в Heap — с задержкой

Для production разработки важно:

  • Понимать, что создаётся в Heap
  • Избегать Memory Leaks через неправильное управление ссылками
  • Мониторить GC паузы с помощью JVM метрик
  • Оптимизировать размер Heap согласно требованиям
Что очищает Garbage Collector: Heap или Stack? | PrepBro