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

В какой области памяти хранится ссылочная переменная

1.2 Junior🔥 171 комментариев
#JVM и управление памятью

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

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

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

# Где хранится ссылочная переменная в Java

Краткий ответ

Ссылочная переменная хранится на Stack (стеке), а сам объект — на Heap (куче).

String name = new String("John");
// name — переменная на Stack (адрес объекта)
// новый объект String("John") — на Heap

Подробно: Stack vs Heap

Stack (стек)

Что там:

  • Примитивные типы: int, boolean, double, float и т.д.
  • Ссылочные переменные (сами переменные, не объекты!)
  • Локальные переменные
  • Параметры методов

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

  • Очень быстро (нет фрагментации)
  • LIFO (Last In First Out) порядок выделения/освобождения
  • Автоматически очищается при выходе из области видимости (scope)
  • Размер фиксирован для thread'а (~1 MB по умолчанию)
public void example() {
    int age = 25;              // Stack: переменная age = 25
    String name = "Alice";     // Stack: переменная name = адрес на Heap
    User user = new User();    // Stack: переменная user = адрес на Heap
    
    // Когда метод завершится, все эти переменные очищаются автоматически
}

Heap (куча)

Что там:

  • Все объекты (новые экземпляры классов)
  • Массивы
  • Строки (в StringPool, но это часть Heap)

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

  • Медленнее Stack (может быть фрагментирована)
  • Неупорядоченное выделение/освобождение памяти
  • Очищается через Garbage Collector
  • Большой размер (~несколько ГБ)
  • Shared между всеми threads
String s1 = new String("Hello");
// Stack: переменная s1 с адресом
// Heap: объект String("Hello") на конкретном адресе памяти

Визуализация памяти

┌─────────────────────────────────┐
│         STACK (Thread)          │
├─────────────────────────────────┤
│ name    → 0x7a8c2f40           │ (ссылка на Heap)
│ age     → 25                    │ (примитив)
│ user    → 0x7a8c2f80           │ (ссылка на Heap)
└─────────────────────────────────┘

┌─────────────────────────────────┐
│     HEAP (Shared Memory)        │
├─────────────────────────────────┤
│ 0x7a8c2f40: [S][t][r][i][n][g] │ (объект String)
│ 0x7a8c2f80: User {name, age}   │ (объект User)
└─────────────────────────────────┘

Примеры: Где хранятся переменные

Пример 1: Локальные переменные метода

public void example() {
    int x = 10;                    // Stack
    String str = "Hello";          // Stack (переменная); Heap (объект)
    StringBuilder sb = new StringBuilder();
    // sb — Stack (переменная), StringBuilder объект — Heap
}

Пример 2: Поля класса

public class Person {
    private int age;              // Это поле на Heap (в теле объекта Person)
    private String name;          // Переменная на Heap; значение на Heap
    
    public Person(int age, String name) {
        this.age = age;           // Присваивание в Heap память Person
        this.name = name;         // Ссылка хранится в Heap (в Person)
    }
}

public void test() {
    Person p = new Person(30, "Bob");  // Stack: переменная p
                                        // Heap: объект Person с полями
}

Пример 3: Массивы

public void arrays() {
    int[] numbers = {1, 2, 3};    // Stack: переменная numbers
                                   // Heap: массив с элементами
    
    String[] names = {"Alice", "Bob"};
    // Stack: переменная names
    // Heap: массив (с ссылками на String объекты)
    // Heap: объекты String("Alice"), String("Bob")
}

Практическое значение: Memory Leaks

Когда теряется ссылка на объект

Public class MemoryExample {
    public static void test() {
        StringBuilder sb = new StringBuilder();
        // Stack: переменная sb
        // Heap: объект StringBuilder
        
        sb = null;  // Ссылка удалена
        // Объект на Heap станет доступен для GC (если на него нет других ссылок)
    }
    // При выходе из метода переменная sb удаляется из Stack
    // Объект будет собран Garbage Collector'ом
}

Memory Leak в случае удержания ссылки

public class Service {
    private static List<byte[]> cache = new ArrayList<>();  // Static = никогда не чистится!
    
    public void loadData() {
        byte[] largeArray = new byte[10_000_000];
        cache.add(largeArray);  // Ссылка вечна → Memory Leak
    }
}

Ключевые различия

ХарактеристикаStackHeap
ХранитПримитивы, ссылкиОбъекты, массивы
СкоростьОчень быстроМедленнее
РазмерМаленький (~1MB)Большой (~несколько GB)
ОчисткаАвтоматическаяGarbage Collector
ПотокобезопасностьКаждый thread свойShared между threads
ФрагментацияНетДа, со временем

Интересный случай: Escape Analysis

Модерный JIT компилятор может оптимизировать и хранить на Stack:

public void test() {
    Point p = new Point(10, 20);
    // JIT может определить, что p никогда не escape из метода
    // Может разместить на Stack вместо Heap (Stack allocation)
}

Итоговый ответ

Ссылочная переменная всегда находится на Stack (это просто адрес памяти в виде числа), а сам объект находится на Heap. Это критически важно понимать для:

  • Отладки и профилирования
  • Предотвращения memory leak'ов
  • Понимания поведения GC
  • Оптимизации приложения
В какой области памяти хранится ссылочная переменная | PrepBro