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

В чем разница между памятью на стеке и на куче?

1.0 Junior🔥 111 комментариев
#JVM и память#Производительность и оптимизация

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

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

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

Разница между памятью на стеке и на куче

Это два разных механизма управления памятью, которые работают с разными типами данных и имеют разные характеристики производительности.

Стек (Stack)

Стек — это область памяти, которая работает по принципу LIFO (Last In, First Out). Память здесь выделяется и освобождается автоматически и очень быстро.

Что хранится на стеке:

  • Примитивные типы: Int, Float, Boolean, Char
  • Локальные переменные
  • Параметры функций
  • Ссылки на объекты (сами объекты лежат в куче)

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

  • Скорость: очень быстрое выделение и освобождение (просто движение указателя)
  • Размер: ограничен, обычно несколько мегабайт (stackOverflow может быть)
  • Время жизни: переменная существует только в рамках блока/функции
  • Управление: полностью автоматическое
fun calculateSum() {
    val a = 5        // стек: примитив int
    val b = 10       // стек: примитив int
    val result = a + b // стек: примитив int
    // После выхода из функции всё освобождается автоматически
}

Куча (Heap)

Куча — это область памяти для динамического выделения объектов во время исполнения. Память выделяется вручную (через конструктор), а освобождается сборщиком мусора.

Что хранится в куче:

  • Все объекты (экземпляры классов)
  • Массивы
  • Строки
  • Коллекции (List, Map и т.д.)
  • Любые complex типы

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

  • Скорость: медленнее стека (нужно найти свободное место, потом сборка мусора)
  • Размер: намного больше, ограничен объёмом RAM
  • Время жизни: пока на объект есть ссылки
  • Управление: управляется Garbage Collector (GC)
fun createPerson() {
    val person = Person("John", 30) // объект Person в куче, ссылка на стеке
    val addresses = listOf("Moscow", "SPb") // объект List в куче, ссылка на стеке
    // После выхода из функции ссылки удаляются со стека,
    // объекты удаляются из кучи сборщиком мусора
}

Наглядное сравнение

ПараметрСтекКуча
Скорость доступаОчень быстроМедленнее
УправлениеАвтоматическоеGC
Размер~1-8 МБВсая доступная RAM
ФрагментацияНетДа, может быть
ПроблемыStackOverflowErrorOutOfMemoryError
ПотокобезопасностьКаждый поток свой стекShared между потоками

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

class User(val name: String, val age: Int)

fun main() {
    val user1 = User("Alice", 25)  // user1 (ссылка) → стек, User объект → куча
    val age = 25                    // age (значение) → стек
    val user2 = user1              // user2 (ссылка) → стек, указывает на ТОТ ЖЕ объект в куче
    
    if (someCondition) {
        val tempList = mutableListOf(1, 2, 3) // tempList (ссылка) → стек, объект List → куча
        // После выхода из блока: tempList удалится со стека, 
        // объект List удалится из кучи GC-ом
    }
}

// СТЕК:                          КУЧА:
// main() stack frame:            User("Alice", 25)
// user1 ─────────────────────→  User("Bob", 30)
// age (25)                        [1, 2, 3]
// user2 ─────────────────────→  (временные объекты)
// tempList ─────────────────→

Важные выводы для Android разработки

Оптимизация памяти:

  • Используйте примитивные типы где возможно (на стеке быстрее)
  • Избегайте создания множества временных объектов в циклах
  • Помните о проблеме memory leak: если ссылка остаётся, объект не удалится
  • Профилируйте память через Android Profiler

Практическое правило:

// Плохо: создание объектов в цикле
for (i in 0..1000) {
    val rect = Rect(0, 0, 100, 100) // 1000 объектов в куче, GC перегружен
}

// Хорошо: переиспользование объекта
val rect = Rect()
for (i in 0..1000) {
    rect.set(0, 0, 100, 100) // один объект на стеке, переиспользуется
}