weakReference

Java Collections
4 уровень , 5 лекция
Открыта

— И снова здравствуйте!

Сейчас я расскажу тебе еще про одну замечательную штуку — WeakReference – слабые ссылки.

Выглядит она почти так же, как и SoftReference:

Пример
//создание объекта Cat
Cat cat = new Cat();

//создание слабой ссылки на объект Cat
WeakReference<Cat> catRef = new WeakReference<Cat>(cat);

//теперь на объект ссылается только слабая ссылка catRef.
cat = null; 

//теперь на объект ссылается еще и обычная переменная cat
cat = catRef.get();

//очищаем слабую ссылку
catRef.clear();

У слабой ссылки есть другая особенность.

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

— А можно еще раз, в чем отличия между этими ссылками?

— Объект, который удерживает от смерти только SoftReference может пережить сколько угодно сборок мусора и скорее всего, будет уничтожен при нехватке программе памяти.

Объект, который удерживает от смерти только WeakReference не переживает ближайшей сборки мусора. Но пока она не произошла, его можно получить, вызвав метод get() у WeakReference и вызвать его методы или сделать что-нибудь еще.

— А если на объект ссылаются и SoftReference и WeakReference?

— Тут все просто. Если на объект есть хотя бы одна обычная ссылка – он считается живым. Такие ссылки, кстати, называются StrongReference.

Если на объект нет обычных ссылок, но есть SoftReference, то он – SoftReference.

Если на объект нет обычных ссылок и SoftReference, но есть WeakReference, то он – WeakReference.

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

— Ага. Вроде понятно.

— Отлично, тогда расскажу тебе про еще одну занимательную штуку с использованием WeakReference – это WeakHashMap.

— Звучит серьезно!

— А то! WeakHashMap – это HashMap, у которого ключи – это слабые ссылки – WeakReference.

Т.е. ты добавляешь в такой HashMap объекты и работаешь с ними. Все как обычно.

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

Но, представь, что во всем приложении больше не осталось ссылок на эти объекты. Все что удерживает их от смерти – это несколько WeakReference внутри WeakHashMap. Тогда после ближайшей очистки мусора такие объекты исчезнут из WeakHashMap. Сами. Как будто их там и не было.

— Не уверен, что понял.

— Ты хранишь в WeakHashMap пары объектов – ключ и значение. Но WeakHashMap ссылается на ключи не прямо, а через WeakReference. Поэтому, когда объекты, используемые в качестве ключей, станут слабодостижимыми, они уничтожатся при ближайшей сборке мусора. А значит, из WeakHashMap автоматически удалятся и их значения.

В WeakHashMap очень удобно хранить дополнительную информацию к каким-то объектам.

Во-первых, ее очень легко получить, если использовать сам объект в качестве ключа.

Во-вторых, если объект будет уничтожен, из HashMap исчезнет и он, и все привязанные к нему данные.

Пример:

Пример
//создаем объект для хранения дополнительной информации о пользователе
WeakHashMap<User, StatisticInfo> userStatistics = new WeakHashMap<User, StatisticInfo>();

//кладем информацию о пользователе в userStatistics
User user = session.getUser();
userStatistics.put(user, new StatisticInfo (…));

//получаем информацию о пользователе из userStatistics
User user = session.getUser();
StatisticInfo statistics = userStatistics.get(user);

//удаление любой информации о пользователе из userStatistics
User user = session.getUser();
userStatistics.remove(user);
  1. Внутри WeakHashMap ключи хранятся в виде WeakReference.
  2. Как только объект user будет уничтожен сборщиком мусора, в WeakHashMap неявно вызовется метод remove(user) и любая «привязанная» к объекту user информация, будет удалена из WeakHashMap автоматически.

— Выглядит как мощный инструмент. А где можно его использовать?

— По обстоятельствам. Ну, допустим, у тебя в программе есть нить, которая отслеживает работу некоторых объектов-заданий и пишет информацию о них в лог. Тогда эта нить может хранить отслеживаемые объекты в таком WeakHashMap. Как только объекты станут не нужны, сборщик мусора удалит их, автоматически удалятся и ссылки на них из WeakHashMap.

