Для чего используют Weak Reference?
Комментарии (1)
Ответ сгенерирован нейросетью и может содержать ошибки
Weak Reference в Java
Weak Reference (слабая ссылка) — это тип ссылки на объект, которая не препятствует сборке мусора (garbage collection). Это инструмент для управления памятью, который полезен в специфических сценариях кэширования и метаинформации.
Основная проблема, которую решают Weak References
Обычная (strong) ссылка предотвращает сборку мусора объекта. Если вы кэшируете объекты и на них есть strong ссылки, они никогда не будут удалены, что приводит к утечкам памяти:
// Плохой подход — memory leak
public class ObjectCache {
private Map<String, SomeObject> cache = new HashMap<>();
public void add(String key, SomeObject obj) {
cache.put(key, obj); // Strong reference — объект никогда не будет удалён
}
public SomeObject get(String key) {
return cache.get(key);
}
}
Решение: WeakHashMap и WeakReference
Weak Reference позволяет объекту быть собран сборщиком мусора, даже если на него есть ссылка в кэше:
import java.lang.ref.WeakReference;
import java.util.WeakHashMap;
// Вариант 1: WeakHashMap
public class SmartCache<K, V> {
private WeakHashMap<K, V> cache = new WeakHashMap<>();
public void put(K key, V value) {
cache.put(key, value);
}
public V get(K key) {
return cache.get(key);
}
}
// Вариант 2: явное использование WeakReference
public class ExplicitWeakRefCache<K, V> {
private Map<K, WeakReference<V>> cache = new HashMap<>();
public void put(K key, V value) {
cache.put(key, new WeakReference<>(value));
}
public V get(K key) {
WeakReference<V> ref = cache.get(key);
if (ref == null) return null;
V value = ref.get();
if (value == null) {
cache.remove(key);
}
return value;
}
}
Когда использовать Weak References
1. Кэширование метаинформации о классах
// Spring Framework использует WeakHashMap для кэша методов
private static final WeakHashMap<Class<?>, Method[]> methodCache =
new WeakHashMap<>();
2. Listener'ы и Observer'ы
public class EventBus {
private List<WeakReference<EventListener>> listeners = new ArrayList<>();
public void subscribe(EventListener listener) {
listeners.add(new WeakReference<>(listener));
}
public void publish(Event event) {
listeners.removeIf(ref -> ref.get() == null);
for (WeakReference<EventListener> ref : listeners) {
EventListener listener = ref.get();
if (listener != null) {
listener.onEvent(event);
}
}
}
}
3. Кэширование объектов с долгим жизненным циклом
public class DataObjectCache {
private WeakHashMap<String, DataObject> cache = new WeakHashMap<>();
public DataObject loadOrCache(String id) {
return cache.computeIfAbsent(id, k -> {
return loadFromDatabase(k);
});
}
}
Иерархия ссылок в Java
- Strong Reference: обычная ссылка, препятствует GC
- Soft Reference: позволяет GC удалить объект при нехватке памяти
- Weak Reference: позволяет GC удалить объект в любой момент
- Phantom Reference: используется только для очистки ресурсов
import java.lang.ref.SoftReference;
import java.lang.ref.WeakReference;
import java.lang.ref.PhantomReference;
import java.lang.ref.ReferenceQueue;
// SoftReference для кэша
SoftReference<LargeObject> softRef = new SoftReference<>(new LargeObject());
// PhantomReference для отслеживания финализации
ReferenceQueue<MyObject> queue = new ReferenceQueue<>();
PhantomReference<MyObject> phantomRef = new PhantomReference<>(new MyObject(), queue);
Плюсы и минусы
Плюсы:
- Предотвращают memory leaks в кэшах
- Автоматическая очистка при нехватке памяти
- Полезны для metadata и listeners
Минусы:
- Сложнее для понимания
- Может привести к неожиданным null значениям
- Требует явной проверки null при получении значения
Weak References — это продвинутый инструмент для тонкого управления памятью в высоконагруженных приложениях и фреймворках.