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

В каком случае Garbage Collector удаляет Soft Reference

2.3 Middle🔥 92 комментариев
#JVM и память

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

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

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

Механизм сборки Soft Reference в Java (Android)

SoftReference — это особый тип ссылки в Java, который предоставляет сборщику мусора (Garbage Collector, GC) гибкие правила для очистки объектов. В отличие от Strong Reference (обычная ссылка) и WeakReference, SoftReference удаляется не сразу при недостижимости объекта, а только при нехватке памяти.

Условия удаления Soft Reference

Сборщик мусора удаляет объект, на который указывает SoftReference, в следующих случаях:

  1. Объект больше не имеет Strong Reference (сильных ссылок). Это обязательное условие — если на объект ещё есть обычные ссылки, он считается живым и не удаляется.

  2. Сборщик мусора обнаруживает нехватку памяти в куче (Heap). Это ключевое отличие от WeakReference. SoftReference сохраняет объект дольше, пока память не станет критически низкой.

  3. Конкретный момент зависит от реализации JVM/ART (Android Runtime). Спецификация Java не определяет точный алгоритм, оставляя это на усмотрение разработчиков виртуальной машины:

    • В HotSpot JVM (стандартная JVM) объекты SoftReference обычно удаляются перед выбросом OutOfMemoryError.
    • В Android (ART/Dalvik) политика может быть более агрессивной, особенно на устройствах с ограниченной памятью.

Пример кода и логики работы

import java.lang.ref.SoftReference;

public class SoftRefExample {
    public static void main(String[] args) {
        // Создаем объект с Strong Reference
        Object strongRef = new Object();
        
        // Создаем SoftReference на тот же объект
        SoftReference<Object> softRef = new SoftReference<>(strongRef);
        
        // Проверяем, что объект доступен через SoftReference
        System.out.println("До удаления Strong Reference: " + softRef.get());
        
        // Удаляем Strong Reference - теперь объект достижим только через SoftReference
        strongRef = null;
        
        // Принудительно вызываем сборку мусора (в реальном коде так делать не нужно)
        System.gc();
        
        // Объект ВОЗМОЖНО ещё доступен, если памяти достаточно
        System.out.println("После удаления Strong Reference: " + softRef.get());
        
        // Эмулируем нехватку памяти
        try {
            byte[] memoryHog = new byte[10_000_000_000]; // Попытка выделить много памяти
        } catch (OutOfMemoryError e) {
            System.out.println("Память переполнена");
        }
        
        // После нехватки памяти SoftReference скорее всего очищен
        System.out.println("После нехватки памяти: " + softRef.get()); // Вернет null
    }
}

Особенности в Android

В Android разработке SoftReference используется реже, чем в серверной Java, по нескольким причинам:

  1. Непредсказуемость поведения на разных версиях Android и устройствах.
  2. Агрессивная политика очистки — Android часто работает в условиях ограниченной памяти, поэтому SoftReference может очищаться раньше, чем ожидается.
  3. Альтернативы — для кэширования изображений и данных лучше использовать специализированные библиотеки (Glide, Picasso) или LruCache, который предоставляет более предсказуемое управление памятью.
// Пример использования SoftReference в Android (Kotlin)
class ImageCache {
    private val cache = HashMap<String, SoftReference<Bitmap>>()
    
    fun getImage(key: String): Bitmap? {
        return cache[key]?.get()
    }
    
    fun putImage(key: String, bitmap: Bitmap) {
        cache[key] = SoftReference(bitmap)
    }
    
    // При нехватке памяти SoftReference будут автоматически очищены
    // но LruCache был бы более предсказуемым решением
}

Ключевые отличия от других типов ссылок

  • Strong Reference: Объект удаляется только когда на него нет сильных ссылок.
  • WeakReference: Объект удаляется при первой же сборке мусора после потери сильных ссылок.
  • SoftReference: Объект удаляется когда сборщик мусора решает, что ему не хватает памяти.

Практические рекомендации

  1. Используйте SoftReference для кэширования, когда повторное создание объекта дорого, но его потеря приемлема.
  2. Всегда проверяйте softRef.get() != null перед использованием объекта.
  3. Рассмотрите альтернативы в Android: LruCache для кэширования изображений, WeakHashMap для временного хранения ассоциаций.

Важно: SoftReference не гарантирует, что объект останется в памяти до самого последнего момента — это решение JVM/ART, основанное на текущем состоянии памяти и алгоритмах сборки мусора.