Les détails sur la marque de mot de java objet d'en-tête


J'étudie la composition de l'en-tête d'objet java.

Trouvé quelques documents et quelques problèmes intéressants.

Sous une machine virtuelle 64 bits, la tête d'objet par défaut est la suivante (car UseCompressedOops est activé par défaut)

|--------------------------------------------------------------------------------------------------------------|--------------------|
|                                            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   |
|--------------------------------------------------------------------------------|-----------------------------|--------------------|

Si UseCompressedOops est désactivé, l'en-tête de l'objet ressemble à ceci:

|------------------------------------------------------------------------------------------------------------|--------------------|
|                                            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   |
|------------------------------------------------------------------------------|-----------------------------|--------------------|

Et le code source C++ à propos de markword est ici: http://hg.openjdk.java.net/jdk8/jdk8/hotspot/file/87ee5ee27509/src/share/vm/oops/markOop.hpp

J'ai une question:

Pourquoi un bit est passé de inutilisé à cms_free lorsque la compression du pointeur est activée?

Je soupçonne que cela a quelque chose à voir avec le ramasse-miettes CMS, mais je ne sais pas ce qu'il fait.

Et quand je vérifie les informations pertinentes de l'en-tête de l'objet (y compris les deux tableaux ci-dessus), la plupart d'entre eux ont mentionné le markOop.hpp fichier, mais seulement introduit dans le Verrou liées. Ignorez les cms_free, narrowOop, promo_bits, PromotedObjec mentionnés dans markOop.hpp cette information importante, donc je suis curieux de cette partie.

Author: Holger, 2020-04-02

1 answers

Lors de l'utilisation de pointeurs plats, les bits les plus bas des pointeurs d'adresse sont toujours nuls en raison de l'alignement et permettent de marquer un état spécial en écrivant ceux-ci dans ces bits. Ainsi, le CMS a défini le bit le plus bas du pointeur klass sur un quand il veut indiquer que le morceau de mémoire particulier n'est pas un objet (plus), mais de la mémoire libre.

Mais la fonction de pointeur compressé utilise la même propriété pour adresser plus de mémoire via un pointeur 32 bits en décalant à droite l'adresse et en ne laissant aucun inutilisé bits de poids faible. Par conséquent, le CMS doit stocker ce bit ailleurs, c'est-à-dire le cms_free_bit en question.

Source: concurrentMarkSweepGeneration.rpc:

// 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
 5
Author: Holger, 2020-04-06 12:34:26