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

Мягкие ссылки в Java

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

1. Обзор

В этой быстрой статье мы поговорим о мягких ссылках в Java.

Мы объясним, что это такое, зачем они нужны и как их создать.

2. Что такое мягкие ссылки?

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

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

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

Эти правила различаются от одной реализации JVM к другой, но в документации указано, что все программные ссылки на мягко достижимые объекты гарантированно очищаются до того, как JVM выдаст ошибку OutOfMemoryError.

Тем не менее, нет никаких гарантий в отношении времени очистки программной ссылки или порядка очистки набора таких ссылок на разные объекты.

Как правило, реализации JVM выбирают между очисткой недавно созданных или недавно использованных ссылок.

Мягкодоступные объекты будут оставаться активными в течение некоторого времени после последней ссылки на них. Значение по умолчанию — одна секунда жизни на каждый свободный мегабайт в куче. Это значение можно изменить с помощью флага -XX:SoftRefLRUPolicyMSPerMB .

Например, чтобы изменить значение на 2,5 секунды (2500 миллисекунд), мы можем использовать:

-XX:SoftRefLRUPolicyMSPerMB=2500

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

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

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

Мягкие ссылки можно использовать для реализации кэшей, чувствительных к памяти, где управление памятью является очень важным фактором.

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

Кэш может, например, предотвратить отбрасывание самых последних использованных записей, сохраняя сильные ссылки на эти записи, оставляя оставшиеся записи отброшенными на усмотрение сборщика мусора.

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

В Java мягкая ссылка представлена классом java.lang.ref.SoftReference .

У нас есть два варианта его инициализации.

Первый способ — передать только референт:

StringBuilder builder = new StringBuilder();
SoftReference<StringBuilder> reference1 = new SoftReference<>(builder);

Второй вариант подразумевает передачу ссылки на java.lang.ref.ReferenceQueue , а также ссылку на референт. Справочные очереди предназначены для информирования нас о действиях, выполняемых сборщиком мусора. Он добавляет объект ссылки в очередь ссылок, когда решает удалить референт этой ссылки.

Вот как инициализировать SoftReference с помощью ReferenceQueue:

ReferenceQueue<StringBuilder> referenceQueue = new ReferenceQueue<>();
SoftReference<StringBuilder> reference2
= new SoftReference<>(builder, referenceQueue);

Как java.lang.ref.Reference , он содержит методы get и clear для получения и сброса референта соответственно:

StringBuilder builder1 = reference2.get();
reference2.clear();
StringBuilder builder2 = reference2.get(); // null

Каждый раз, когда мы работаем с такого рода ссылками, нам нужно убедиться, что референт, возвращаемый функцией get , присутствует:

StringBuilder builder3 = reference2.get();
if (builder3 != null) {
// GC hasn't removed the instance yet
} else {
// GC has cleared the instance
}

5. Вывод

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

Кроме того, мы научились создавать его и работать с ним программно.