私は次のコードを持っています:
void method() {
Object o1 = new Object();
{
Object o2 = new Object();
System.out.println(o2);
}
// any long operation
}
o2 オブジェクトは の実行中にガベージ コレクションの対象になりますlong operation
か?
私は次のコードを持っています:
void method() {
Object o1 = new Object();
{
Object o2 = new Object();
System.out.println(o2);
}
// any long operation
}
o2 オブジェクトは の実行中にガベージ コレクションの対象になりますlong operation
か?
到達可能性の JLS 定義は次のとおりです。
「到達可能なオブジェクトとは、任意のライブ スレッドから潜在的な継続計算でアクセスできる任意のオブジェクトです。」
この場合、参照は、呼び出しが戻る前に進行中の計算に理論的にアクセスできなくなります。println
(println(o2)
参照がどこかに保存されていないと思います。)
ただし、実際には、呼び出し中に Object が到達不能になったことを伝えることができる JVM は存在せず、ほとんどの JVM は ... または ...o2
がスコープ外になった後にのみ、これに気づきます。それでも、GC の実行によってオブジェクトが削除されるとは限りません。
注:「到達可能なオブジェクト」テストは、オブジェクトがいつガベージコレクションされるかではなく、いつガベージコレクションされないかを実際に伝えているため、これはJLSと矛盾しません。JLS は、オブジェクトが到達不能になった後、ある時点でファイナライズされ、ガベージ コレクションが行われる可能性があることを慎重に指定しますが、決してファイナライズされず、ガベージ コレクションが行われないこともあります。
はい。ただし、これは、JVM/JITが余分なスタック操作を回避するためにこれを最適化しないかどうかによって異なります。
それを作るだろう
Object o1 = new Object();
Object o2 = new Object();
System.out.println(o2);
// any long operation
多くのコンパイラは、必要なすべてのローカル変数をグループ化し、それらをすべて保持するために必要な最大スペースを計算し(一部は削除され、レジスタに保持されるだけです)、それに応じてスタックを拡張し、関数が戻ることができた後にのみスタックを縮小します
これは、o2が別のスコープ内の別の変数で上書きされない限り、GCに従って「アクセス可能な」メモリに残ることを意味します。
o2
変数と OBJECT DESIGNATED BYo2
が異なる ことを理解する必要があります。
変数o2 は実際にはポインターであり (Java はそれらを「参照」と呼ぶことを好みます)、自動スタック フレームで 4 または 8 バイトを占有します。このストレージはガベージ コレクションではなく、プロシージャから戻ったとき (または{}
、コンパイラの実装によってはブラケットを終了したとき) にのみ消えます。
o2 によって「指定された」(指された) オブジェクトは、基本的に、new Object()
操作が終了するとすぐにガベージ コレクションに使用できます。変数 o2 がスタック フレームに存在しなくなるか、別のポインター値が格納されると、オブジェクトは収集対象になります。
したがって、あなたの特定のケースでは、答えは「多分」です。これは、コンパイラと JIT が をどのように処理するかに依存します。また、ブロックを終了した後 (メソッド全体ではなく)、o2 の格納場所が別の目的で再利用さ{}
れるかどうかについてのいくつかの「運」の問題もあります。{}
いいえ。o2 によって参照されるオブジェクトに到達できなくても、ガベージ コレクションは行われません。参照変数 o2 がまだスタック上にあるため、「不可視」と呼ばれる到達可能と到達不能の間の状態にあります。
オブジェクトをガベージ コレクション可能にするには、o2 = null
そのブロックを別の関数に割り当てるか配置します。