— Звучит интересно. Сразу чувствуется, ну не писал я еще серьезных программ на Java, чтобы задействовать такие мощные механизмы. Но я буду расти в эту сторону, спасибо большое, Элли, за такой интересный урок.

Комментарии (38)
ЧТОБЫ ПОСМОТРЕТЬ ВСЕ КОММЕНТАРИИ ИЛИ ОСТАВИТЬ КОММЕНТАРИЙ,
ПЕРЕЙДИТЕ В ПОЛНУЮ ВЕРСИЮ
Assanali Уровень 29
7 апреля 2025
на работе один синьор такой код написал

  public static void gc() {
    Object obj = new Object();
    WeakReference<Object> ref = new WeakReference<>(obj);
    obj = null;
    while (ref.get() != null) {
      System.gc();
    }
  }
но до этого я не видел использований SoftReference, WeakReference работаю несколько лет
{Java_Shark} Уровень 36
12 февраля 2025
++
Scarry-77 Уровень 42
13 сентября 2024
Кстати, если сделать так, чтобы на объект ссылалась только слабая ссылка, и еще вызвать сборщик мусора, можно увидеть, что объект будет действительно удален:

Cat cat = new Cat();
WeakReference<Cat> ref = new WeakReference<>(cat);

cat = null;

System.gc(); // вызовет Сборщик мусора и удалит объект

System.out.println(ref.get()); // null
LE_Anonymous #3029647 Уровень 38
1 марта 2023
Василий Чи Уровень 51
16 января 2023
Какое "спасибо, Элли"? Что ещё за session???
safelogj Уровень 51
30 сентября 2024
😁
10 марта 2022
Второй пример немного неточен. Код в нем указан как бы в одном месте. Но данный код не будет работать в одном методе. Подразумевается, что строки 5-6 используются в одном месте, строки 9-10 где-то в другом месте (другой метод или даже другая программа), тоже и строки 13-14. Целесообразно разделить пример на 3 отдельных фрейма или вообще на 3 метода.
LuneFox Уровень 41 Expert
22 января 2022
Получается, я с тем же успехом могу пользоваться обычной мапой, просто должен буду ещё вручную удалять объекты, которые уже не нужны, да?
Stepan Уровень 27
30 января 2022
Судя по тексту - нет. На сколько я понял самостоятельно удаленный объект вполне себе может пережить сборку мусора, если он ранее пережил множество очисток памяти, т.е. он далеко не первого поколения и потому считается долгожителем, а значит на него сборщик мусора обрати внимание не сразу. Тогда как "WeakReference не переживает ближайшей сборки мусора".
LuneFox Уровень 41 Expert
30 января 2022
Хочешь сказать, что старый, но недостижимый ветеран сбора мусора будет ещё какое-то время держаться в памяти по непонятной причине? А смысл?
Stepan Уровень 27
31 января 2022
Цитата: "Сборщик Мусора очень — сложная и эффективная составляющая Java. Многие его части работают эвристически – на основе алгоритмов-догадок. Поэтому он часто «не слушается» пользователя." Смысл вижу только один - не занимать время ЦП на тотальные заботы о мусоре. Я считаю, что сборщик мусора просматривает долгоживущие объекты несколько реже. Вообще надо найти время и разобраться со всеми премудростями работы сборщика мусора.
Нейросеть Уровень 41
14 декабря 2022
Мне как то один препод с другого курса тоже объяснял, что если объект пережил достаточно сборок, то скорей всего сборшик мусора перестанет обращать на него внимание вообще.
3 января 2021
Спасибо, Элли! Хоть кто-то вспомнил, что квест называется "Java Collections".
Евгений Уровень 2 Expert
27 июня 2020
Вроде бы всё понятно. Мапа, которую лучше всего использовать для метаданных (данных об объекте или о других данных). В качестве ключа используем целевой объект, и как только объект будет удалён сборщиком мусора, нам не надо париться с удалением информации о нём из мапы - она также автоматически будет удалена сборщиком мусора.