Javaの定数プール(文字列定数プール、class定数プール、および実行時定数プール)

2526 ワード

ここ数日、Javaの仮想マシンに関する知識を見ていると、いくつかの異なる定数プールの説を見て、CSDN、ブログ園などに行って資料を探しました.
Javaのメモリ割り当てでは、合計3つの定数プールがあります.
1.文字列定数プール(String Constant Pool):
1.1:文字列定数プールはJavaメモリ領域のどこにありますか?
  • JDK 6.0以降のバージョンでは、文字列定数プールはPerm Gen領域(すなわちメソッド領域)に配置されています.
  • JDK 7.0バージョンでは、文字列定数プールがスタックに移動されました.なぜスタック内に移動したのかというと、メソッド領域のメモリ容量が小さすぎるためでしょう.

  • 1.2:文字列定数プールは何ですか.
  • HotSpot VMで実現されるstring pool機能はStringTableクラスであり、Hashテーブルであり、デフォルト値のサイズ長は1009である.このStringTableは各HotSpot VMのインスタンスに1部のみあり,すべてのクラスで共有される.文字列定数は1文字ずつで構成され、StringTable上に配置されます.
  • JDK 6.0ではStringTableの長さが固定されており、長さは1009であるため、String Poolに入れるStringが非常に多いとhash衝突を起こし、チェーンテーブルが長すぎるため、String#intern()を呼び出すとチェーンテーブルに1つずつ探す必要があり、性能が大幅に低下する.
  • JDK 7.0でStringTableの長さはパラメータで指定できます:
  • -XX:StringTableSize=66666

    1
    1.3:文字列定数プールに何が入っていますか.
  • JDK 6.0以降のバージョンでは、String Poolには文字列定数が格納されています.
  • JDK 7.0では、String#intern()が変更されたため、String Poolにスタック内に置かれた文字列オブジェクトの参照を格納することもできる.メモリ内のStringのストレージとString#intern()メソッドの説明については、私の別のブログ:
  • を参照してください.
    説明する必要があるのは、文字列定数プールの文字列が1部しか存在しません. 次のようになります.
    String s1 = "hello,world!";
    String s2 = "hello,world!";

    1
    2
    すなわち、第1行のコードを実行した後、定数プールに「hello,world!」がすでに存在すると、s 2は定数プールで新しい空間を申請するのではなく、既存の文字列メモリアドレスを直接s 2に返す.(ここで具体的な文字列の配分は詳しくは言わないが、私の別のブログを見ることができる)
    2.class定数プール(Class Constant Pool):
    2.1:class定数プールの概要:
  • 私たちが書いたJavaクラスごとにコンパイルされると、classファイルが形成されます.クラスファイルには、クラスのバージョン、フィールド、メソッド、インタフェースなどの記述情報に加えて、コンパイラが生成した様々な字面量(Literal)とシンボル参照(Symbolic References)を格納するための定数プール(constant pool table)があります.
  • classファイルごとにclass定数プールがあります.

  • 2.2:字面量と記号参照とは:
  • 字面量は、1.テキスト文字列2.8種類の基本タイプの値3.finalとして宣言された定数などを含む.
  • シンボル参照には、1.クラスおよびメソッドの全限定名2.フィールドの名前および記述子3.メソッドの名前および記述子が含まれる.

  • 3.運転時定数プール(Runtime Constant Pool):
  • ランタイムプールはメモリに存在する、すなわちclass定数プールがメモリにロードされた後のバージョンである.異なる点は、その字面量は動的に追加することができ(String#intern())、シンボル参照は直接参照
  • として解析することができる.
  • JVMは、あるクラスを実行するときに、ロード、接続、初期化を経なければならないが、接続には検証、準備、解析の3段階が含まれている.クラスがメモリにロードされると、jvmはclass定数プールの内容を実行時定数プールに格納します.これにより、実行時定数プールも各クラスに1つあることがわかります.解析フェーズでは、シンボル参照が直接参照に置き換えられ、解析プロセスでは文字列定数プール、すなわちStringTableがクエリされ、実行時定数プールで参照される文字列が文字列定数プールと一致することを保証します.