GC

30.03.2022https://habr.com/ru/companies/otus/articles/658219/
19.02.2013https://habr.com/ru/post/169883
Garbage Collector (GC)

Сборка мусора  —  процесс восстановления заполненной памяти среды выполнения путем уничтожения неиспользуемых объектов. Сборщик мусора запускается виртуальной машиной Java (JVM). В таких языках, как C и C++, программист отвечает и за создание и за уничтожение объектов. В Java сборщик мусора управляет памятью автоматически. Сборщик мусора — низкоприоритетный процесс, который запускается периодически и освобождает память использованную объектами которые больше не нужны. Если забыть уничтожить бесполезные объекты - выделенная им память не будет освобождаться, будет расходоваться все больше и больше системной памяти, и в конечном итоге перестанет выделяется. Такие приложения страдают от «утечек памяти». После определенного момента памяти уже не хватает для создания новых объектов, и программа нештатно завершается с OutOfMemoryError. GC строит дерево с рутами - уничтожает все до чего может дотянуться.

Память в JVM делится на 3 части:

• young generation (молодое поколение).

• old generation (старое поколение).

• metaspace (perm gen).

Young Generation

Область памяти для новых, вновь создаваемых объектов.

• когда область Young Generation заполняется, запускается минорная сборка мусора (Minor GC).

• при Minor GC "мертвые" объекты удаляются из Young Generation.

• чем больше "мертвых" объектов в Young Generation, тем быстрее выполняется Minor GC.

• при Minor GC происходит "остановка мира" (stop the world) — все потоки в приложении останавливаются.

Old Generation

Область памяти для долгоживущих объектов.

• как правило, эта область больше, чем область для Young Generation.

• при заполнении (или достижении заданного порога) происходит Major GC.

• обычно Major GC выполняются медленнее и реже, чем minor GC.

GC roots

Все объекты на которые прямо или косвенно ссылаются из gc roots не будут удалены.

• типы gs roots: классы, локальные переменные, активные потоки, ссылки JNI, некоторые другие объекты.

• если два объекта ссылаются друг на друга и больше на них никто не ссылается, то они будут удалены сборщиком мусора.

Reference Counting

Подсчет ссылок - техника управления памятью, которая используется в некоторых языках (не Java) для отслеживания того, сколько раз на объект ссылаются.

• Каждый объект имеет счетчик ссылок — переменную, которая увеличивается, когда объекту присваивают ссылку, и уменьшается, когда эта ссылка теряется.

• Когда счетчик ссылок объекта становится нулевым, он может быть удален из памяти, так как на него больше нет ссылок.

• Основная проблема с подсчетом ссылок — это циклические зависимости. Если два объекта ссылаются друг на друга, но больше нигде не используются, они не будут удалены, так как их счетчики ссылок не будут равны нулю.

finalize

Метод класса Object который вызывается перед удалением объекта из памяти (перед сборкой мусора). Его можно переопределить и в теле метода указать те действия которые должны быть выполнены перед уничтожением объекта.

StrongReference

Объект запрещен для удаления сборщиком мусора.

String s = "abc" // переменная s и есть strong-ссылка.
WeakReference

Объект уничтожится при ближайшей сборке мусора. Подходит для хранения ссылки на ClassLoader. Если нет классов для загрузки то нет смысла хранить ссылку.

• применение в Android - ссылка на Context.

get возвращает ссылку на объект.

clear удаляет ссылку на объект.

Counter counter = new Counter(); // strong reference
WeakReference<Counter> weakCounter = new WeakReference(counter); // weak reference
counter = null; // объект доступен для удаления сборщиком мусора
SoftReference

Уничтожится сборщиком мусора когда JVM потребуется память. Подходит для реализации кэшей. Может пережить несколько сборок мусора.

• применение в Android - кэш для картинок Bitmap.

get возвращает ссылку на объект.

clear удаляет ссылку на объект.

Counter counter = new Counter(); // strong reference
SoftReference<Counter> softCounter = new SoftReference(counter); // soft reference
counter = null; // объект доступен для сборщика мусора. будет удален когда потребуется память
PhantomReference

Используется в комбинации с ReferenceQueue. Используется для определения того, когда объект был удален из памяти, что помогает планировать задачи, чувствительные к памяти (дождаться удаления большого объекта, прежде чем загружать другой). Вручную улучшить процесс финализации, контролировать процесс очистки. Объект умер в JVM, но не исчез, а остался в нем “призраком” - на него хранится ссылка в ReferenceQueue.

• объект не удаляется из памяти пока его фантомная ссылка находится в очереди ReferenceQueue.

get возвращает null. объект фантомной ссылки всегда недоступен.

ReferenceQueue referenceQueue = new ReferenceQueue(); // ссылка будет храниться в этой очереди для очистки
Counter counter = new Counter(); // strong reference
PhantomReference<Counter> phantomCounter = new PhantomReference(counter, referenceQueue); // phantom reference
counter = null; // объект доступен для сборщика мусора. будет удален в любой момент
WeakHashMap

HashMap у которого ключи – это слабые ссылки – WeakReference. Пока на объекты которые ты хранишь в WeakHashMap в качестве ключей есть обычные (сильные или мягкие) ссылки, эти объекты будут живы.

WeakHashMap<Int, String> map = new WeakHashMap<Int, String>();
Java GC. Вопросы на собесе
  1. Что такое сборщик мусора в Java?

    Это механизм автоматического управления памятью, который освобождает память, занятую объектами, больше не доступными для программы, чтобы предотвратить утечки памяти и оптимизировать использование ресурсов.

  1. Как работает сборщик мусора?

    Сборщик мусора в Java работает путем отслеживания объектов в памяти, которые больше не имеют ссылок из активного кода. Когда такие объекты обнаруживаются, память, которую они занимают, освобождается.

  1. Что такое stop the world?

    Это пауза в работе приложения, когда сборщик мусора (Garbage Collector) приостанавливает выполнение всех потоков программы для выполнения операций по сборке мусора. Во время этой паузы приложение не может продолжать работу, что может вызывать задержки в его работе.

  1. Что триггерит запуск GC?

    GC может быть запущен при нехватке памяти, по запросу через System.gc(), или по достижении определенных порогов использования памяти (отслеживает создание новых объектов).

  1. Как GC проверяет, что объекты недоступны для сборки?

    GC проверяет доступность объектов, используя граф достижимости от корней (GC roots). Если объект не доступен из корней, он считается недоступным для использования и может быть собран.

  1. Если 2 объекта в Java ссылаются только друг на друга и не имеют ссылок из других объектов, будут ли они собраны сборщиком мусора?

    Да. GC может обнаруживать и собирать объекты, которые образуют циклические ссылки между собой, если они не достижимы из корней.

  1. Какие существуют типы ссылок?

    StrongReference WeakReference SoftReference PhantomReference

  1. Что такое утечка памяти?

    Ситуация когда объект больше не используется, но память под него остается выделенной.

  1. Как LeakCanary детектит утечки памяти?

    LeakCanary обнаруживает утечки памяти с помощью слабых ссылок и запуска сборщика мусора. После завершения жизненного цикла объекта создается слабая ссылка на него, и вызывается сборщик мусора. Если объект не удаляется, создается дамп памяти, который анализируется для поиска цепочек ссылок, удерживающих объект, что указывает на утечку.