← Назад к вопросам

В чем разница между SoftReference, WeakReference, PhantomReference?

2.7 Senior🔥 151 комментариев
#JVM и память

Комментарии (1)

🐱
deepseek-v3.2PrepBro AI5 апр. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

Разница между SoftReference, WeakReference, PhantomReference в Java

В Java механизм ссылочных объектов (Reference Objects) предоставляет различные уровни "слабых" ссылок на объекты, позволяя гибко управлять памятью и реализовывать кеширование, слушателей событий и другие паттерны. Все они находятся в пакете java.lang.ref и отличаются поведением при сборке мусора.

Основные отличия

SoftReference (мягкая ссылка)

Объекты, на которые ссылаются только через SoftReference, собираются сборщиком мусора только при нехватке памяти (OutOfMemoryError). Это делает их идеальными для реализации кешей.

// Пример использования SoftReference
import java.lang.ref.SoftReference;

public class SoftRefExample {
    public static void main(String[] args) {
        Object strongRef = new Object();
        SoftReference<Object> softRef = new SoftReference<>(strongRef);
        
        // Удаляем сильную ссылку
        strongRef = null;
        
        // Объект может быть доступен через softRef.get()
        // до тех пор, пока GC не решит очистить память
        System.gc();
        Object retrieved = softRef.get(); // Может вернуть null, если память под давлением
    }
}

Характеристики:

  • Сборка происходит только при нехватке памяти
  • Используется для кеширования, где потеря данных допустима под памятьным давлением
  • Не гарантирует сохранение объекта даже без явного вызова System.gc()

WeakReference (слабая ссылка)

Объекты со слабыми ссылками собираются сборщиком мусора в ближайший цикл GC, независимо от доступной памяти. После этого get() возвращает null.

// Пример использования WeakReference
import java.lang.ref.WeakReference;
import java.util.WeakHashMap;

public class WeakRefExample {
    public static void main(String[] args) {
        Object strongRef = new Object();
        WeakReference<Object> weakRef = new WeakReference<>(strongRef);
        
        strongRef = null;
        System.gc();
        
        // После GC weakRef.get() почти гарантированно вернет null
        if (weakRef.get() == null) {
            System.out.println("Объект был собран GC");
        }
    }
}

Характеристики:

  • Сборка происходит в следующем цикле GC
  • Используется для реализации канонических отображений, слушателей событий
  • WeakHashMap использует слабые ссылки для ключей

PhantomReference (фантомная ссылка)

Самый слабый тип ссылки. Не позволяет получить объект через get() (всегда возвращает null). Используется для выполнения действий после того, как объект был удален из памяти, но до того как его память будет перераспределена.

// Пример использования PhantomReference
import java.lang.ref.PhantomReference;
import java.lang.ref.ReferenceQueue;

public class PhantomRefExample {
    public static void main(String[] args) {
        Object strongRef = new Object();
        ReferenceQueue<Object> queue = new ReferenceQueue<>();
        PhantomReference<Object> phantomRef = new PhantomReference<>(strongRef, queue);
        
        strongRef = null;
        System.gc();
        
        // phantomRef.get() ВСЕГДА возвращает null
        
        // Проверяем очередь на наличие фантомной ссылки
        PhantomReference<?> refFromQueue = (PhantomReference<?>) queue.poll();
        if (refFromQueue != null) {
            // Здесь можно выполнить финализацию ресурсов
            System.out.println("Объект готов к финализации");
        }
    }
}

Характеристики:

  • get() всегда возвращает null
  • Добавляется в ReferenceQueue после финализации объекта
  • Используется для более надежной альтернативы методу finalize()
  • Позволяет контролировать освобождение ресурсов (закрытие файлов, соединений)

Сравнительная таблица

КритерийSoftReferenceWeakReferencePhantomReference
Время сборкиПри нехватке памятиСледующий цикл GCПосле финализации
get() возвращаетОбъект или nullОбъект или nullВсегда null
ReferenceQueueОпциональноОпциональноОбязательно
Основное применениеКешированиеРеализация "слабых" коллекцийКонтроль финализации ресурсов
Сила ссылкиСредняяСлабаяОчень слабая

Практические применения

  • SoftReference: Кеширование изображений в Android (LruCache с мягкими ссылками), кеширование результатов вычислений
  • WeakReference: Реализация WeakHashMap, избегание утечек памяти в слушателях событий, особенно в Android (Activity/Context)
  • PhantomReference: Освобождение нативных ресурсов, мониторинг сборки мусора, реализация пулов с точным контролем памяти

В Android разработке особенно важно понимать эти различия, так как неправильное использование может привести к утечкам памяти (MemoryLeak) или преждевременному удалению объектов. Например, использование WeakReference для хранения ссылок на Activity помогает избежать утечек при асинхронных операциях.