Сколько байт занимает ссылка на объект в Java
Что проверяют
Знаете ли вы, что размер ссылки не описан спецификацией языка и зависит от режима JVM. Обычно это вход в разговор про расходы памяти на объект целиком и про то, почему одна и та же структура данных на большой куче внезапно начинает занимать больше.
Как отвечать
Спецификация Java размер ссылки не задаёт, это деталь реализации HotSpot. На 64-битной JVM ссылка логически занимает 8 байт, но по умолчанию работает режим сжатых указателей (-XX:+UseCompressedOops): в поле пишется не адрес, а его номер в единицах выравнивания, поэтому четырёх байт хватает примерно до 32 ГБ кучи. Как только -Xmx переваливает за этот порог, JVM отключает сжатие сама, и все ссылки в приложении разом становятся восьмибайтовыми. Отсюда известный эффект: куча в 33 ГБ вмещает меньше объектов, чем куча в 31 ГБ.
Дальше полезно показать, что ссылка это лишь часть счёта. У объекта есть заголовок (mark word и указатель на класс), а итоговый размер выравнивается, поэтому одно добавленное поле иногда достаётся «бесплатно», а иногда стоит сразу восьми байт. Считать это руками не нужно, есть JOL:
System.out.println(ClassLayout.parseInstance(new Object[3]).toPrintable());Где спотыкаются
Отвечают «4 байта на 32-битной системе, 8 на 64-битной» и на этом останавливаются. Тридцатидвухбитные сборки JDK сегодня почти не встречаются, а сжатые указатели работают на любой типовой машине, так что без них ответ мимо реальности.
Второе: путают размер ссылки и размер объекта. Обёртка Long это не восемь байт, а заголовок плюс поле плюс выравнивание, и миллион таких объектов стоит кратно дороже, чем long[] той же длины.
Третье: пробуют измерить размер через Unsafe и называют заранее придуманное число. Константа, которая отдаёт шаг элемента в массиве ссылок, на машине со сжатыми указателями вернёт 4, а не 8, и кандидат начинает спорить с собственным кодом.