Какая из двух объявлений массива занимает больше памяти в Java
Что проверяют
Представляете ли вы, как массив лежит в куче JVM: заголовок, длина, выравнивание, ссылки. Чаще всего сравнивают new int[1000][2] и new int[2][1000] или int[] и Integer[]. Следом просят посчитать байты и назвать инструмент, которым это проверить.
Как отвечать
Сначала зафиксируйте условия: 64-битная HotSpot, сжатые ссылки включены (так по умолчанию при куче до 32 ГБ), объекты выравниваются по 8 байт. Тогда заголовок массива 16 байт: 8 байт mark word, 4 байта указатель на класс, 4 байта длина. Ссылка занимает 4 байта.
Двумерный массив в Java это массив массивов, и у каждого вложенного свой заголовок:
new int[2][1000]: внешний массив 16 + 2 × 4 = 24 байта, два вложенных по 16 + 4000 = 4016. Итого около 8 КБ;new int[1000][2]: внешний 16 + 1000 × 4 = 4016 байт, тысяча вложенных по 16 + 8 = 24. Итого около 28 КБ, в три с половиной раза больше при тех же двух тысячах чисел.
Вывод: в многомерном массиве выгоднее, чтобы внешним было короткое измерение. Ещё лучше плоский int[] с индексом i * cols + j.
Второй частый вариант: int[1000] занимает 4016 байт, а Integer[1000] те же 4016 на ссылки плюс по 16 байт на каждый объект Integer, то есть около 20 КБ. Исключение составляют значения от -128 до 127: Integer.valueOf и автоупаковка берут их из кэша.
Проверяют всё это через JOL (GraphLayout.parseInstance(arr).totalSize()), а не через разницу Runtime.totalMemory().
Где спотыкаются
Считают заголовок массива 12 байт и забывают про поле длины и выравнивание. У int[10] получается 52 байта вместо реальных 56.
Утверждают, что примитивный массив всегда меньше ссылочного. long[10] занимает 96 байт, а String[10] из пустых ссылок 56, потому что сжатая ссылка вдвое меньше long. Основная память уходит на сами объекты, а не на массив ссылок.
Не оговаривают флаги. Без сжатых ссылок ссылка весит 8 байт, а в свежих JDK есть -XX:+UseCompactObjectHeaders, уменьшающий заголовок. Без оговорки об условиях любой расчёт неточен.