25

非常に単純な HelloWorld アプリケーションで javap を実行すると、定数プールに関する出力に混乱が生じます。

テストコード

public class TestClass {
    public static void main(String[] args) {
        System.out.println("hello world");
    }
}

Javap -c -verbose 出力 (省略)

// Header + consts 1..22 snipped
const #22 = String      #23;    //  hello world
const #23 = Asciz       hello world;

public static void main(java.lang.String[]);
  Signature: ([Ljava/lang/String;)V
  Code:
   Stack=2, Locals=1, Args_size=1
   0:   getstatic       #16; //Field java/lang/System.out:Ljava/io/PrintStream;
   3:   ldc     #22; //String hello world
   5:   invokevirtual   #24; //Method java/io/PrintStream.println:(Ljava/lang/String;)V
   8:   return
  // Debug info snipped
}

3 行目で、#22 を介して "hello world" 定数がスタックにプッシュされていますが、const #23 は実際の値を保持しているようです。プリントアウトの右側に表示される #(数字) が何を意味するのか、少し混乱していると思います。

Javap に関する Oracle/Sun の man ページには、まだ十分とは言えない点がたくさんあります。

4

3 に答える 3

26

名前と定数classはすべてJava定数プールinterfaceに入ります。fieldstring

VM 仕様 ( http://java.sun.com/docs/books/jvms/second_edition/html/ClassFile.doc.html ) に従って:

constant_pool は、さまざまな文字列定数、クラス名とインターフェイス名、フィールド名、および ClassFile 構造とそのサブ構造内で参照されるその他の定数を表す構造 (§4.4) のテーブルです。各 constant_pool テーブル エントリの形式は、最初の「タグ」バイトによって示されます。constant_pool テーブルには、1 から constant_pool_count-1 までのインデックスが付けられます。

したがって、定数プールに関しては、以下のようなものは次のように表示できます。

const #22 = String      #23;    //  hello world
const #23 = Asciz       hello world;

#22 (インデックス 22) の値はタイプStringであり、その値は null で終了する c 文字列 ( Asciz )hello worldであり、インデックス 23 にあります。

于 2011-04-05T02:12:02.693 に答える
5

Java 定数プールは、文字列を格納するときに 2 種類のエントリを格納します。まず、文字列リテラルを UTF-8 でエンコードされたデータ (ここでは定数 #23) として格納します。第 2 に、定数 #23 の内容を使用してString. この理由は、JVM が、指定された定数の動的な実装で構成される「ランタイム定数プール」を各クラスに関連付けているためだと思います。文字列の場合、これは、指定された文字を保持するインターンされたStringオブジェクトへの参照になります。UTF-8 定数データには、文字列リテラル (たとえば、フィールドやクラスの名前付け) 以外にも用途があるため、この追加の間接化は、懸念事項を分離するための合理的な方法のように思えます。

于 2011-04-05T02:12:10.713 に答える
4

プールエントリ#22はjava.lang.Stringオブジェクトです。エントリ#23は、その文字列を構成するために使用される文字の配列です。

Java VM仕様は、javapの「欠落しているマニュアル」です。

于 2011-04-05T02:09:47.983 に答える