Перейти к основному содержимому

Слабые ссылки в Java

· 3 мин. чтения

1. Обзор

В этой статье мы рассмотрим концепцию слабой ссылки в языке Java.

Мы собираемся объяснить, что это такое, для чего они используются и как правильно с ними работать.

2. Слабые ссылки

Объект со слабой ссылкой очищается сборщиком мусора, когда он слабо доступен.

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

Во-первых, сборщик мусора очищает слабую ссылку, поэтому ссылка больше недоступна. Затем ссылка помещается в очередь ссылок (если таковая существует), откуда мы можем ее получить.

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

2.1. Слабые и мягкие ссылки

Иногда разница между слабыми и мягкими ссылками неясна. Мягкие ссылки — это, по сути, большой кэш LRU. То есть мы используем мягкие ссылки, когда референт имеет хорошие шансы быть повторно использованным в ближайшем будущем .

Поскольку мягкая ссылка действует как кеш, она может оставаться доступной, даже если сам референт недоступен. На самом деле программная ссылка подлежит сбору тогда и только тогда, когда:

  • Референт не сильно достижим
  • Мягкая ссылка в последнее время не используется

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

3. Варианты использования

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

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

Для получения дополнительной информации ознакомьтесь с нашим руководством по WeakHashMap .

Еще одна область, где их можно использовать, — проблема просроченного слушателя .

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

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

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

4. Работа со слабыми ссылками

Слабые ссылки представлены классом java.lang.ref.WeakReference . Мы можем инициализировать его, передав референт в качестве параметра. При желании мы можем предоставить java.lang.ref.ReferenceQueue :

Object referent = new Object();
ReferenceQueue<Object> referenceQueue = new ReferenceQueue<>();

WeakReference weakReference1 = new WeakReference<>(referent);
WeakReference weakReference2 = new WeakReference<>(referent, referenceQueue);

Референт ссылки может быть получен методом get и удален вручную с помощью метода clear :

Object referent2 = weakReference1.get();
weakReference1.clear();

Схема безопасной работы с такого рода ссылками такая же, как и с программными ссылками :

Object referent3 = weakReference2.get();
if (referent3 != null) {
// GC hasn't removed the instance yet
} else {
// GC has cleared the instance
}

5. Вывод

В этом кратком руководстве мы рассмотрели низкоуровневую концепцию слабой ссылки в Java и сосредоточились на наиболее распространенных сценариях их использования.