OpenJDK 19 и сжатые указатели
Мне трудно понять, как работают сжатые указатели в Java 19, помощь приветствуется.
В Java 11 эталонный размер равен 4 для кучи меньше 32 ГБ (сжатые указатели) и 8 для кучи большего размера. В Java 19 кажется, что они занимают 4 байта даже для больших куч (как?).
Подробности:
Версии Java: OpenJDK Java 11.0.12 и OpenJDK Java 19.0.1.
Командные строки:
-XX:+UnlockExperimentalVMOptions -XX:+UseEpsilonGC -Xlog:gc -Xlog:gc+heap+coops -Xms41g -Xmx41g -XX:+AlwaysPreTouch
-XX:+UnlockExperimentalVMOptions -XX:+UseEpsilonGC -Xlog:gc -Xlog:gc+heap+coops -Xms31g -Xmx31g -XX:+AlwaysPreTouch
Код: https://github.com/cornelcreanga/fun/blob/master/src/main/java/com/ccreanga/various/RandomAllocate.java — код взят с https://shipilev.net/jvm/anatomy -кварки/23-сжатые ссылки/
Запустите этот код как с Java 11, так и с Java 19, и вы увидите, что размер памяти в Java 19 меньше, чем в Java 11, для кучи > 32 ГиБ. Для меньшей кучи размер почти идентичен.
1 ответ
Вы смотрите на макетbyte[]
массив и экземплярjava.lang.Object
. Ни один из них не содержит ссылки на объект внутри кучи.
Разница, которую вы видите, заключается в размере указателя класса , который не указывает на место внутри кучи памяти. Но по историческим причинам вариант-XX:+UseCompressedClassPointers
был связан с наличием-XX:+UseCompressedOops
вариант. Поэтому, когда размер кучи запрещал сжатые указатели на объекты, сжатые указатели классов отключались как побочный эффект.
JDK-8241825, сделать сжатые oops и сжатые указатели классов независимыми адресами, и это было решено с помощью JDK15.
Поэтому, когда я изменяю вашу программу на
System.out.println(ClassLayout.parseInstance(new Object[3]).toPrintable());
и запустить его с кучей 41 ГБ, я получаю
[Ljava.lang.Object; object internals:
OFF SZ TYPE DESCRIPTION VALUE
0 8 (object header: mark) 0x0000000000000001 (non-biasable; age: 0)
8 8 (object header: class) 0x000001f54bec41e0
16 4 (array length) 3
20 4 (alignment/padding gap)
24 24 java.lang.Object Object;.<elements> N/A
Instance size: 48 bytes
Space losses: 4 bytes internal + 0 bytes external = 4 bytes total
до JDK15 и
[Ljava.lang.Object; object internals:
OFF SZ TYPE DESCRIPTION VALUE
0 8 (object header: mark) 0x0000000000000001 (non-biasable; age: 0)
8 4 (object header: class) 0x000020fc
12 4 (array length) 3
16 24 java.lang.Object Object;.<elements> N/A
Instance size: 40 bytes
Space losses: 0 bytes internal + 0 bytes external = 0 bytes total
с JDK15 или новее.
Разница явно вызвана указателем класса и дополнением, но для трех ссылок на объекты требуется 24 байта в каждой версии JVM.