定数のプール

多くの人々は、すべての.classファイルに定数プールと呼ばれる素晴らしいデータ構造があることを知っています。 しかし、ソースを見ているすべてのJava開発者が、プール内に作成される定数の数を大まかに見積もることができるわけではありません。



たとえば、次のコードをご覧ください。



System.out.println("Hello World!");
      
      





getstatic(静的フィールドSystem.outをロードする)、ldc(定数文字列「Hello World!」をロードする)、invokevirtual(println仮想関数を実行する)の3つのバイトコード命令に変換されます。 このコードが機能するために必要な定数の数を把握してください。



この行は14の定数を使用していることがわかります。



ご覧のとおり、ほとんどの定数は他の定数への参照です。 各定数には、参照可能な型、値、および番号があります。 以下は、何も参照しない基本タイプです。



参照タイプの一部を次に示します。



フィールドにアクセスするには、その名前だけでなく、フィールドが宣言されているクラスのフルネーム、およびフィールドのタイプも必要です。 メソッドにアクセスするには、メソッドのクラス、名前、および署名が必要です。 幸い、メソッドパラメーターの数に関係なく、署名全体が1行でエンコードされます。プリミティブ型は1文字(たとえばD = double)でエンコードされ、オブジェクトは文字Lで、その後に完全なクラス名とセミコロンが続き、1レベルの配列が追加されます角かっこ。 引数のタイプは括弧で囲まれ、戻り値のタイプが続きます(Vは無効です)。 たとえば、署名(IDLjava/lang/Thread;)Ljava/lang/Object;



このメソッドには次のものがあります。

 Object m(int i, double d, Thread t) {...}
      
      





メソッドを参照するには正確な署名が必要であるという事実から、開発者はNoSuchMethodErrorに遭遇することがあります。 メソッドの戻り値の型をより具体的なものに変更したとしましょう。 その後、他のクラスからのこのメソッドへの呼び出しは同じままであり、ソースファイルが変更されていないため、コンパイラはこれらのクラスを再コンパイルしません。 ただし、実行時にこのメソッドを呼び出そうとすると、Javaマシンは古い署名を探します。



Javaコードを自動的に生成する場合は、プール内の最大定数が65535を超えないようにしてください。その後、コンパイルエラーが発生します。 膨大な数のリンクと、長くて二重の2つの位置を占めるという事実を考えると、これはそれほど多くありません。 プールデバイスを知ることは、コードを生成する際にプールデバイスを制御するのに役立ちます。



定数プールデバイスの詳細について 、Java Virtual Machine仕様の§4.4を参照してください。



All Articles