Javaオブジェクトヘッダー

内部からjavaオブジェクトがどのように見えるか疑問に思ったことはありますか?
猫の下には、javaオブジェクトヘッダーの詳細な説明、その構成要素、および必要なメモリ量が表示されます。


まず、jvmでは、メモリ内のオブジェクトはオブジェクトヘッダーとオブジェクト変数(リンクとプリミティブ)で構成されていることを思い出してください。 また、オブジェクトの最終サイズは、サイズが8バイトの倍数になるように拡張できます。


各オブジェクトのタイトル(配列を除く)は、 mark wordclass wordの2つの機械語で構成されます。 配列には、配列の長さを記述する追加の32ビットがあります。


マークワードには、アイデンティティハッシュコード、ガベージコレクターが使用するビット、およびロックに使用されるビットが格納されます。 詳細は、対応するOpenJDK ソートmarkOop.hppでいつでも確認できます。


クラスワードには、クラス自体へのポインター、つまり、このデータ型に関する情報が存在する場所(メソッド、注釈、継承など)へのポインターが格納されます。 詳細は、対応するOpenJDKの種類のklass.hppでも常に確認できます。


次に、オブジェクトタイトル 、特にマークワードを詳しく見てみましょう。


32ビットJVM


32ビットJVM


表からわかるように、 Mark wordの内容は、オブジェクトの現在の状態によって大きく異なる可能性があります。


オブジェクトの通常の状態(biased_lock = 0、lock = 01)



もう少し
バイアスロックをオンにすると、オブジェクトは、モニターをキャプチャした最初のオブジェクトに移動します。 同じストリームでのオブジェクトの後続のキャプチャは、わずかに高速になります。

このロックの基本的な理論的前提条件は次のとおりです。
  • オブジェクトの存続期間中、その所有者は主に1つのストリームです。
  • スレッドがこのオブジェクトのロックを最近使用した場合、プロセッサキャッシュには、このオブジェクトの再キャプチャに必要なデータがまだ含まれている可能性が高いです。


Java 6以降、バイアスロックはデフォルトで有効になっています-XX:-UseBiasedLocking


つまり、テーブルでは、オブジェクトの状態は、biased_lockビットとロックビットの組み合わせによって決定されます。


バイアスロックモード(biased_lock = 1、lock = 01)



軽量ロックモード(ロック= 00)


このモードでは、異なるフローによるこのオブジェクトのキャプチャ時間がまったく交差しないか、わずかに重複しないと想定されます。 このモードでは、オペレーティングシステムを大きくブロックする代わりに、JVMはアトミックを使用します。



ヘビーウェイトロックモード(ロック= 10)



したがって、32ビットjvmでは、オブジェクトのヘッダーは8バイトで構成されます。 配列にはさらに4バイトがあります。


64ビットJVM


64ビットJVM


64ビットjvmでは、オブジェクトヘッダーは16バイトで構成されます。 配列にはさらに4バイトがあります。


ポインター圧縮を備えた64ビットJVM


64ビットJVM Coop


オブジェクトヘッダーは12バイトで構成されます。 配列にはさらに4バイトがあります。


ポインター圧縮について少し。 32ビットポインターの場合、アドレススペースは4GBに制限されます。 ただし、jvmでオブジェクトのサイズが8バイトの倍数であることを再度思い出すと、最後に3つのゼロがある擬似35ビットポインターを使用できます。 したがって、すでに32GBのメモリを参照しています。 圧縮は無料ではなく、価格はヒープへの呼び出しに対する追加の操作(ポインター<< 3)です。


元の記事へのリンク:


Javaオブジェクトヘッダー


また、ここで説明するすべてがドグマではないことを付け加えます。おそらく、jvmの他のバージョンでは、オブジェクトのタイトルが異なります。 ここで説明するのは、openjdk 8に関連するものです。



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


All Articles