Jvmメモリ割当て(4)

3836 ワード

以下の内容はすべてネットから来ており、基本的にオリジナルはありません.メモを勉強するだけです.

3.2.2メソッド領域の使用


jvmがメソッド領域でどのように使用されているかを示すために、一例に基づいて、次のクラスを見ます.
 
class Lava {
    private int speed = 5; // 5 kilometers per hour
    void flow() {
    }
}
class Volcano {
    public static void main(String[] args) {
        Lava lava = new Lava();
        lava.flow();
    }
}

次にmain()メソッドの最初の命令のバイトコードがどのように実行されるかについて説明する.異なるjvm実装の差は大きく,ここではその1つにすぎない.
 
 
次は以上のコードのバイトコードです.
 
public class Lava {
  
  // Field descriptor #6 I
  private int speed;
  
  // Method descriptor #8 ()V
  // Stack: 2, Locals: 1
  public Lava();
     0  aload_0 [this]
     1  invokespecial java.lang.Object() [10]
     4  aload_0 [this]
     5  iconst_5
     6  putfield Lava.speed : int [12]
     9  return
      Line numbers:
        [pc: 0, line: 1]
        [pc: 4, line: 3]
        [pc: 9, line: 1]
      Local variable table:
        [pc: 0, pc: 10] local: this index: 0 type: Lava
  
  // Method descriptor #8 ()V
  // Stack: 0, Locals: 1
  void flow();
    0  return
      Line numbers:
        [pc: 0, line: 6]
      Local variable table:
        [pc: 0, pc: 1] local: this index: 0 type: Lava
}

 class Volcano {
  
  // Method descriptor #6 ()V
  // Stack: 1, Locals: 1
  Volcano();
    0  aload_0 [this]
    1  invokespecial java.lang.Object() [8]
    4  return
      Line numbers:
        [pc: 0, line: 9]
      Local variable table:
        [pc: 0, pc: 5] local: this index: 0 type: Volcano
  
  // Method descriptor #15 ([Ljava/lang/String;)V
  // Stack: 2, Locals: 2
  public static void main(java.lang.String[] args);
     0  new Lava [16]
     3  dup
     4  invokespecial Lava() [18]
     7  astore_1 [lava]
     8  aload_1 [lava]
     9  invokevirtual Lava.flow() : void [19]
    12  return
      Line numbers:
        [pc: 0, line: 11]
        [pc: 8, line: 12]
        [pc: 12, line: 13]
      Local variable table:
        [pc: 0, pc: 13] local: args index: 0 type: java.lang.String[]
        [pc: 8, pc: 13] local: lava index: 1 type: Lava
}

1このプログラムを実行するために、何らかの方法で「Volcano」をjvmに渡しました.この名前があれば、jvmはこのクラスファイル(Volcano.class)を見つけて読み込み、クラスファイルからタイプ情報を抽出してメソッドエリアに置きました
2メソッド領域に存在するバイトコードを解析することにより、jvmはmain()メソッドをアクティブにし、実行時にjvmは現在のクラス(Volcano)定数プールへのポインタを保持する.注意jvmは、Lavaクラスがロードされていない間に実行されています.ほとんどのjvmのように、すべてのクラスがロードされてから実行されるのではなく、必要なときにのみロードされます.実はオンデマンドロードです)
このシンボル参照はクラスlavaの完全な有効名「lava」にすぎません.ここでは、jvmができるだけ早く1つの名前からクラスを見つけるために、良好なデータ構造がどれほど重要かを示します.ここでjvmの実装者は、hashテーブル、ツリーの検索など、さまざまな方法を採用することができます.同じアルゴリズムはClassクラスのforName()の実装に使用できます.
3 jvmがまだ「Lava」というクラスがロードされていないことを発見すると、クラスファイル「Lava.class」の検索とロードを開始します.クラスファイルからタイプ情報を抽出し、メソッド領域に配置します.
4 jvmは、定数プールの第1項のシンボル参照を、メソッド領域lavaクラスを直接指すポインタで置き換えた.後でこのポインタでlavaクラスをすばやく見つけることができます.この置換プロセスを定数プール解析(constant pool resolution)と呼ぶ.ここで交換したのはnativeポインタです.
5 jvmはついに新しいlavaオブジェクトに空間を割り当て始めた.今回,jvmはメソッド領域の情報を依然として必要とする.lavaデータを指すポインタ(volcano定数プールの最初のアイテムを指すポインタ)を使用して、lavaオブジェクトにどれだけの空間が必要かを見つけます.
jvmは、メソッド領域に格納されたタイプ情報から、あるタイプのオブジェクトに必要な空間を常に知ることができる.しかし、1つのオブジェクトは、異なるjvmで異なる空間を必要とし、その空間分布も異なる場合があります.
6 jvmがLavaオブジェクトに必要な空間を知ったら、スタックにこの空間を割り当て、このインスタンスの変数speedをデフォルト値0に初期化します.lavaの親オブジェクトにもインスタンス変数がある場合は、初期化されます.(これには後のheapの知識が必要です)
7新しく生成されたlavaオブジェクトの参照をスタックに押すと、最初のコマンドも終了します.次のコマンドは、このリファレンスを使用してjavaコードをアクティブにしてspeed変数を初期値に設定します.
8別の命令はこの参照でアクティブになります