HotSpot仮想マシンが、メモリ・レイアウトに記憶されたオブジェクトは3つの領域に分けることができる:
オブジェクトヘッダ
(ヘッダ)、
インスタンスデータ
(インスタンスデータ)と
アライメントパディング
(パディング)
1.オブジェクトヘッダー
HotSpot仮想マシンのオブジェクトヘッダーには、2つの情報部分が含まれています。
(1)第一の部分
MarkWord
:のような、それ自体をオブジェクトのランタイムデータを格納するための
ハッシュコード
(ハッシュコード)
GC世代年齢
、
ロック状態フラグを
、
スレッドロックが保持されている
、
スレッドIDを偏向
、
バイアスタイムスタンプを
、同様にデータのこの部分の長さは、32ビットおよび64ビットの仮想マシンでは32ビットおよび64ビットです(圧縮ポインターをオンにするシナリオは考慮されていません)。これは、正式に「マークワード」と呼ばれています。
クラスがロードされると、hashCodeはMark Wordのオブジェクトヘッダーに格納されます。
(2)第一の部分
KlassWordは
、即ち
ポインタの種類
、である、
そのクラスのオブジェクト・メタデータ・ポインタ、仮想マシンは、オブジェクト・クラスのインスタンスであるポインタによって決定されます。すべての仮想マシンの実装がオブジェクトデータの型ポインターを保持する必要があるわけではありません。つまり、オブジェクトのメタデータ情報を見つけることが必ずしもオブジェクト自体を通過するわけではありません。さらに、オブジェクトがJava配列の場合は、配列の長さをオブジェクトヘッダーに記録するために使用するデータが必要です。これは、仮想マシンが通常のJavaオブジェクトのメタデータ情報を介して、ただし配列のメタデータからJavaオブジェクトのサイズを決定できるためです。配列のサイズを判別できません。
![](https://img2020.cnblogs.com/blog/1443749/202004/1443749-20200420042213214-632310697.png)
2.インスタンスデータ
インスタンスデータ部分は、オブジェクトが実際に格納する有効な情報であり、プログラムコードで定義されたさまざまなタイプのフィールドの内容でもあります。親クラスから継承されているか、子クラスで定義されているかにかかわらず、記録する必要があります。
3.パディングを揃えます
配置パディングの3番目の部分は必ずしも存在するわけではなく、特別な意味はありません。プレースホルダーとしてのみ機能します。HotSpot VMの自動メモリ管理システムでは、オブジェクトの開始アドレスを8バイトの整数倍にする必要があります。つまり、オブジェクトのサイズは8バイトの整数倍にする必要があります。オブジェクトヘッダー部分は正確に8バイトの倍数(1xまたは2x)であるため、オブジェクトインスタンスデータ部分が整列されていない場合は、整列パディングによって完了する必要があります。
一般的なオブジェクトと配列型の凡例
- オブジェクトヘッダーのMark Wordは、主にオブジェクトのスレッドロック状態を示すために使用され、GCと連携してオブジェクトのhashCodeを格納するためにも使用できます。
- クラスワードは、メソッド領域のクラス情報へのポインタです。つまり、オブジェクトは、どのクラスインスタンスであるかを常に知ることができます。
- 配列の長さも64ビット(8バイト)のスペースを占めますが、これはオプションであり、オブジェクトが配列オブジェクトである場合にのみ、この部分があります。
- オブジェクト本体は、オブジェクトの属性と値を保存するために使用される主要な部分であり、占有されるメモリ空間は、オブジェクトの属性の数とタイプによって異なります。
- アラインメントワードは、ヒープメモリの断片化領域を減らすためのものです(必ずしも正確ではありません)。
すべてのオブジェクトはoopDescクラスから継承します。
class oopDesc { private : volatile markOop _mark; // ハッシュコード、GCエージ、ロックなどのオブジェクトのランタイム情報 union _metaData { // オブジェクトを記述するklassオブジェクトを指すオブジェクトのメタデータポインター wideKlassOop _klass; arrowOop _compressed_klass; } _metaData; …… }
newが呼び出されて新しいオブジェクトが作成されると、ヒープにメモリが割り当てられ、オブジェクトヘッダーとインスタンスデータを含むオブジェクトインスタンスが作成され、作成された結果の参照がJavaスタックのローカル変数に返されます。オブジェクトヘッダーを介して、オブジェクトのランタイム情報(_mark)およびオブジェクトタイプ関連情報(_metaDataポインター)にアクセスできます。
HotSpotのオブジェクトアクセスは、次の図に示すように、直接ポインターによって実装されます。
Javaプログラムは、Javaスタック内の参照により、ヒープ上の特定のオブジェクトを操作します。
1)インスタンスデータ、つまりクラスの一般属性にアクセスする場合、参照を介してヒープ内のオブジェクトのインスタンスデータに直接アクセスできます。
2)オブジェクトのメソッドと静的プロパティにアクセスする場合は、_metaDataポインターを介してメソッド領域のklassオブジェクトにアクセスできます
3)klassオブジェクトには仮想関数テーブルvtblが含まれているため、_metaDataポインターを介してklassオブジェクトにアクセスすることにより、各オブジェクトはすべての仮想関数を見つけることができます
4)klassには_super、_subclassなどの情報が含まれているため、各クラスのすべての親クラス、子クラス、兄弟クラスなどを見つけることができます