Как интерпретировать знаковое слово экземпляра?
Я пытаюсь разобраться в выводе Java object layout на 64-битной виртуальной машине HotSpot (v8). Я не понимаю, как первые три бита маркируют слово используются те, которые согласно комментарию в файле связанного класса должны указывать на то, что на экземпляре установлена смещенная блокировка или необъективная блокировка.
Когда я анализирую экземпляр Object
, используя JOL by
ClassLayout layout = ClassLayout.parseClass(Object.class);
Object object = new Object();
System.out.println(layout.toPrintable(object));
Я получаю следующий результат:
java.lang.Object object internals:
OFFSET SIZE TYPE DESCRIPTION VALUE
0 4 (object header) 01 00 00 00 (0000 0001 0000 0000 0000 0000 0000 0000)
4 4 (object header) 00 00 00 00 (0000 0000 0000 0000 0000 0000 0000 0000)
8 4 (object header) e5 01 00 f8 (1110 0101 0000 0001 0000 0000 1111 1000)
12 4 (loss due to the next object alignment)
Instance size: 16 bytes (estimated, add this JAR via -javaagent: to get accurate result)
Space losses: 0 bytes internal + 4 bytes external = 4 bytes total
От описание точки доступа слова метки (первые 8 байт), я понимаю, что должен интерпретировать вышеупомянутые разрядные диапазоны вывода следующим образом:
-
00:01
- флаг для блокировки (00
в Примере.) -
02:02
- флаг для смещенной блокировки (0
в Примере.) -
03:06
- возраст как число молодых итераций сборки мусора. (0000
в Примере.) -
07:07
- не используется. (Кажется, всегда1
.) -
08:39
- идентификационный хэш-код. (Только после его вычисления, до заполнения нулем.) -
40:63
- не используется. (Кажется, он заполнен нулями.)
Подтверждение этой компоновки для диапазона хэш-кодов
По крайней мере, для хэш-кода это можно легко подтвердить, вычисляя идентификационный хэш-код и сравнивая значения:ClassLayout layout = ClassLayout.parseClass(Object.class);
Object object = new Object();
// Check that the hash code is not set.
System.out.println(layout.toPrintable(object));
System.out.println("hash code: 0x" + Integer.toHexString(object.hashCode()));
// Confirm that the value is set:
System.out.println(layout.toPrintable(object));
// Compute the hash code manually:
Field field = Unsafe.class.getDeclaredField("theUnsafe");
field.setAccessible(true);
Unsafe unsafe = (Unsafe) field.get(null);
long hashCode = 0;
for (long index = 7; index > 0; index--) {
hashCode |= (unsafe.getByte(object, index) & 0xFF) << ((index - 1) * 8);
}
System.out.println("hash code: 0x" + Long.toHexString(hashCode));
Где хэш-код задается как фактический бит (игнорируя тот факт, что он представлен только 31 битом вместо 32, поскольку напоминание установлено в ноль). То флаги для Блокировок Все установлены на ноль, как и ожидалось.
Проверка макета для смещенной блокировки
markOops также дает макет, когда объект подвергается смещенной блокировке. Здесь последние две точки маркера заменяются следующими диапазонами:
-
08:09
- бит эпохи -
10:63
- указатель нити, удерживающей эту смещенную блокировку.
Когда я теперь попытаюсь использовать смещенную блокировку, запустив следующий код с -XX:BiasedLockingStartupDelay=0
, я также могу наблюдать, как устанавливается смещенный замок. Когда я запускаю следующий код:
ClassLayout layout = ClassLayout.parseClass(Object.class);
Object object = new Object();
// Before using any lock, the layout is as above.
System.out.println(layout.toPrintable(object));
// When acquiring the lock, the thread ID can be seen as below:
synchronized (object) {
System.out.println(layout.toPrintable(object));
}
// After leaving the lock, the object is biased towards this thread:
System.out.println(layout.toPrintable(object));
Смещенная блокировка видна в слове метки после первоначальной блокировки, как показано ниже:
java.lang.Object object internals:
OFFSET SIZE TYPE DESCRIPTION VALUE
0 4 (object header) 05 f0 3f 02 (0000 0101 1111 0000 0011 1111 0000 0010)
4 4 (object header) 00 00 00 00 (0000 0000 0000 0000 0000 0000 0000 0000)
8 4 (object header) e5 01 00 f8 (1110 0101 0000 0001 0000 0000 1111 1000)
12 4 (loss due to the next object alignment)
Instance size: 16 bytes (estimated, add this JAR via -javaagent: to get accurate result)
Space losses: 0 bytes internal + 4 bytes external = 4 bytes total
Я могу проверить, что это не представляет хэш-код, поскольку слово метки изменяется (смещенная блокировка отменяется), как только я вызываю object.hashCode()
.
Чего я не понимаю, так это того, что флаги для смещенной блокировки и необъективной блокировки по-прежнему равны нулю. Как точка доступа знают, что это смещенная блокировка, а не хэш-код, представленный в объекте. Кроме того, я задаюсь вопросом: Что означает бит epoch?