Как узнать, что память, которую занимал объект, освобождена? | OTUS
⚡ Подписка на курсы OTUS!
Интенсивная прокачка навыков для IT-специалистов!
Подробнее

Курсы

Программирование
Алгоритмы и структуры данных Team Lead Архитектура и шаблоны проектирования Разработчик IoT C# Developer. Professional PostgreSQL Разработчик на Spring Framework
-5%
Flutter Mobile Developer NoSQL iOS Developer. Basic
-10%
C++ Developer. Basic C++ Developer. Professional Android Developer. Professional Microservice Architecture Unity Game Developer. Professional Базы данных Node.js Developer React.js Developer Специализация Java-разработчик
-25%
Web-разработчик на Python Framework Laravel Cloud Solution Architecture Vue.js разработчик Интенсив «Оптимизация в Java» Супер - интенсив по паттернам проектирования Супер - интенсив по Kubernetes Супер-интенсив "Tarantool" PHP Developer. Basic
Инфраструктура
Мониторинг и логирование: Zabbix, Prometheus, ELK Administrator Linux. Professional Дизайн сетей ЦОД Разработчик IoT PostgreSQL Экспресс-курс "Версионирование и командная работа с помощью Git"
-30%
Microservice Architecture Highload Architect Специализация Administrator Linux
-25%
Network engineer Cloud Solution Architecture Внедрение и работа в DevSecOps Супер-практикум по работе с протоколом BGP Супер - интенсив по паттернам проектирования Супер - интенсив по Kubernetes Супер-интенсив «СУБД в высоконагруженных системах» Супер-интенсив "Tarantool" Network engineer. Basic
Корпоративные курсы
Безопасность веб-приложений IT-Recruiter Дизайн сетей ЦОД Компьютерное зрение Разработчик IoT Вебинар CERTIPORT Machine Learning. Professional
-6%
NoSQL Пентест. Практика тестирования на проникновение Java QA Engineer. Базовый курс Руководитель поддержки пользователей в IT
-8%
SRE практики и инструменты Cloud Solution Architecture Внедрение и работа в DevSecOps Супер-практикум по работе с протоколом BGP Infrastructure as a code Супер-практикум по использованию и настройке GIT Промышленный ML на больших данных Экспресс-курс «CI/CD или Непрерывная поставка с Docker и Kubernetes» BPMN: Моделирование бизнес-процессов Основы Windows Server
Специализации Курсы в разработке Подготовительные курсы Подписка
+7 499 938-92-02

Как узнать, что память, которую занимал объект, освобождена?

Java_Deep_9.08_Site.png

В некоторых языках сделать это очень просто: вызвал delete, и можешь быть уверен – памяти стало больше. В Java всё немного сложнее.

С одной стороны, отлично, что нам не нужно писать delete «ручками». GC всё сделает за тебя. Потерял ссылку на объект и ничего страшного! Память будет освобождена и без ссылки. Утечки не будет. С другой стороны, очень хочется иногда написать delete, но нет такой возможности.

И, в самом деле, как узнать, что объект удалён?

Можно подписаться на события GC. Но они не про конкретный объект, а про событие для всех объектов. Можно переопределить finalize() (у всех классов он есть) и обработать событие в нём.

Но если таких объектов будет много, это может сильно снизить скорость работы GC. А медленный GC – это большие паузы в работе всего приложения. К счастью в Java есть отличный способ узнать о том, что объект удалён.

Phantom reference

Фантомная ссылка — объект класса java.lang.ref.PhantomReference. Объект, на который существуют только фантомные ссылки, доступен сборщику мусора. Фантомная ссылка не даёт пользователю возможности «спасти» объект, создав на него сильную ссылку: метод get на ней всегда возвращает null.

Зато с помощью фантомной ссылки можно определить, что объект собирается быть удалён. В силу этих особенностей фантомная ссылка бесполезна без объекта ReferenceQueue, поэтому для неё определён единственный конструктор:

ReferenceQueue<Wiki> queue = new ReferenceQueue<Wiki>(); //создание очереди 
PhantomReference<Wiki> ref = new PhantomReference<Wiki>(new Wiki("cyclowiki.org"), queue);

Основное предназначение фантомных ссылок — замена методу finalize, имеющему большое количество недостатков. С их помощью можно реализовать логику подготовки объекта к удалению, например освобождение захваченных им ресурсов, очистка сессии, сохранение состояния или логгирование.

Фантомная ссылка, указывающая на удаляемый объект, попадает в ReferenceQueue, откуда она может быть извлечена. Поскольку базовая фантомная ссылка не предоставляет пользователю возможности определить, на какой именно объект она ссылается, стоит реализовывать собственного потомка класса PhantomReference, хранящего идентификатор объекта (не ссылку на сам объект, ибо это будет сильная ссылка — объект перестанет быть доступен сборщику мусора).

В таком случае после обращения к идентификатору можно однозначно определить, какой объект был удалён, и выполнить все необходимые операции.

Проще говоря

Phantom reference – тоже ссылка на объект, как и нормальная ссылка. Но у нее всё по-своему. Получить объект по ней нельзя. Но можно найти её в специальном пуле ссылок для удалённых объектов. Создали ссылку, подождали GC, проверили в пуле. Если она там есть, значит объект был удалён.

А какие еще типы ссылок есть в Java? И зачем они нужны?

Знаете? Напишите в комментариях!

Не пропустите новые полезные статьи!

Спасибо за подписку!

Мы отправили вам письмо для подтверждения вашего email.
С уважением, OTUS!

Автор
0 комментариев
Для комментирования необходимо авторизоваться