Пользователь Diana
Diana
41 уровень

Сборка мусора

Статья из группы Архив info.javarush.ru

Линия поведения сборщика мусора (утилизатора памяти)

Java-программисту не нужно следить за распределением памяти, так как сборщик мусора управляет памятью автоматически. Сборщик мусора запускается виртуальной машиной Java (JVM). Сборщик мусора — это низкоприоритетный процесс, который запускается периодически и освобождает память, использованную объектами, которые больше не нужны. Сборка мусора - 1Разные JVM имеют отличные друг от друга алгоритмы сбора мусора. Существует несколько используемых алгоритмов, например: алгоритм подсчёта ссылок или алгоритмы разметки и очистки. Подробнее о сборщике мусора см. Ресурсы.

Запуск сборщика мусора

JVM обычно запускает сборщик мусора при низком уровне свободной памяти. Но работа сборщика мусора не гарантирует, что всегда будет оставаться достаточно свободной памяти. Если памяти недостаточно даже после восстановления, JVM генерирует исключение OutOfMemoryError. Обратите внимание, что перед генерированием исключения JVM обязательно запускает сборщик мусора как минимум 1 раз. Вы можете запросить запуск сборщика мусора, но вы не можете принудительно задавать это действие.

Запрос запуска сборщика мусора

Для запроса вы можете вызвать один из следующих методов:

System.gc()
Runtime.getRuntime().gc()

Пригодность для запуска сборщика мусора

Объект подлежит утилизации, когда он недоступен живому потоку. Объект может подлежать утилизации в разных случаях:
  • Если переменная ссылочного типа, которая ссылается на объект, установлена в положение "0", объект подлежит утилизации, в том случае, если на него нет других ссылок.
  • Если переменная ссылочного типа, которая ссылается на объект, создана для ссылки на другой объект, объект подлежит утилизации, в том случае, если на него нет других ссылок.
  • Объекты, созданные локально в методе, подлежат утилизации, когда метод завершает работу, если только они не экспортируются из этого метода (т.е, возвращаются или генерируются как исключение).
  • Объекты, которые ссылаются друг на друга, могут подлежать утилизации, если ни один из них не доступен живому потоку.
Рассмотрим пример:

public class TestGC
  {	
    public static void main(String [] args)  
    {
      Object o1 = new Integer(3);               // Line 1
      Object o2 = new String("Tutorial");       // Line 2
      o1 = o2;                                  // Line 3
      o2 = null;                                // Line 4
      // Rest of the code here
    }
  }
В этом примере объект Integer (целочисленный), на который первоначально ссылается указатель o1 может подвергаться утилизации после строки 3, так как o1 теперь ссылается на объект String (строковый). Несмотря на то, что o2 создан для ссылки к нулю, объект String (строковый) не подлежит утилизации, так как o1 ссылается на него.

Финализация

Java-технология позволяет использовать метод finalize() (финализировать), чтобы произвести необходимую очистку перед тем, как сборщик мусора извлекает объект из памяти. Этот метод вызывается для объекта сборщиком мусора, когда сборщик мусора вычисляет, что ссылок к объекту больше нет. Это описано в классе Object, а значит, это наследуется всеми классами. Подкласс отменяет метод finalize(), чтобы освободиться от системных ресурсов или для ещё одной очистки:

protected void finalize() throws Throwable
Если незарегистрированное исключение генерируется методом finalize(), то исключение игнорируется и финализация этого объекта прекращается. Метод finalize() будет активизирован только один раз за время существования объекта. Возможно использование метода finalize() любого объекта, чтобы защитить его от утилизации. Но в этом случае сборщик мусора уже не активирует finalize() для этого объекта. Метод finalize() всегда будет активизирован один раз перед тем, как объект будет удалён сборщиком мусора. Однако, возможно, что метод finalize() не будет активизирован для данного объекта за всё время его существования, так как он может не подлежать утилизации.

Резюме

В этом разделе мы рассмотрели процесс сборки мусора, который относится к технике управления памятью языка Java. Сборка мусора не может быть задана принудительно. Мы познакомились с различными способами обращения объектов в подлежащие утилизации и узнали, что метод finalize() активизируется перед тем, как объект извлекается сборщиком мусора.

Упражнение

Вопрос: Сколько объектов будут подлежать утилизации после строки 7?

