少し遅いかもしれませんが、現在の説明は私にとって完全に満足のいくものではなく、より賢明な説明が得られたと思います.
まず第一に、すべての Java GC は何らかの方法でルート セットから何らかのトレースを行います。これは、古いヘッドが収集された場合、next
とにかく変数を読み取らないことを意味します-そうする理由はありません。したがって、 IFヘッドは次の反復で収集されますが、問題ではありません。
上記の文の IF は、ここで重要な部分です。異なるものの隣に設定することの違いは、頭を収集すること自体には関係ありませんが、他のオブジェクトに違いをもたらす可能性があります。
単純な世代別 GC を想定してみましょう。head が若いセットにある場合、とにかく次の GC で収集されます。ただし、古いセットにある場合は、めったに発生しない完全な GC を実行したときにのみ収集されます。
ヘッドが古いセットにあり、若い GC を実行するとどうなるでしょうか? この場合、JVM は古いヒープ内のすべてのオブジェクトがまだ有効であると想定し、古いオブジェクトから若いオブジェクトへのすべての参照を若い GC のルート セットに追加します。そして、それはまさにここで割り当てが回避するものです: 古いヒープへの書き込みは、通常、JVM がそのような割り当てをキャッチして正しく処理できるように、書き込みバリアまたは何かで保護されますnext
。結果があります。
短い例:
があると仮定します1 (old) -> 2 (young) -> 3 (xx)
。ここでリストから 1 と 2 を削除すると、次の GC で両方の要素が収集されると予想できます。ただし、若い GC のみが発生しnext
、古い GC のポインターを削除していない場合、要素 1 と 2 の両方が収集されません。これとは逆に、1 でポインターを削除した場合、2 は若い GC によって収集されます。