1. 概要

このクイックチュートリアルでは、HotSpotJVMが配列の長さを格納する方法と場所を確認します。

通常、ランタイムデータ領域のメモリレイアウトはJVM仕様の一部ではなく、実装者裁量に任されています。 したがって、各JVM実装には、メモリ内のオブジェクトと配列をレイアウトするための異なる戦略がある場合があります。

このチュートリアルでは、特定のJVM実装であるHotSpotJVMに焦点を当てています。 また、JVMとHotSpotJVMの用語を同じ意味で使用する場合もあります。

2. 依存

JVM内の配列のメモリレイアウトを検査するために、Javaオブジェクトレイアウト( JOL )ツールを使用します。 したがって、jol-core依存関係を追加する必要があります。

<dependency> 
    <groupId>org.openjdk.jol</groupId> 
    <artifactId>jol-core</artifactId>    
    <version>0.10</version> 
</dependency>

3. 配列の長さ

HotSpot JVMは、通常のオブジェクトポインタ(OOP)と呼ばれるデータ構造を使用して、オブジェクトへのポインタを表します。 具体的には、HotSpot JVMは、と呼ばれる特別なOOPを使用してアレイを表します。 arrayOop 。 各arrayOopには、次の詳細を含むオブジェクトヘッダーが含まれています。

  • IDハッシュコードまたはGC情報を格納するための1つのマークワード
  • 一般的なクラスのメタデータを格納するための1つのクラスワード
  • 配列の長さを表す4バイト

したがって、 JVMは、配列の長さをオブジェクトヘッダーに格納します。

配列のメモリレイアウトを調べて、これを確認しましょう。

int[] ints = new int[42];
System.out.println(ClassLayout.parseInstance(ints).toPrintable());

上に示したように、既存の配列インスタンスからメモリレイアウトを解析しています。 JVMがint[]をレイアウトする方法は次のとおりです。

[I object internals:
 OFFSET  SIZE   TYPE DESCRIPTION               VALUE
      0     4        (object header)           01 00 00 00 (00000001 00000000 00000000 00000000) (1) # mark
      4     4        (object header)           00 00 00 00 (00000000 00000000 00000000 00000000) (0) # mark
      8     4        (object header)           6d 01 00 f8 (01101101 00000001 00000000 11111000) (-134217363) #klass
     12     4        (object header)           2a 00 00 00 (00101010 00000000 00000000 00000000) (42) # array length
     16   168    int [I.<elements>             N/A
Instance size: 184 bytes

前述のように、JVMは、markおよびklassワードの後のオブジェクトヘッダー内に配列の長さを格納します。 また、配列の長さは4バイトで格納されるため、32ビット整数の最大値を超えることはできません。

オブジェクトヘッダーの後に、JVMは実際の配列要素を格納します。 42個の整数の配列があるため、配列の合計サイズは168バイト(42に4を掛けたもの)になります。

4. 結論

この短いチュートリアルでは、JVMが配列の長さを格納する方法を確認しました。

いつものように、すべての例はGitHubから入手できます。