public class TutorialGC
  {
    public static void main(String [] args)
    {
      Object a = new Integer(100);  // Line1
      Object b = new Long(100);     // Line2
      Object c = new String("100"); // Line3
      a = null;                     // Line4
      a = c;                        // Line5
      c = b;                        // Line6
      b = a;                        // Line7
      // Rest of the code here
    }
  }
Варианты ответа: A. 0 B. 1 C. 2 D. 3 E. Код не возможно скомпилировать Правильный вариант: B Пояснение: из трёх объектов, созданных в строках 1, 2 и 3, только объект Integer подлежит утилизации в конце строки 7. Переменная ссылки, a, которая первоначально ссылалась на объект Integer, ссылается на объект String в строке 5. Таким образом, Integer oбъект подлежит утилизации после строки 5, так как нет переменных, которые ссылаются на него. Переменные b и c ссылаются на объекты String и Long объекты в строках 6 и 7, поэтому они не подлежат утилизации. Источник
Комментарии (93)
Чтобы просмотреть все комментарии или оставить свой,
перейдите в полную версию
Vitaly Khan 40 уровень Master
17 декабря 2019
/* Комментарий удален */
Адиль 20 уровень, Санкт-Петербург
22 июля 2019
finalize() уже давно deprecated. Так что про него даже читать не стоит. Если попробуете переопределить его в одном из своих классов в IDEA, то его название будет перечёркнуто. Это означает, что метод устарел.
Денис 9 уровень, Москва
28 мая 2019
В разделе статьи "Финализация" вообще ничего не понимаю - попал отсюда из 6ур, но упражнение сделал верно
Илья 14 уровень
28 апреля 2019
finalize() чем-нибудь отличается от деструктора в C++?
Yaroslav Tikhonov 14 уровень, Санкт-Петербург
22 апреля 2019
Если я правильно понял, то finalize() это как последнее дыхание перед смертью объекта? Запускается один раз и как раз перед тем, как объект уничтожится сборщиком мусора. Однако, при этом с помощью finalize() и Throwable возможно создавать исключения, которые не позволят сборщику уничтожить объект. Вопрос: в каком сценарии в жизни нам это понадобится на практике? Ну в какой ситуации я точно должен знать, что пора вспомнить лекции о сборе мусора в JVM?
Eduard 8 уровень
17 апреля 2019
Если переменная ссылочного типа, которая ссылается на объект, создана для ссылки на другой объект, объект подлежит утилизации, в том случае, если на него нет других ссылок. Как это!? Ссылается на обьект, но создана для ссылки на другой обьект. Какой другой обьект? Никак не могу вьехать! Поясните кто может на более простом, пожалуйста.
Папонт 18 уровень, Самара
30 марта 2019
>Если переменная ссылочного типа, которая ссылается на объект, установлена в положение "0" за такое убивать надо (
Myroslav Kravchenko 8 уровень
19 марта 2019
Рубрика : "Кто не понял,тот поймет"))
Sumeria 19 уровень
17 марта 2019
Данная статья по сути -- вторая лекция шестого уровня. Если последовательно изучать все материалы курса, то первое описание о finalize() появляется именно здесь. Речь идёт об изучении Java с самого начала курса. За это время встречались разные типы информации: статьи, ссылки, книги, задания. Но -- мало ссылок непосредственно на Java docs. А это -- один из основных и первых источников информации для любого разработчика. К тому же, английский -- один из нужных пунктов для будущей работы Java dev'ом. Думаю, данный случай о finalize() -- очень показательный случай, когда можно за основу взять именно оригинальную ссылку и добавить перевод: https://docs.oracle.com/javase/7/docs/api/java/lang/Object.html#finalize%28%29 По сборщику мусора в целом та же история. Taras Kutselya добавил ряд ссылок в комментариях к лекции https://javarush.ru/quests/lectures/questsyntax.level06.lecture02 Можно использовать/добавить их, например. Если цель статьи -- не просто перевод небольшого отрывка, а интеграция нескольких источников, тогда статью нужно переделать. Добавить определений, развернуть описание самого GC, напомнить (или рассказать) о его структуре, показать на диаграмме время жизни объекта. И уже именно в такой развёртке показать варианты развития событий в судьбе объекта с разными вариациями finalize() в Object или наследниках. Плюсы статьи: упражнение по теории. Подобный подход стоит и в другие лекции заимствовать.
13 марта 2019
Кто не понял темы может сразу мусорщиком устроится ) Мотивация учится и понимать точно поднимется )))