Ответ
SoftReference<T> в Java — это ссылка, объект по которой может быть удалён сборщиком мусора (GC) только при нехватке памяти. Это делает её идеальной для реализации кэшей в памяти, которые автоматически освобождают ресурсы под давлением GC.
Ключевое отличие от других ссылок:
- Strong reference (
Object obj = new Object()): объект не удаляется, пока на него есть сильная ссылка. - SoftReference: объект удаляется, только если JVM не хватает памяти (перед
OutOfMemoryError). - WeakReference: объект удаляется при следующем цикле GC, независимо от памяти.
- PhantomReference: используется для отслеживания факта удаления (после финализации).
Практические сценарии:
-
Кэширование дорогостоящих или больших объектов
public class ImageCache { private Map<String, SoftReference<BufferedImage>> cache = new HashMap<>(); public BufferedImage getImage(String path) { SoftReference<BufferedImage> ref = cache.get(path); BufferedImage img = (ref != null) ? ref.get() : null; if (img == null) { img = loadImageFromDisk(path); // Дорогая операция cache.put(path, new SoftReference<>(img)); } return img; } } -
Хранение временных данных в memory-sensitive приложениях
- Кэш результатов вычислений, которые можно пересчитать.
- Временное хранение десериализованных объектов.
Важные нюансы:
- GC удаляет объекты
SoftReferenceне гарантированно и в неопределённый момент. - Для предсказуемости часто используют
ReferenceQueue. - В современных приложениях часто предпочитают специализированные кэши (Caffeine, Guava Cache), которые внутри могут использовать
SoftReference.
Пример с ReferenceQueue:
ReferenceQueue<BigObject> queue = new ReferenceQueue<>();
SoftReference<BigObject> softRef = new SoftReference<>(new BigObject(), queue);
// Поток, очищающий Map от удалённых ссылок
new Thread(() -> {
while (true) {
try {
Reference<? extends BigObject> ref = queue.remove();
// Удалить ref из кэша
} catch (InterruptedException e) { /* ... */ }
}
}).start();
Итог: SoftReference — это механизм уровня JVM для создания «безопасных» кэшей, которые автоматически освобождают память под давлением, предотвращая OutOfMemoryError.