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

В какой момент чистятся SoftReference

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

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

🐱
claude-haiku-4.5PrepBro AI26 мар. 2026 г.(ред.)

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

В какой момент чистятся SoftReference

SoftReference — это тип слабой ссылки в Java, которая позволяет объектам быть собранными сборщиком мусора в определённых условиях. Её очистка (обнуление) происходит не в конкретный момент, а в определённом диапазоне условий, связанных с давлением на память.

Когда происходит очистка

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

  1. При недостатке памяти — это основное условие. Когда JVM почти исчерпала доступную память и возникает OutOfMemoryError, GC первым делом очищает все SoftReference перед выбросом исключения
  2. После полной сборки мусора (Full GC) — если обычная сборка мусора не освободила достаточно памяти
  3. По решению GC алгоритма — детали зависят от реализации JVM (например, HotSpot может учитывать последнее обращение к объекту)

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

// StrongReference — стандартная ссылка, не удаляется
val strongRef = MyObject()

// SoftReference — удаляется только при нехватке памяти
val softRef = SoftReference(MyObject())
val obj = softRef.get() // null если объект был удалён

// WeakReference — удаляется при следующем GC если нет strong ссылок
val weakRef = WeakReference(MyObject())

// PhantomReference — удаляется всегда, нужна для очистки ресурсов
val phantomRef = PhantomReference(MyObject(), queue)

Практический пример в Android

CacheManager часто использует SoftReference для кэширования изображений:

class ImageCache {
    private val cache = mutableMapOf<String, SoftReference<Bitmap>>()
    
    fun put(key: String, bitmap: Bitmap) {
        cache[key] = SoftReference(bitmap)
    }
    
    fun get(key: String): Bitmap? {
        val ref = cache[key]
        val bitmap = ref?.get()
        
        // Если SoftReference вернула null, объект был удалён
        if (bitmap == null) {
            cache.remove(key)
        }
        
        return bitmap
    }
}

Важные моменты

  • SoftReference.get() может вернуть null в любой момент после вызова GC
  • Не гарантируется время удержания объекта в памяти — это зависит от JVM реализации
  • Не следует полагаться на SoftReference для освобождения критических ресурсов (используй try-with-resources или PhantomReference)
  • На практике SoftReference часто медленнее, чем явное управление кэшем с размером

Поведение по версиям JVM

В HotSpot JVM действует примерно такое правило:

  • Время жизни SoftReference ≈ msPerMB × свободная память в МБ
  • Например, если -XX:SoftRefLRUPolicyMSPerMB=1000 и свободно 100МБ, то объект может жить ~100 секунд

Когда использовать

SoftReference имеет смысл для:

  • Кэширования бинарных данных (изображения, видео)
  • Кэширования результатов вычислений
  • Когда есть возможность пересчитать/перезагрузить данные

Не используй SoftReference для:

  • Хранения состояния UI
  • Объектов с критическими ресурсами
  • Когда нужна гарантия наличия объекта