4

私はちょうどこの記事を読みました:ガベージコレクションについての真実

「A.3.3非表示」のセクションでは、オブジェクトがいつどのようにinvisible状態になるかについて説明します。

以下のコードでは、変数に割り当てられたオブジェクトはブロックを離れた後にfooなり、メソッドが終了するまで強く参照されたままになります(ループは永久に実行されるため、これは発生しません)。invisibletry/catchrunwhile

public void run() {
    try {
        Object foo = new Object();
        foo.doSomething();
    } catch (Exception e) {
        // whatever
    }
    while (true) { // do stuff } // loop forever
}

それはこの記事で述べられています:

ただし、JVMを効率的に実装すると、参照がスコープ外になったときに参照がゼロになる可能性は低くなります。

なぜそれは効率的ではないのですか?

私の説明の試みは次のとおりです。

このメソッドのスタックに4つの要素が含まれていて、現在は表示されていないオブジェクトが下部にあるとします。
オブジェクトを即座に収集したい場合は、3つの要素をポップして保存し、4番目の要素をポップして破棄してから、まだ有効な3つの要素をスタックにプッシュして戻す必要があります。
制御フローがメソッドを離れた後に非表示のオブジェクトを収集するrunと、VMは4つの要素すべてをポップして、それらを破棄することができます。

4

2 に答える 2

3

aloadローカル変数はオペランドスタック上にありませんが、アクティブ化フレームのローカル変数領域にあり、バイトコードを介した参照の場合にアクセスされ、astoreローカル変数をゼロにすることはプッシュとポップを含みません。

ゼロ化は必要ないため、非効率的です。

  • すぐにガベージコレクションサイクルが発生することはありません
  • プログラムのロジックで指定されているように、ゼロはすぐに別の値で上書きされる可能性があります。
  • スコープから外れるということは、ローカル変数がガベージコレクションのルートセットの一部ではなくなったことを意味します。そのため、スコープから外れる直前に保持していた値(ゼロまたは有効な参照)は重要ではありません。とにかく調べられません。

編集:

最後のステートメントに関するいくつかのコメント。

実際、バイトコードレベルではスコープはなく、ローカル変数スロットはメソッドが戻るまでルートセットの一部のままである可​​能性があります。もちろん、JVM実装は、ローカル変数スロットがいつデッドになるか(つまり、メソッドreturnへのすべての可能なパスが変数にアクセスしないかストアであるか)を判別し、それをルートセットの一部とは見なしませんが、決してそうする必要はありません。

于 2011-11-19T16:48:19.123 に答える
0

非常に単純な答えは、b/cは非効率的です。

多くのガベージコレクタアルゴリズムがあり、積極的に収集するものもあります。一部のコンパイラはスタックで割り当てを行いますが、あなたの場合で最も明白なのはdoSomething()、オブジェクトへの参照を他の場所に実際に保持(リーク)する可能性があることです。

于 2011-11-19T16:38:27.703 に答える