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

Когда срабатывает Garbage Collector на разные ссылки в Java?

1.8 Middle🔥 131 комментариев
#JVM и память#Производительность и оптимизация

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

🐱
deepseek-v3.2PrepBro AI6 апр. 2026 г.(ред.)

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

Сборка мусора в Java: механизм работы для разных типов ссылок

В Java Garbage Collector (GC) — это автоматический механизм управления памятью, который освобождает память, занятую недостижимыми объектами. Время срабатывания GC зависит как от типа ссылки, так и от реализации JVM и выделенной памяти, но принципы работы для разных тип ссылок стандартизированы через пакет java.lang.ref.

Основные типы ссылок и их сборка

1. Сильные ссылки (Strong References)

Это обычные ссылки, создаваемые оператором new. Объекты, на которые существуют сильные ссылки, никогда не будут собраны GC, пока ссылка активна. GC срабатывает для них, когда они становятся недостижимыми (например, вышли из области видимости или присвоено null).

MyClass obj = new MyClass(); // Сильная ссылка
obj = null; // Теперь объект может быть удалён GC

2. Мягкие ссылки (SoftReferences)

Объекты, на которые ссылаются только мягкие ссылки, удаляются GC только при нехватке памяти (перед OutOfMemoryError). Они идеальны для кэширования.

SoftReference<MyClass> softRef = new SoftReference<>(new MyClass());
// GC удалит объект, если память под давлением

3. Слабые ссылки (WeakReferences)

Объекты с слабыми ссылками удаляются при следующем запуске Minor GC (сборки молодого поколения), независимо от доступной памяти. Часто используются в WeakHashMap для хранения метаданных.

WeakReference<MyClass> weakRef = new WeakReference<>(new MyClass());
System.gc(); // С высокой вероятностью объект будет удалён сразу

4. Фантомные ссылки (PhantomReferences)

Самые "слабые" ссылки. Фантомные ссылки не позволяют получить сам объект (всегда возвращают null), но уведомляют через очередь, когда объект финализирован и готов к cleanup. Используются для управления нативными ресурсами.

ReferenceQueue<MyClass> queue = new ReferenceQueue<>();
PhantomReference<MyClass> phantomRef = new PhantomReference<>(new MyClass(), queue);
// Объект удалён, но мы можем выполнить очистку через queue.poll()

Когда запускается GC для каждого типа?

  • Minor GC (для молодого поколения: Eden и Survivor spaces):

    • Запускается при заполнении Eden space.
    • Собирает в первую очередь слабые и фантомные ссылки.
  • Major/Full GC (для всего heap, включая Old Generation):

    • Запускается при заполнении Old Generation или явном вызове System.gc().
    • Удаляет мягкие ссылки при нехватке памяти.
    • Очищает сильные ссылки, если они недостижимы.

Практические сценарии

// Пример с WeakHashMap
WeakHashMap<Key, Value> cache = new WeakHashMap<>();
// Элементы автоматически удалятся GC, когда на Key не останется сильных ссылок

// Мониторинг через ReferenceQueue
ReferenceQueue<MyObject> refQueue = new ReferenceQueue<>();
WeakReference<MyObject> ref = new WeakReference<>(new MyObject(), refQueue);
// Позволяет отслеживать удаление объектов

Ключевые факторы, влияющие на срабатывание GC

  1. Тип сборщика (Serial, Parallel, G1, ZGC, Shenandoah) — каждый имеет разные стратегии.
  2. Наполненность heap — основные триггеры:
    • Young generation full → Minor GC.
    • Old generation full → Major GC.
  3. Явный вызов System.gc() (но не гарантирует немедленного выполнения).
  4. Настройки JVM (-Xms, -Xmx, -XX:SoftRefLRUPolicyMSPerMB).

Важно

Использование несильных ссылок требует аккуратности: всегда проверяйте get() перед использованием, так как он может внезапно вернуть null. Правильное применение этих механизмов позволяет создавать эффективные кэши, избегать утечек памяти и управлять жизненным циклом объектов в сложных приложениях. На Android, с учётом ограниченных ресурсов, понимание этих нюансов особенно критично для производительности.