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

Где хранятся объекты с типом String?

1.0 Junior🔥 151 комментариев
#JVM и память#Kotlin основы

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

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

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

Где хранятся объекты String в памяти

Это классический вопрос о памяти в JVM, который важен для понимания производительности и правильной работы с памятью в Android.

Основное хранилище: String Pool

String Pool (буквальный пул) — это специальная область в памяти JVM, где хранятся все строковые литералы ("строки в кавычках в коде").

Где находится String Pool:

  • Java 7+ — в Heap (куче), а не в PermGen/MetaSpace
  • Для класса String это специальная таблица хеш-кодов (StringTable)
  • Занимает часть Heap памяти

Как работает String Pool:

val str1 = "hello"  // Создается объект в String Pool
val str2 = "hello"  // Указывает на ТОТ ЖЕ объект из Pool
val str3 = String("hello")  // Создает новый объект в Heap

println(str1 === str2)  // true — один и тот же объект
println(str1 === str3)  // false — разные объекты
println(str1 == str3)   // true — одинаковое содержимое

Разделение памяти String объектов

1. String Pool (для литералов):

  • Все строковые литералы "текст в коде"
  • Очень быстрый поиск через хеш-таблицу
  • Один объект для всех одинаковых литералов
  • Автоматически очищается GC, когда на String нет ссылок

2. Heap (обычная память):

  • Строки, созданные через String(...) конструктор
  • Строки из StringBuilder.toString()
  • Строки из операций (конкатенация, substring и т.д.)
  • Результаты методов, возвращающих String

3. Stack (стек вызовов):

  • Ссылки на String объекты (переменные)
  • Локальные переменные методов
  • Параметры функций

Пример памяти в коде

class StringMemoryExample {
    fun demonstrateStringStorage() {
        // String Pool (интерниро из литерала)
        val literal1 = "Android"  // Heap + String Pool
        val literal2 = "Android"  // Указывает на существующий в Pool
        
        // Явное создание в Heap (не в Pool)
        val constructed = String("Android")  // Новый объект в Heap
        
        // Результат конкатенации (Heap)
        val concatenated = "Android" + " Developer"  // В Heap
        
        // Результат метода (Heap)
        val substring = "Android".substring(0, 3)  // "And" в Heap
        
        // Intern (добавить в String Pool вручную)
        val fromHeap = String("Test")
        val interned = fromHeap.intern()  // Теперь в String Pool
        
        println(literal1 === literal2)      // true — оба из Pool
        println(literal1 === constructed)   // false — разные места
        println(interned === "Test")        // true — оба в Pool
    }
}

Эффект Intern

String.intern() — вручную добавляет String в String Pool.

Осторожно:

// ПЛОХО: может вызвать утечку памяти
val userInput = readLine()
val interned = userInput?.intern()  // Может заполнить String Pool

// ХОРОШО: используй только для известных значений
val status = "ACTIVE".intern()  // Реально небольшое количество

Сборка мусора (Garbage Collection)

Как GC работает с String:

fun memoryExample() {
    var temp = "Temporary String"  // В Heap или Pool
    temp = null  // Ссылка удалена
    // GC может удалить объект, если нет других ссылок
    
    val reused = "Temporary String"  // Может использовать из Pool
}
  • Если String в Pool и на него нет ссылок, GC удаляет его
  • String в обычном Heap удаляется обычным образом
  • String Pool автоматически оптимизируется

Важно для Android

Memory pressure:

  • String Pool добавляет памяти на куче (Heap)
  • Больше String = больше памяти
  • На мобильных устройствах память ограничена

Лучшие практики:

  • Избегай создания миллионов уникальных String объектов
  • Переиспользуй String константы
  • Не intern() пользовательский ввод
  • Учи, что конкатенация в цикле создает много объектов — используй StringBuilder

Вывод:

String объекты хранятся в двух местах: **String Pool в Heap** (для литералов) и **обычная Heap память** (для динамически созданных строк). String Pool — это оптимизация JVM, которая экономит память, но требует аккуратности при работе с большим объемом данных.