1. ホーム
  2. java

javaで文字列がガベージコレクションされるのはいつ?

2023-11-22 23:35:47

質問

Javaでは、オブジェクトがライブリファレンスを持っていないとき、それはガベージコレクションの対象となります。文字列の場合、文字列は文字列プールに入り、JVMは再利用のためにオブジェクトを生かし続けるので、この限りではありません。 つまり、一度作成された文字列は、「決して」ガベージコレクションされないということですか?

どのように解決するのでしょうか?

文字列の場合、文字列は文字列プールに入り、JVMは再利用のためにオブジェクトを維持するので、このケースには当てはまりません。つまり、一度作成された文字列は、「決して」ガベージ コレクションされないということですか?

まず、それは だけ 文字列 リテラル (注釈を参照) で、自動的にインターンされ、文字列プールに追加されます。 String アプリケーションが実行時に作成したオブジェクトはインターンされません ... ただし、アプリケーションが明示的に String.intern() .

次に、実は文字列プールのオブジェクトをガベージコレクションするためのルールは、他の String オブジェクトと同じです。 GCが到達不可能であると判断した場合、それらはガベージコレクションされます。

実際には String 文字列リテラルに対応するオブジェクト は通常 はガベージコレクションの候補になることはありません。 これは 暗黙の への参照があるからです。 String オブジェクトへの暗黙の参照です。 これはつまり String はメソッドが実行される限り到達可能であることを意味します。

しかし、これは 常に とは限りません。 文字列リテラルが動的に読み込まれるクラスで定義されていた場合 (例えば Class.forName(...) を使用)、そのクラスが アンロード . もしそうなった場合は String オブジェクトに対応するリテラル は到達不能になり、最終的にGCされるかもしれません。

こちらもご覧ください。 Javaでクラスがガベージコレクションされるのはいつ、どのようにですか?


注意事項

  1. 文字列リテラル( JLS 3.10.5 ) は、以下のように表示される文字列です。 という文字列です。 と表示される文字列です。

      "abc"            // string literal
      new String(...)  // not a string literal
    
    
  2. (コンパイル時の)定数式( JLS 15.28 ) も内部化されるかもしれません。

       "abc" + 123      // this is a constant expression
    
    
  3. 厳密に言えば、すべてのStringリテラルがインターンであるわけではありません。

    • String リテラルが定数式の部分式としてのみソースコードに現れる場合、そのリテラルは ".class" ファイルに現れないかもしれません。 どのような形であれ . このようなリテラルは実行時に存在しないため、インターンされません。

    • Java 9+では、リテラルとコンパイル時の定数でない値を含む文字列の連結は は異なる方法で処理されます。 現在、バイトコードコンパイラのオプションで、以下のような文字列の連結が可能です。

       int x = 42;   // not a compile time constant
       String s = "prefix " + x + " suffix";
      
      

      かもしれない のような文字列定数がインターネイトされることになります。

       "prefix \1 suffix"
      
      

      実行時には、上記の文字列定数は動的連結メソッドを生成するための "recipe" として使用されます。その際 オリジナル 文字列リテラル(すなわち "prefix "" suffix" ) は内部で文字列オブジェクトにならないでしょう。

      を賞賛します。 ホルガー の指摘に感謝します。 より詳細な情報は JEP 280 javadoc に対して StringConcatFactory .

  4. Java 7 より前のバージョンでは、文字列プールは PermGen にありました。 Javaのいくつかのバージョンでは、PermGen のガベージコレクションは有効ではありませんでした。 デフォルトで CMS コレクターを選択した場合です。 しかし、CMS は決してデフォルトのコレクターではなく、CMS による PermGen 収集を有効にするフラグもありました。 (そして、もう誰も Java 6 以前のコードを開発してはいけません。)