Сколько памяти освободится после вызова list.clear() для ArrayList с 1 млн элементов Integer?

«Сколько памяти освободится после вызова list.clear() для ArrayList с 1 млн элементов Integer?» — вопрос из категории Java Core, который задают на 10% собеседований Java Разработчик. Ниже — развёрнутый ответ с разбором ключевых моментов.

Ответ

Вызов list.clear() для ArrayList<Integer> с 1 млн элементов не освобождает память, занятую внутренним массивом, но позволяет GC собрать сами объекты Integer.

Детализация:

  1. Память внутреннего массива (elementData)

    • Метод clear() устанавливает size = 0 и обнуляет (null) ссылки в массиве, но не уменьшает его емкость (capacity).
    • Массив из 1 млн ссылок (~4 байта каждая при -XX:+UseCompressedOops) продолжает занимать ~4 МБ.
  2. Память объектов Integer

    • После clear() ссылки на 1 млн объектов Integer теряются.
    • Если других ссылок на эти объекты нет, они становятся кандидатами на сборку мусора (GC).
    • Память под сами объекты (примерно 16 байт на объект) будет освобождена во время следующей сборки мусора.

Пример и управление памятью:

import java.util.ArrayList;

public class MemoryDemo {
    public static void main(String[] args) {
        ArrayList<Integer> list = new ArrayList<>();
        // Заполняем 1 млн элементов
        for (int i = 0; i < 1_000_000; i++) {
            list.add(i); // Автоупаковка int -> Integer
        }
        System.out.println("Size after fill: " + list.size());

        // 1. clear() освобождает только ссылки
        list.clear();
        System.out.println("Size after clear: " + list.size());
        // Внутренний массив все еще имеет capacity на 1 млн элементов (~4 МБ).

        // 2. Чтобы уменьшить внутренний массив, нужно:
        list.trimToSize(); // Теперь capacity = size = 0
        // ИЛИ
        list = new ArrayList<>(); // Старый ArrayList будет собран GC
    }
}

Итог: Сразу после clear() остается ~4 МБ под внутренний массив ссылок. Память объектов Integer (~16 МБ) освободится после работы GC.