19

.NET や Java などで、弱参照が内部でどのように機能するのだろうか。私の2つの一般的なアイデアは次のとおりです。

  1. 「侵入的」 - 最上位クラス (オブジェクト クラス) への弱い参照のリストを追加します。次に、オブジェクトが破棄されると、すべての弱い参照を反復して null に設定できます。
  2. 「非侵入的」 - 弱い参照のリストへのオブジェクトのポインターのハッシュテーブルを維持するため。オブジェクト B への弱い参照 A が作成されると、変更または作成されたハッシュテーブル内のエントリが存在し、そのキーは B へのポインタになります。
  3. 「ダーティ」 - オブジェクトが破棄されるとゼロになる、各オブジェクトに特別なハッシュ値を格納します。弱参照はそのハッシュ値をコピーし、それをオブジェクトの値と比較して、オブジェクトが生きているかどうかを確認します。ただし、これを直接使用するとアクセス違反エラーが発生するため、そのハッシュ値を持つ追加のオブジェクトが必要になると思います。

これらのソリューションはどちらもクリーンでも効率的でもないようです。実際にどのように行われるか知っている人はいますか?

4

5 に答える 5

7

.NET では、WeakReferenceが作成されると、参照を表すハンドル/不透明なトークンが GC に要求されます。次に、必要に応じて、WeakReferenceこのハンドルを使用して、そのハンドルがまだ有効か (つまり、元のオブジェクトがまだ存在するか) を GC に問い合わせます。有効な場合は、実際のオブジェクト参照を取得できます。

したがって、これはオブジェクトアドレスに対してトークン/ハンドルのリストを作成しています(おそらく、最適化中などにそのリストを維持します)

私は 3 つの箇条書きを 100% 理解しているかどうか確信が持てないので、どれが最も近いか (もしあれば) 推測するのをためらっています。

于 2009-04-23T08:32:52.753 に答える
5

弱参照の実装は、業界では秘密にされているようです ;-)。たとえば、現時点では、ウィキペディアの記事には実装の詳細がありません。そして、上記の回答(受け入れられたものを含む)を見てください:「ソースを見てください」または「私は思う」;-\ .

すべての回答のうち、Python の PEP 205 を参照しているものだけが洞察に満ちています。それが言うように、weakref をエンティティ自体として扱う場合、任意の単一のオブジェクトに対して、最大で 1 つの弱参照が存在する可能性があります。

残りは Squirrel 言語の実装について説明します。したがって、weakref はそれ自体がオブジェクトです。オブジェクトへの弱い参照をコンテナに配置すると、実際には weakref オブジェクトへの参照が配置されます。各参照カウント可能オブジェクトには、そのオブジェクトへの weakref が実際に要求されるまで NULL であるその weakref へのポインターを格納するフィールドがあります。各オブジェクトには、weakref を要求するメソッドがあり、フィールドから既存の (シングルトンの) weakref を返すか、それを作成してフィールドにキャッシュします。

もちろん、weakref は元のオブジェクトを指しています。したがって、オブジェクトへの参照が処理されるすべての使用可能な場所を調べて、weakref の透過的な処理を追加するだけです (つまり、自動的に参照解除します)。(「透過的な」代替手段は、ほとんどのオブジェクトのアイデンティティとなる仮想の「アクセス」メソッドと、weakref の実際の逆参照を追加することです。)

また、オブジェクトはそのweakrefへのポインタを持っているため、オブジェクトは自身のデストラクタでweakrefをNULL化できます。

この実装は非常にクリーンで (魔法の「GC への呼び出し」などはありません)、O(1) のランタイム コストがあります。もちろん、それはメモリをかなり貪欲です - 通常は 90+% のオブジェクトが NULL であるにもかかわらず、各オブジェクトに +1 ポインタ フィールドを追加する必要があります。もちろん、VHLL には既にオブジェクトごとに大きなメモリ オーバーヘッドがあり、さまざまな「余分な」フィールドを圧縮する可能性があります。たとえば、オブジェクト型は通常小さな列挙であるため、型とある種の weakref 参照を 1 つの機械語にマージすることができる場合があります (たとえば、weakref オブジェクトを別の領域に保持し、そのインデックスを使用します)。

于 2013-08-02T23:20:38.677 に答える
5

あなたの質問を理解できたかどうかはわかりませんが、クラス WeakReference とそのスーパークラス Reference in Java の実装を見ることができます。十分にコメントされており、GC によって特別に処理されるフィールドと、VM によって直接使用される別のフィールドがあることがわかります。

于 2009-04-23T11:48:54.153 に答える
0

通常のアプローチは、システムがある種の弱参照のリストを維持することだと思います。ガベージ コレクターが実行されると、デッド オブジェクトが削除される前に、システムは弱参照のリストを繰り返し処理し、ターゲットにライブ タグが付けられていない参照を無効にします。システムによっては、これは、システムが即時ファイナライズの対象となるオブジェクトを一時的に復元する前または後に発生する可能性があります (.net の場合、2 種類あります。そのうちの 1 つWeakReferenceは、システムがファイナライザーをスキャンする前に効果的に処理されます。つまり、ターゲットがファイナライズの対象になると無効になり、そのうちの 1 つが後で処理されます)。

ちなみに、私が gc ベースのフレームワークを設計している場合は、他のいくつかの利点を追加します。(1) 参照型の格納場所を、他の誰かにとって主に関心のある参照を保持するものとして宣言する手段、および (2)WeakReferenceオブジェクトへの唯一の参照が「他の誰かにとって関心のある」ストレージの場所にあることを示している可能性があります。は便利なタイプですがWeakReference、弱い参照を強い参照に変える行為は、ターゲットが消えても誰も気にしないというシステムの認識を妨げる可能性があります。

于 2012-06-09T18:09:58.743 に答える