0

次のシナリオを検討してください。

String dude = "Harold";

//some stuff

dude = "Kumar";

「Kumar」という 2 番目の値が割り当てられるとdude、「Harold」とは別のまったく新しいオブジェクトが出現します。私が疑問に思っているのは、「ハロルド」は明らかにもう使用されていないため、ガベージコレクションは即座に行われるのでしょうか、それとも後で JVM が適切であると判断したときに行われるのでしょうか?

アップデート:

が新しい値 (オブジェクト) に設定されたからといっdudeて、必ずしも古いオブジェクトへのすべての参照が削除されたわけではありません。dude「Harold」の後、「Kumar」の前に別の参照が呼び出された場合、明らかに「Harold」オブジェクトが保持されます。

String dude = "Harold";

//some stuff

String interim = dude;

dude = "Kumar";

System.out.println("dude = " + dude);
System.out.println("interim = " + interim);

版画

dude = Kumar
interim = Harold

当初想定していた以上の考慮事項があるため、変更後に初期値が必ずしも範囲外である必要はありません。

4

7 に答える 7

5

即座にガベージ コレクションが行われることはなく、ガベージ コレクションを強制しようとすることは推奨されません (Java がリリースされるたびにますます困難になります)。
はい、「ハロルド」に到達できなくなった分(ポインターのチェーンがそれにつながるわけではありません)、ガベージコレクションの対象になり、収集される可能性があります(GCが実行された場合)。そうは言っても、文字列は const プールに割り当てられる可能性があります。これは perm gen にあり、GC されません* (少なくとも Java 7 まで)。文字列のインターンに関する詳細はこちら: http://www.codeinstructions.com/2009/01/busting-javalangstringintern-myths.html

* - 完全に正確というわけではありません。それは複雑です。

于 2013-02-12T16:06:58.943 に答える
2

「ハロルド」はもう明らかに使い物にならないから

どのようにしてこの結論に達しましたか? 参照を作成した単一のクラスを見るだけですか? ただし、 Java 言語仕様によると、文字列リテラルは次の場合に再利用されます。

  • 同じパッケージ内の同じクラス内のリテラル文字列は、同じ String オブジェクトへの参照を表します。
  • 同じパッケージ内の異なるクラス内のリテラル文字列は、同じ String オブジェクトへの参照を表します。
  • 同様に、異なるパッケージの異なるクラス内のリテラル文字列は、同じ String オブジェクトへの参照を表します。
  • 定数式によって計算された文字列は、コンパイル時に計算され、リテラルであるかのように扱われます。
  • 実行時に連結によって計算された文字列は新しく作成されるため、区別されます。
  • 計算された文字列を明示的にインターンした結果は、同じ内容の既存のリテラル文字列と同じ文字列になります。

したがって、上記のすべてが当てはまらないことが確実でない限り、ガベージ コレクションの対象となることさえ期待できないでしょう。

于 2013-02-12T16:52:24.043 に答える
2

通常、ガベージ コレクションはすぐには実行されません。さらに、文字列は不変であり、(私の知る限り、ほとんどの JVM によって) グローバル テーブルに保持されるため、収集されない可能性があります。

于 2013-02-12T16:07:29.453 に答える
2

これは、「後でJVMが適切と判断したとき」です。ガベージ コレクションは CPU を消費し、スレッドの一時停止を意味する場合があります。GC は、CPU とメモリの使用量のバランスを常に保つ非常に複雑なものです。

他の人が言ったように、文字列はもっと複雑ですが、Java オブジェクトの一般的なことを知りたいだけだと思います。String に関するこのワッフルのすべてがあなたの質問に本当に関連しているとは思わず、この質問を必要以上に複雑にしています!

于 2013-02-12T16:12:15.130 に答える
1

定数のString扱いが異なる場合があることを忘れないでください。オブジェクトがすぐにガベージ コレクションされない主な理由は、そのオブジェクトへの他の参照が存在する可能性があるためです。たとえば、「いくつかのもの」に次のようなステートメントが含まれている場合

t = dude;

に新しい値を割り当てても、オブジェクトに到達できませんdude。すべての参照を見つけるのはかなりコストがかかるため、必要な場合にのみ実行します。

于 2013-02-12T16:14:09.603 に答える
1

Java 仕様の現在のほとんどすべての実装でトレース ガベージ コレクターが使用されていますが、トレース GC を使用してヒープを管理することが仕様で要求されているとは思いません。

GC の実装に参照カウントが組み込まれていることが想像できます。上記のケースのこのバリエーション (const プールの詳細を回避するように設計されています):

String dude = new String("Harold");
//
dude = new String("Kumar");

dudeの参照カウントが参照する元のオブジェクトがゼロになり、すぐにガベージ コレクションが行われる可能性があります。

要するに、Java では保証はありませんが、通常は心配する必要はありません。

また、Java GC に関する古いリファレンス.

于 2013-02-12T16:19:39.830 に答える
0

Stringですimmutable。変数を再割り当てするとdude = "Kumar"、古い文字列オブジェクトがスコープから外れます。

そして、ガベージ コレクターが動作を開始すると、そのオブジェクトが収集されました。

于 2013-02-12T16:06:46.540 に答える