Подробности о слове пометки java заголовка объекта - PullRequest
4 голосов
/ 02 апреля 2020

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

Найдены некоторые документы и некоторые интересные проблемы.

При 64-битном vm заголовок объекта по умолчанию выглядит следующим образом (потому что 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, PromotedObje c, упомянутый в markOop.hpp, эту важную информацию, поэтому мне любопытно узнать об этой части.

1 Ответ

4 голосов
/ 06 апреля 2020

При использовании плоских указателей младшие биты адресных указателей всегда равны нулю из-за выравнивания и позволяют отмечать особое состояние, записывая их в эти биты. Таким образом, 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
...