En-tête d'objet Java

Vous êtes-vous déjà demandé à quoi ressemblent les objets java de l'intérieur?
Sous le chat, il y aura une description détaillée de l'en-tête de l'objet Java, de sa composition et de la quantité de mémoire nécessaire.


Pour commencer, rappelez-vous qu'en jvm, tout objet en mémoire est constitué de l'en-tête d'objet et des variables d'objet (liens et primitives). De plus, la taille finale de l'objet peut être étendue pour devenir un multiple de 8 octets.


Le titre de chaque objet (à l'exception du tableau) se compose de deux mots machine - mot de marque et mot de classe . Les tableaux ont 32 bits supplémentaires pour décrire la longueur du tableau.


Mark Word stocke le code de hachage d'identité, les bits utilisés par le garbage collector et les bits utilisés pour les verrous. Vous pouvez toujours trouver plus de détails dans les tris OpenJDK correspondants markOop.hpp .


Un mot de classe stocke un pointeur vers la classe elle-même, c'est-à-dire vers l'endroit où se trouvent les informations sur ce type de données: méthodes, annotations, héritage, etc. Plus de détails peuvent également toujours être trouvés dans les sortes OpenJDK correspondantes de klass.hpp .


Examinons maintenant de plus près le titre de l'objet, et en particulier le mot de repère


Jvm 32 bits


JVM 32 bits


Comme vous pouvez le voir dans le tableau, le contenu du mot Mark peut varier considérablement en fonction de l'état actuel de l'objet.


État normal de l'objet (polared_lock = 0, lock = 01)


  • identity_hashcode est le hachage d'un objet qui apparaît paresseusement. Si l'objet a un appel System.identityHashCode (obj) pour la première fois, ce hachage sera calculé et écrit dans l'en-tête de l'objet.
    Dans d'autres états, lorsque différents flux sont en concurrence pour un objet, le code d'identité_hashcode sera stocké non pas dans l'en-tête de l'objet, mais dans le moniteur de l'objet.
  • âge - le nombre de collectes d'ordures enregistrées. Lorsque l'âge atteint le nombre maximal de tenure,
    l'objet se déplace vers la hanche de l'ancienne génération.
  • polared_lock - contient 1 si le verrouillage biaisé est activé pour cet objet, sinon 0.

Un peu plus
Lorsque le verrouillage biaisé est activé, l'objet se déplace comme s'il s'agissait du premier objet qui a capturé son moniteur. La capture ultérieure de l'objet dans le même flux sera légèrement plus rapide.

Voici les prérequis théoriques de base pour ce verrou:
  • Tout au long de la vie d'un objet, il appartient principalement à un flux
  • Si le thread a récemment utilisé un verrou sur cet objet, le cache du processeur contiendra probablement les données qui seront nécessaires pour recapturer cet objet.


Le verrouillage biaisé est activé par défaut depuis java 6, -XX: -UseBiasLocking

  • lock - contient le code d'état du verrou. 00 - Léger verrouillé, 01 - Déverrouillé ou biaisé, 10 - Lourd verrouillé, 11 - Marqué pour la collecte des ordures.

Autrement dit, dans le tableau, l'état d'un objet est déterminé par la combinaison des bits de verrouillage biaisé et de verrouillage.


Mode verrouillé biaisé (polared_lock = 1, lock = 01)


  • thread - en mode de verrouillage biaisé, on suppose que l'objet appartient principalement à un thread particulier, l'ID de ce thread est stocké dans le champ.
  • epoch contient un indicateur temporaire de propriété de l'objet par un thread dont l'id est stocké dans le thread

Mode verrouillé léger (verrou = 00)


Dans ce mode, on suppose que le temps de capture par cet objet par différents flux ne se coupe pas du tout ou ne se chevauche pas de manière insignifiante. Dans ce mode, au lieu de bloquer lourdement le système d'exploitation, la JVM utilise l'atomique.


  • ptr_to_lock_record - CAS (comparer et définir) à l'intérieur de la boucle de rotation est utilisé pour définir / attendre un verrou.
    À titre de référence, le temps de blocage minimal du système d'exploitation sera d'environ 10 ms, à l'aide de l'atomique, le flux ne s'endort pas, mais continue de battre un petit cycle, et dès que la ressource est libre, le cycle atomique se termine et le flux capture immédiatement cet objet.

Mode verrouillé lourd (verrou = 10)


  • ptr_to_heavyweight_monitor - si le temps de capture de cet objet avec différents flux se chevauchent de manière significative, le verrou léger sera remplacé par un verrou lourd. Un pointeur vers le moniteur sera écrit dans ptr_to_heavyweight_monitor. Le verrouillage du système d'exploitation est utilisé.

Ainsi, en jvm 32 bits, l'en-tête de l'objet se compose de 8 octets. Les tableaux ont en outre 4 octets.


Jvm 64 bits


JVM 64 bits


Sur un jvm 64 bits, l'en-tête d'objet se compose de 16 octets. Les tableaux ont en outre 4 octets.


Jvm 64 bits avec compression de pointeur


Coops JVM 64 bits


Un en-tête d'objet se compose de 12 octets. Les tableaux ont en outre 4 octets.


Un peu sur la compression du pointeur. Pour un pointeur 32 bits, l'espace d'adressage est limité à 4 Go. Cependant, si nous rappelons à nouveau qu'en jvm, la taille d'un objet est un multiple de 8 octets, alors nous pouvons utiliser un pseudo pointeur de 35 bits, avec trois zéros à la fin. Et, par conséquent, faites déjà référence à 32 Go de mémoire. La compression n'est pas gratuite, le prix est une opération supplémentaire (pointeur << 3) pour tout appel à tas.


Lien vers l'article d'origine:


En-tête d'objet Java


Je voudrais également ajouter que tout ce qui est décrit ici n'est pas un dogme, peut-être que dans d'autres versions de jvm le titre de l'objet sera différent. Décrit ici est pertinent pour openjdk 8.

Source: https://habr.com/ru/post/fr447848/


All Articles