Жизненный цикл объекта в Java это путь от создания до удаления: объект создается оператором new, живет и используется, пока на него есть хотя бы одна ссылка, а когда ссылок не остается, становится «мусором» и автоматически удаляется сборщиком мусора (Garbage Collector), который освобождает занятую память.
Привет! Думаю, ты не сильно удивишься, если тебе сказать, что размер памяти на твоем компьютере ограничен:)
Кратко
Жизненный цикл объекта: создание → жизнь (пока есть ссылки) → превращение в мусор → удаление сборщиком мусора.
При создании (new) JVM выделяет память, создает ссылку, инициализирует поля и вызывает конструктор.
Объект жив, пока на него есть хотя бы одна ссылка; когда ссылок не остается, он становится мусором.
Сборщик мусора (Garbage Collector, GC) автоматически удаляет ненужные объекты и освобождает память.
Перед удалением объекта JVM может (но не обязана) вызвать метод finalize(), поэтому полагаться на него нельзя.
Если ненужные объекты остаются достижимыми, GC не может их удалить, и возникает утечка памяти.
Даже жесткий диск, который в разы больше оперативной памяти, можно забить под завязку любимыми играми, сериалами и прочим. Чтобы этого не произошло, нужно следить за текущим состоянием памяти и удалять с компа ненужные файлы.
Какое отношение ко всему этому имеет программирование на Java? Прямое! Ведь при создании любого объекта Java-машиной под него выделяется память. В реальной большой программе создаются десятки и сотни тысяч объектов, под каждый из которых в памяти выделяется свой кусочек.Но как ты думаешь, сколько существуют все эти объекты? “Живут” ли они все время, пока работает наша программа? Разумеется, нет.
При всех достоинствах Java-объектов, они не бессмертны :) У объектов есть собственный жизненный цикл.
Сегодня мы чуть-чуть отдохнем от написания кода и рассмотрим этот процесс :) Тем более что он является очень важным для понимания работы программы и распоряжения ресурсами.
Кратко все этапы жизненного цикла объекта можно свести в таблицу:
Этап
Что происходит
Создание
по new JVM выделяет память, создает ссылку, инициализирует поля, вызывает конструктор
Жизнь
объект используется, пока на него есть хотя бы одна ссылка
Смерть (мусор)
ссылок не осталось (null или переприсвоение), объект становится мусором
Сборка
Garbage Collector удаляет объект и освобождает память (перед этим может вызвать finalize())
Как создается объект
Итак, с чего же начинается жизнь объекта? Как и у человека, с его рождения, то есть создания.
Cat cat =newCat();//вот сейчас и начался жизненный цикл нашего объекта Cat!
При создании объекта происходит несколько шагов:
Виртуальная Java-машина выделяет необходимый объем памяти под объект.
Создается ссылка на объект (в нашем случае cat), чтобы иметь возможность его отслеживать.
Инициализируются все переменные (поля) объекта.
Вызывается конструктор, и вот наш свежий объект уже живет своей жизнью :)
Срок жизни у объектов разный, точных цифр здесь не существует. В любом случае, в течение какого-то времени он живет внутри программы и выполняет свои функции.
Когда объект умирает
Если говорить точно, объект является “живым” пока на него есть ссылки. Как только ссылок не остается, объект “умирает”.
Например:
В методе main() объект машины Lamborghini Diablo перестает быть живым уже на второй строке. На него была всего одна ссылка, а теперь этой ссылке был присвоен null. Поскольку на Lamborghini Diablo не осталось ссылок, он становится “мусором”.
Ссылку при этом не обязательно обнулять:
Здесь мы создали второй объект, после чего взяли ссылку lamborghini и присвоили ей этот новый объект. Теперь на объект Lamborghini Gallardo указывает две ссылки, а на объект Lamborghini Diablo ни одной. Поэтому объект Diablo становится мусором.
Сборщик мусора (Garbage Collector)
И в этот момент в работу вступает встроенный механизм Java под названием сборщик мусора, или по-другому Garbage Collector, GC.
Сборщик мусора это внутренний механизм Java, который отвечает за освобождение памяти, то есть удаление из нее ненужных объектов.
Мы не зря выбрали для его изображения картинку с роботом-пылесосом. Ведь сборщик мусора работает примерно так же: в фоновом режиме он “ездит” по твоей программе, собирает мусор, и при этом ты с ним практически не взаимодействуешь.
Его работа это удалять объекты, которые уже не используются в программе. Таким образом он освобождает в компьютере память для других объектов. Помнишь в начале лекции мы говорили, что в обычной жизни тебе приходится следить за состоянием твоего компьютера и удалять старые файлы?
Так вот, в случае с Java-объектами сборщик мусора делает это вместо тебя.
Garbage Collector запускается многократно в течение работы твоей программы: его не надо вызывать специально и отдавать команды, хотя технически это возможно.
Позднее мы еще поговорим о нем и разберем процесс его работы более детально.
Метод finalize()
В момент, когда сборщик мусора добрался до объекта, перед самым его уничтожением, у объекта вызывается специальный метод, finalize().
Его можно использовать, чтобы освободить какие-то дополнительные ресурсы, которые использовал объект.
Метод finalize() принадлежит классу Object. То есть, наравне с equals(), hashCode() и toString(), с которыми ты уже познакомился ранее, он есть у любого объекта.
Его отличие от других методов в том, что он... как бы это сказать... весьма своенравен.
А именно: перед уничтожением объекта он вызывается далеко не всегда.
Программирование штука точная. Программист говорит компьютеру что-то сделать, компьютер это и делает. Ты, полагаю, уже привык к такому поведению, и тебе поначалу может быть сложно принять идею: “Перед уничтожением объектов вызывается метод finalize() класса Object. Или не вызывается. Как повезет!”
Тем не менее, это действительно так. Java-машина сама определяет, вызывать метод finalize() в каждом конкретном случае или нет.
Например, давай попробуем ради эксперимента запустить такой код:
publicclassCat{privateString name;publicCat(String name){this.name = name;}publicCat(){}publicstaticvoidmain(String[] args)throwsThrowable{for(int i =0; i <1000000; i++){Cat cat =newCat();
cat =null;//вот здесь первый объект становится доступен сборщику мусора}}@Overrideprotectedvoidfinalize()throwsThrowable{System.out.println("Объект Cat уничтожен!");}}
Мы создаем объект Cat и уже в следующей строчке кода обнуляем единственную ссылку на него. И так миллион раз.
Мы явно переопределили метод finalize(), и он должен миллион раз вывести строку в консоль, каждый раз перед уничтожением объекта Cat.
Но нет! Если быть точным, на моем компьютере он отработал всего 37346 раз! То есть только в 1 случае из 27-ми установленная у меня Java-машина принимала решение вызвать метод finalize(), в остальных случаях сборка мусора проходила без этого.
Попробуй запустить этот код у себя: скорее всего, результат будет отличаться.
Как видишь, finalize() трудно назвать надежным партнером :)
Поэтому небольшой совет на будущее: не стоит полагаться на метод finalize() в случае с освобождением каких-то критически важных ресурсов. Может JVM его вызовет, а может нет. Кто знает? Если твой объект при жизни занимал какие-то суперважные для производительности ресурсы, например, держал открытым соединение с базой данных, лучше создай в своем классе специальный метод для их освобождения и вызови его явно, когда объект уже будет не нужен. Так ты точно будешь знать, что производительность твоей программы не пострадает.
Важно: начиная с Java 9 метод finalize() официально признан устаревшим (deprecated) именно из-за его ненадежности. В современном коде для освобождения ресурсов используют конструкцию try-with-resources или явные методы очистки, а не finalize().
Утечка памяти
В самом начале мы сказали, что работа с памятью и удаление мусора очень важны, и это действительно так. Неподобающая работа с ресурсами и непонимание процесса сборки ненужных объектов могут привести к утечке памяти. Это одна из самых известных ошибок в программировании.
Неправильно написанный программистом код может привести к тому, что для вновь созданных объектов каждый раз будет выделяться новая память, при этом старые, ненужные объекты будут недоступны для удаления сборщиком мусора.
Раз уж мы привели аналогию с роботом пылесосом, представь, что будет, если перед запуском робота разбросать по дому носки, разбить стеклянную вазу и оставить на полу разобранный конструктор Lego. Робот, конечно, попытается что-то сделать, но в один прекрасный момент он застрянет.
Для его правильной работы нужно держать пол в нормальном состоянии и убирать оттуда все, с чем не справится пылесос.
По такому же принципу работает и сборщик мусора. Если в программе будет оставаться много объектов, которые он не может собрать (как носок или Lego для робота-пылесоса), в один прекрасный момент память закончится. И зависнет не только написанная тобой программа, но и все остальные программы, запущенные в этот момент на компьютере. Для них тоже не будет хватать памяти.
Вот так выглядят в Java жизненный цикл объектов и сборщик мусора. Это не нужно заучивать: достаточно просто понять принцип работы. В следующей лекции мы поговорим об этих процессах подробнее, а пока можешь вернуться к решению задач JavaRush :) Успехов!
Подробнее о методе можно почитать в документации Oracle (класс Object).
Это путь объекта от создания до удаления: он создается оператором new, живет и используется, пока на него есть ссылки, а когда ссылок не остается, становится мусором и удаляется сборщиком мусора.
Что происходит при создании объекта?
JVM выделяет память под объект, создает на него ссылку, инициализирует поля значениями и вызывает конструктор. После этого объект готов к работе.
Когда объект становится мусором?
Когда на него не остается ни одной ссылки: например, ссылке присвоили null или перенаправили ее на другой объект. Такой объект недостижим и подлежит удалению.
Что такое сборщик мусора (Garbage Collector)?
Это встроенный механизм Java, который в фоновом режиме находит объекты без ссылок и удаляет их, освобождая память. Вызывать его вручную не нужно.
Можно ли полагаться на метод finalize()?
Нет. JVM вызывает finalize() перед удалением объекта не всегда, а начиная с Java 9 метод считается устаревшим. Ресурсы лучше освобождать явно или через try-with-resources.
Что такое утечка памяти?
Это ситуация, когда ненужные объекты остаются достижимыми по ссылкам, поэтому сборщик мусора не может их удалить. Память постепенно заканчивается, и программа может зависнуть.
Senior Java-разработчик и преподаватель в LearningTree
Senior Java-разработчик и преподаватель Java на курсах программирования Learning Tree International. Иногда пишу всякие глупости п ... [Читать полную биографию]
+1355
Комментарии (211)
популярные
новые
старые
Для того, чтобы оставить комментарий Вы должны авторизоваться
Метод finalize():
Вызывался перед сборкой мусора (GC),
Устарел начиная с Java 9, и помечен как @Deprecated(forRemoval = true) с Java 18+,
Вместо него используют AutoCloseable или try-with-resources.
про @Override пропустил или не видел, что это и для чего... в заданиях тоже в подсказках он был, но я проходил задания, не используя его... так вот, нужно его использовать и в каких моментах, если нужно?
Если в двух словах то это специальная метка, которой помечается метод который мы переопределяем. В данном примере меткой помечен метод finalize(), который есть в классе Object. Так как класс Object это класс родитель для всех классов в Java , то этод метод есть в любом создаваемом классе, мы просто пишем свою реализацию метода. А метку ( или правильнее аннотацию) указываем просто для того что бы компилятор проверил что мы не допустили ошибки, и переопределяем метод именно класа родителя. Если мы напишем метод
Начиная с Java 9, метод finalize() помечен как устаревший (deprecated), поскольку его использование может вызывать проблемы с производительностью и управлением ресурсами.
Вместо него рекомендуется использовать такие механизмы, как try-with-resources (для автозакрытия ресурсов) или явное управление жизненным циклом объекта.
Ваш пример показывает принцип работы сборщика мусора, но не всегда вызовет вывод сообщения. Для обучения это полезный код, но в реальных проектах лучше использовать современные методы управления памятью и ресурсами.
вот вопрос "" То есть только в 1 случае из 27-ми установленная у меня Java-машина принимала решение вызвать метод finalize() — в остальных случаях сборка мусора проходила без этого. ""
Это ведь значит что все объекты удалены. Просто метод finalize не вызван. Так для чего нам руками удалять?
Речь шла не об удалении объектов - объекты сборщик мусора сам удалит. Насколько понимаю, автор пишет о том, что если объект задействовал какой-то ценный или критический ресурс, то для надёжности нужно позаботиться об освобождении этого ресурса, перед тем как зачистить ненужный уже объект.
Например, объекту нужно прочитать данные из таблицы базы данных. Он заблокировал эту таблицу, чтобы какой-то другой объект не вносил туда изменения, пока он читает. Потом выполнил свою работу и "умер". GC убрал мусор. А таблица в базе данных осталась заблокированной. Тоже самое открытые файлы или порты для передачи данных.
"Если говорить точно, объект является “живым” пока на него есть ссылки."
Для автора статьи такое утверждение - серьёзная ошибка.
Следует понимать, что объект является "живым" до тех пор, пока он является достижимым.
Наличие ссылок на объект не является признаком того, что он "жив".
А у меня всего 14868 😵. Но можно ли сказать что все остальные живы ? Если не используется метод - ( finalize() ), разве можно сказать что объект остался жив ?