私はこの記事を読みました:ガベージコレクションの真実
「A.3.3非表示」セクションでは、オブジェクトがいつどのようにinvisible
状態になるかが説明されています。
以下のコードでは、変数に割り当てられたオブジェクトはブロックを出た後foo
となり、メソッドが終了するまで強く参照され続けます(ループが永久に実行されるため、これは決して起こりません)。invisible
try/catch
run
while
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つの要素すべてを単純にポップして破棄できます。
ローカル変数はオペランドスタック上ではありませんが、バイトコードによる参照aload
およびastore
ローカル変数のゼロ化の場合にアクセスされる、アクティブ化フレームのローカル変数領域にあります。
ゼロ化は必要ないため、非効率的です。
編集:
最後の声明についてのいくつかのコメント。
実際、バイトコードレベルではスコープはなく、ローカル変数スロットはメソッドが戻るまでルートセットの一部のままになる場合があります。もちろん、JVM実装は、ローカル変数スロットが停止している(つまり、メソッドが返すすべての可能なパスが変数にアクセスしないか、ストアである)かどうかを判断でき、それをルートセットの一部とは見なしませんが、決してそうする必要はありません。
この記事はインターネットから収集されたものであり、転載の際にはソースを示してください。
侵害の場合は、連絡してください[email protected]
コメントを追加