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

Как происходит очистка мусора в Java

2.0 Middle🔥 91 комментариев
#Основы Java

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

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

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

Как происходит очистка мусора в Java

Очистка мусора (Garbage Collection, GC) — это автоматический процесс освобождения памяти от объектов, которые больше не используются приложением. Это один из ключевых механизмов JVM, который отличает Java от языков вроде C++, где программист сам управляет памятью.

Основной принцип работы

Java использует поколенческий (generational) подход к сборке мусора. Идея заключается в том, что большинство объектов живут недолго, поэтому их лучше проверять чаще, а долгоживущие объекты — реже.

// Пример: создание временных объектов, которые быстро удаляются
for (int i = 0; i < 1000000; i++) {
    String temp = new String("temp object"); // эти объекты удалятся быстро
    // использование temp
} // temp становится недостижимым после каждой итерации

Структура памяти JVM

Куча (Heap) разделена на несколько областей:

  1. Young Generation (молодое поколение)

    • Eden — где создаются новые объекты
    • Survivor Spaces (S0, S1) — где выживают объекты после первой GC
    • Объекты, пережившие определённое количество GC, переходят в Old Generation
  2. Old Generation (старое поколение)

    • Хранит долгоживущие объекты
    • Требует более дорогостоящей очистки
  3. Permanent Generation (метаspace в Java 8+)

    • Хранит метаданные классов, методов, строки

Типы сборки мусора

Minor GC (Молодая очистка)

Происходит в Young Generation часто и быстро:

List<String> strings = new ArrayList<>();
for (int i = 0; i < 100000; i++) {
    strings.add("String " + i); // при выходе из памяти Eden произойдёт Minor GC
}

Major/Full GC (Полная очистка)

Происходит реже, очищает Old Generation и весь Heap:

// Full GC может произойти если:
// 1. Old Generation переполнена
// 2. Недостаточно памяти в Metaspace
// 3. Вызван System.gc() (не гарантирует, что произойдёт)

public class GarbageCollectionExample {
    static List<byte[]> largeObjects = new ArrayList<>();
    
    public static void main(String[] args) {
        // Создание долгоживущих объектов
        while (true) {
            largeObjects.add(new byte[1024 * 1024]); // 1 MB объекты
            // Когда Old Generation переполнится, произойдёт Full GC
        }
    }
}

Алгоритмы сборки мусора

В современной Java используются несколько алгоритмов:

Mark-Sweep-Compact

  • Mark: пометить достижимые объекты из корневых ссылок
  • Sweep: удалить недостижимые объекты
  • Compact: переместить оставшиеся объекты, убрать фрагментацию
// Пример: выявление недостижимых объектов
public class ReachabilityExample {
    public static void main(String[] args) {
        Object obj = new Object();
        // obj достижим из стека
        
        obj = null; // obj становится недостижимым
        // GC может удалить этот объект
    }
}

Copying Algorithm Делит память на две части: только заполненная часть копируется

G1GC (Garbage First) Разделяет кучу на регионы, собирает самые мусорные регионы первыми

// Запуск с G1GC (для Java 9+)
// java -XX:+UseG1GC MyApplication

Достижимость объектов (Reachability)

Объект удаляется, если он недостижим из корневых ссылок:

public class ReachabilityTypes {
    public static void main(String[] args) {
        // Сильная ссылка (Strong Reference)
        Object strong = new Object();
        
        // Мягкая ссылка (Soft Reference) — удаляется если мало памяти
        SoftReference<Object> soft = new SoftReference<>(new Object());
        
        // Слабая ссылка (Weak Reference) — удаляется всегда при GC
        WeakReference<Object> weak = new WeakReference<>(new Object());
        
        // Фантомная ссылка (Phantom Reference) — для очистки ресурсов
        PhantomReference<Object> phantom = new PhantomReference<>(new Object(), null);
    }
}

Оптимизация и мониторинг

// Получить информацию о памяти
Runtime runtime = Runtime.getRuntime();
long maxMemory = runtime.maxMemory();
long totalMemory = runtime.totalMemory();
long freeMemory = runtime.freeMemory();
long usedMemory = totalMemory - freeMemory;

System.out.println("Max: " + maxMemory / 1024 / 1024 + " MB");
System.out.println("Used: " + usedMemory / 1024 / 1024 + " MB");

Утечки памяти в Java

Хотя GC автоматична, утечки всё равно возможны:

public class MemoryLeakExample {
    static List<Object> cache = new ArrayList<>(); // статический список
    
    public void addToCache(Object obj) {
        cache.add(obj); // объекты будут жить столько же, сколько приложение
        // это утечка памяти!
    }
}

// Правильный подход с WeakHashMap
public class ProperCache {
    static Map<String, Object> cache = new WeakHashMap<>();
    // объекты удалятся автоматически при недостатке памяти
}

Настройка GC параметров

# Выбрать GC алгоритм
java -XX:+UseG1GC MyApplication

# Настроить размер кучи
java -Xms512m -Xmx2g MyApplication

# Логирование GC
java -Xlog:gc*:file=gc.log MyApplication

Ключевые выводы

  • Автоматизм: разработчик не должен беспокоиться о явном удалении объектов
  • Поколенческий подход: молодые объекты проверяются часто, старые — редко
  • Отслеживание достижимости: GC использует граф ссылок для определения живых объектов
  • Выбор алгоритма: разные сценарии требуют разных GC (G1, ZGC, Shenandoah)
  • Мониторинг: в production важно отслеживать паузы GC и утечки памяти

Понимание GC критично для написания производительного кода и отладки проблем с памятью.

Как происходит очистка мусора в Java | PrepBro