Подробная информация о слове метки заголовка объекта Java

Я изучаю состав заголовка объекта Java.

Нашел несколько документов и несколько интересных задач.

В 64-битной виртуальной машине заголовок объекта по умолчанию выглядит следующим образом (поскольку UseCompressedOops включен по умолчанию)

|--------------------------------------------------------------------------------------------------------------|--------------------|
|                                            Object Header (96 bits)                                           |        State       |
|--------------------------------------------------------------------------------|-----------------------------|--------------------|
|                                  Mark Word (64 bits)                           |    Klass Word (32 bits)     |                    |
|--------------------------------------------------------------------------------|-----------------------------|--------------------|
| unused:25 | identity_hashcode:31 | cms_free:1 | age:4 | biased_lock:1 | lock:2 |    OOP to metadata object   |       Normal       |
|--------------------------------------------------------------------------------|-----------------------------|--------------------|
| thread:54 |       epoch:2        | cms_free:1 | age:4 | biased_lock:1 | lock:2 |    OOP to metadata object   |       Biased       |
|--------------------------------------------------------------------------------|-----------------------------|--------------------|
|                         ptr_to_lock_record                            | lock:2 |    OOP to metadata object   | Lightweight Locked |
|--------------------------------------------------------------------------------|-----------------------------|--------------------|
|                     ptr_to_heavyweight_monitor                        | lock:2 |    OOP to metadata object   | Heavyweight Locked |
|--------------------------------------------------------------------------------|-----------------------------|--------------------|
|                                                                       | lock:2 |    OOP to metadata object   |    Marked for GC   |
|--------------------------------------------------------------------------------|-----------------------------|--------------------|

Если UseCompressedOops выключен, заголовок объекта выглядит следующим образом:

|------------------------------------------------------------------------------------------------------------|--------------------|
|                                            Object Header (128 bits)                                        |        State       |
|------------------------------------------------------------------------------|-----------------------------|--------------------|
|                                  Mark Word (64 bits)                         |    Klass Word (64 bits)     |                    |
|------------------------------------------------------------------------------|-----------------------------|--------------------|
| unused:25 | identity_hashcode:31 | unused:1 | age:4 | biased_lock:1 | lock:2 |    OOP to metadata object   |       Normal       |
|------------------------------------------------------------------------------|-----------------------------|--------------------|
| thread:54 |       epoch:2        | unused:1 | age:4 | biased_lock:1 | lock:2 |    OOP to metadata object   |       Biased       |
|------------------------------------------------------------------------------|-----------------------------|--------------------|
|                       ptr_to_lock_record:62                         | lock:2 |    OOP to metadata object   | Lightweight Locked |
|------------------------------------------------------------------------------|-----------------------------|--------------------|
|                     ptr_to_heavyweight_monitor:62                   | lock:2 |    OOP to metadata object   | Heavyweight Locked |
|------------------------------------------------------------------------------|-----------------------------|--------------------|
|                                                                     | lock:2 |    OOP to metadata object   |    Marked for GC   |
|------------------------------------------------------------------------------|-----------------------------|--------------------|

Исходный код C++ для markword находится здесь: http://hg.openjdk.java.net/jdk8/jdk8/hotspot/file/87ee5ee27509/src/share/vm/oops/markOop.hpp

У меня есть вопрос:

Почему один бит изменился с неиспользуемого на cms_free, когда включено сжатие указателя?

Я подозреваю, что это как-то связано со сборщиком мусора CMS, но я не знаю, что он делает.

И когда я проверяю соответствующую информацию в заголовке объекта (включая две приведенные выше таблицы), в большинстве из них упоминается файл markOop.hpp, но представлена ​​только информация, связанная с Lock. Не обращайте внимания на cms_free, узкийOop, promo_bits, PromotedObjec, упомянутые в markOop.hpp этой важной информации, поэтому мне любопытна эта часть.


person student    schedule 02.04.2020    source источник
comment
Я не знаю, как раньше CMS использовала заголовки объектов, но CMS давно устарела и удалена в JDK 14: openjdk.java.net/jeps/363. Таким образом, я бы не стал заморачиваться по этому поводу и предложил изучить более современную реализацию Hotspot.   -  person Juraj Martinka    schedule 02.04.2020
comment
@Juraj Martinka Спасибо за подсказку. Я прочитал код markoop.hpp jdk11, но он не изменился. В jdk14 я нашел markword.hpp, но не markoop.hpp. В комментариях нет описания, связанного с CMS. Прежде чем появится лучший ответ, я могу думать о cms_free только как о специальной обработке для сборщика CMS.   -  person student    schedule 02.04.2020


Ответы (1)


При использовании плоских указателей младшие биты адресных указателей всегда равны нулю из-за выравнивания и позволяют отмечать особое состояние, записывая в эти биты единицы. Таким образом, CMS устанавливает младший бит указателя klass в единицу, когда хочет обозначить, что конкретный фрагмент памяти является не объектом (больше), а свободной памятью.

Но функция сжатого указателя использует то же свойство для адресации большего объема памяти с помощью 32-битного указателя, сдвигая адрес вправо и не оставляя неиспользуемых младших битов. Следовательно, CMS должен хранить этот бит где-то еще, то есть в рассматриваемом cms_free_bit.

Источник: concurrentMarkSweepGeneration.cpp:

// A block of storage in the CMS generation is always in
// one of three states. A free block (FREE), an allocated
// object (OBJECT) whose size() method reports the correct size,
// and an intermediate state (TRANSIENT) in which its size cannot
// be accurately determined.
// STATE IDENTIFICATION:   (32 bit and 64 bit w/o COOPS)
// -----------------------------------------------------
// FREE:      klass_word & 1 == 1; mark_word holds block size
//
// OBJECT:    klass_word installed; klass_word != 0 && klass_word & 1 == 0;
//            obj->size() computes correct size
//
// TRANSIENT: klass_word == 0; size is indeterminate until we become an OBJECT
//
// STATE IDENTIFICATION: (64 bit+COOPS)
// ------------------------------------
// FREE:      mark_word & CMS_FREE_BIT == 1; mark_word & ~CMS_FREE_BIT gives block_size
//
// OBJECT:    klass_word installed; klass_word != 0;
//            obj->size() computes correct size
//
// TRANSIENT: klass_word == 0; size is indeterminate until we become an OBJECT
person Holger    schedule 06.04.2020