← Назад к вопросам
Где хранятся объекты с типом 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, которая экономит память, но требует аккуратности при работе с большим объемом данных.