最初に注意しなければならないのは、この文は Java 9 のファントム参照のドキュメントへのソフト参照とウィーク参照のドキュメントからコピーされたものであり、そのバージョンで行われた変更に対応するためのものですが、ファントム参照には適していないため、その背後にある理論的根拠は、ソフト参照と弱い参照についてよりよく説明されています。
次の状況があるとします。
(weak)→ A
(weak)→ B (strong)→ A
技術的には、 と の両方A
にB
弱い到達可能性がありますがget()
、どちらかの弱い参照でメソッドを呼び出して、その指示対象への強い参照を取得することで、これを変更できます。
への強い参照を取得するために最初の弱い参照でこれを行うとA
、オブジェクトB
は弱い到達可能のままになりますが、への強い参照を取得するためにこれを行うと、からの強い参照によりB
、オブジェクトA
も強く到達可能になります。B
にA
。
したがって、 への弱参照A
がクリアされた場合、 への弱参照をクリアする必要があるというルールがあります。そうしないと、への弱参照がクリアされたにもかかわらず、via へB
の強参照を取得できてしまうからです。安全のために、これはアトミックに発生する必要があるため、2 つの参照のクリアランスの間に参照を取得できる競合状態はありません。A
B
A
B
前述のように、ファントム参照では参照を取得できないため、これは関連性が低くなりますが、異なる方法で処理する理由はありません。
ここでのポイントは、ガベージ コレクターが実際にどのように機能するかを考えると、これは実際の負担ではないということです。それらはすべてのライブ参照、つまり強力に到達可能なオブジェクトをトラバースする必要があり、遭遇しないものはすべて削除ごとにガベージです。そのため、トラバーサル中に弱い参照に遭遇すると、参照対象をトラバースしませんが、参照オブジェクトを記憶します。トラバーサルが完了すると、遭遇したすべての参照オブジェクトを実行し、参照先が別のパスから到達可能としてマークされているかどうかを確認します。そうでない場合、参照オブジェクトはクリアされ、エンキューのためにリンクされます。
あなたの例に対処するには:
(strong)→ A
(weak)→ B (strong)→ A
ここで、B
への強い参照に関係なく、 は弱く到達可能A
です。への強い参照を削除してもA
、 はB
まだ到達可能性が低く、エンキューされる可能性があります。正式にA
は、現在は弱い到達可能性がありますが、JVM はそれが弱い到達可能性であることを検出しない限り、決してそれを検出しB
ません。弱い到達可能性を検出する唯一の方法A
は、弱い到達可能性から始まる参照グラフをトラバースすることですB
。しかし、これを行う実装はありません。ガベージ コレクターは、弱い参照を単純にクリアしB
ます。それだけです。