Программируя языки как C, C++ не сохранит значения массива в "куче" скорее, это сохраняет значение в СТЕКЕ. Но в Java, почему существует необходимость сохранить значения массива в "куче"?
В Java массивы (как и все другие объекты) передаются по ссылке: когда вы передаете массив в метод, он получит ссылку, указывающую на то же место в памяти, нет копия делается. Это означает, что массив должен оставаться «живым» после метода, который его создал, и поэтому не может быть сохранен в кадре стека для метода. Он должен управляться сборщиком мусора, как и все другие объекты.
Проводятся некоторые исследования по оптимизации выделения памяти JVM с использованием «анализа выхода»: если объект (например, массив) может быть гарантированно никогда не уйдет при текущей области видимости, становится возможным фактически выделить ее в стеке, что более эффективно.
Короткий ответ: массив в Java является ссылочным типом, а ссылочные типы находятся в куче. Стоит отметить, что в C # можно переключиться в небезопасный режим и инициализировать массивы с помощью stackalloc, который создаст массив в стеке. Поэтому вполне вероятно, что виртуальная машина позволит вам создать массив в стеке, и это просто деталь реализации, которая означает, что все массивы находятся в куче.