パッケージjava.lang.ref


パッケージjava.lang.ref
参照オブジェクト・クラスを提供し、限定されたレベルでのガベージ・コレクタとの対話を可能にします。 ほかのあるオブジェクトがガベージ・コレクタによってすでに再生されていても、そのオブジェクトを指す参照を維持したい場合に、プログラムは参照オブジェクトを使うことができます。 さらに、プログラムは、あるオブジェクトへの到達可能性が変わったとガベージ・コレクタが判断したあとで、通知を受けるようにすることができます。

参照オブジェクト

参照オブジェクトは、その参照自体をほかのオブジェクトと同じように検査および操作できるようにするために、ほかのオブジェクトへの参照をカプセル化します。 弱いものから順に、ソフト、およびファントムという3種類の参照オブジェクトが提供されます。 各型は、次に定義されているように、対応する到達可能性のレベルがそれぞれ異なります。 ソフト参照はメモリー依存キャッシュを実装するためのものであり、弱い参照はキー(値)の再利用を妨げない正規化マッピングを実装するためのものであり、ファントム参照は事後クリーンアップ・アクションをスケジュールするためのものです。 事後クリーンアップ・アクションは、Cleanerで登録および管理することもできます。

各参照オブジェクト型は、抽象ベースReferenceクラスのサブクラスによって実装されます。 それらのサブクラスのインスタンスは、リファレントと呼ばれる、特定のオブジェクトへの参照をカプセル化します。 各参照オブジェクトは、参照を取得およびクリアするためのメソッドを提供します。 クリア処理は提供されますが、参照オブジェクトは不変であるため、setオペレーションは提供されません。 プログラムは、これらのサブクラスをさらにサブクラス化して目的にあったフィールドおよびメソッドを追加することも、これらのサブクラスを変更しないでそのまま使うこともできます。

到達可能性

「到達可能」オブジェクトは、任意の「ライブ・スレッド」 (JLS 12.6.1に記載のとおり)から継続的に計算される可能性のある任意のオブジェクトです。

到達可能性には最強から最弱までのレベルがあり、これはオブジェクトのライフ・サイクルを反映します。 それらは、機能的に次のように定義されます。

  • オブジェクトがアクセス可能であり、参照オブジェクトの参照をトラバースせずにそのオブジェクトにアクセスできる場合は、「強く到達可能な」です。
  • ソフト到達可能なオブジェクトとは、強到達可能ではないが、ソフト参照をトラバースすることで到達できるオブジェクト。
  • 弱到達可能なオブジェクトとは、強到達可能でもソフト到達可能でもないが、弱参照をトラバースすることで到達できるオブジェクト。 弱到達可能なオブジェクトへの弱参照がクリアされると、そのオブジェクトはファイナライズの対象となる。
  • ファントム到達可能オブジェクトとは、強到達可能でも、ソフト到達可能でも、弱到達可能でもなく、ファイナライズされており、ファントム参照がそれを指しているオブジェクト。
  • 最後に、オブジェクトがどのようにも到達できない場合、そのオブジェクトは到達不可能であり、そのため再生の対象となる。

通知

プログラムは、ReferenceQueueを持つ適切な参照オブジェクトを「登録」して、オブジェクトの到達可能性の変更を通知するようにリクエストできます。 これは、参照オブジェクトの作成時に参照キューをコンストラクタ引数として指定することによって行われます。 ガベージ・コレクタが参照の到達可能性が参照のタイプに対応するように変更されたと判断してからしばらくすると、参照がクリアされ、関連するキューに追加されます。 この時点で、参照はキューに入っているとみなされます。 プログラムは、関連する参照がキューで使用可能になったときに、参照の到達可能性の変更を学習します。 プログラムは、ReferenceQueue.poll()またはReferenceQueue.remove()メソッドを使用して、キュー(つまり、「デキュー」します)から参照を削除できます。 参照の到達可能性の変化への対応に必要な追加の状態は、カスタム参照サブクラスのフィールドに格納し、参照がキューから返されたときにアクセスできます。

登録された参照オブジェクトとそのキューの関係は一方向です。 つまり、キューは登録されている参照の履歴を記録しません。 登録されている参照自体が到達不可能になると、それは絶対にキューに入れられません。 プログラムは、参照オブジェクトが参照に関心があるかぎり、参照オブジェクトが到達可能であることを保証する責任があります。

プログラムによっては、あるスレッドを、1つ以上のキューからの参照オブジェクトの削除およびそれらの処理専用にするように選択されますが、これは、まったく必要ありません。 多くの場合にうまく機能する方法は、かなり頻繁に行われるほかのアクションを実行する間に参照キューを検査することです。 たとえば、弱キーを実装するために弱参照を使用するハッシュ表の場合は、表がアクセスされるたびに自分の参照キューに対してポーリングします。 これは、WeakHashMapクラスの仕組みです。 ReferenceQueue.pollメソッドは内部データ構造をチェックするのみであるため、このチェックによってハッシュ表アクセス方法へのオーバーヘッドはほとんど発生しません。

メモリー整合性特性

参照、参照キューおよびガベージ・コレクタ間の特定の相互作用は、happens-before関係を形成します:
  • Reference.reachabilityFence(x) happen-beforeをコールする前のスレッド内のアクションでは、ガベージ・コレクタはxへの参照をすべてクリアします。
  • ガベージ・コレクタhappens-beforeによる参照のクリアは、ガベージ・コレクタが参照をエンキューします。
  • 参照(ガベージ・コレクタによって、またはReference.enqueue()への正常なコールによって) happens-beforeのエンキューは、キュー(「デキュー済み」)から削除されます。
  • registeredオブジェクトへの参照のデキューは、クリーナ・スレッドhappens-beforeによって、クリーナ・スレッドがそのオブジェクトのクリーニング・アクションを実行します。
前述のhappens-beforeエッジのチェーンにより、xReference.reachabilityFence(x) happen-beforeクリーン・アップ・コードより前のスレッド内のアクションがCleanerスレッドで実行されるようになります。 特に、reachabilityFence(x)より前に行われたxの状態に対する変更は、追加の同期なしでCleanerスレッドで実行されているクリーンアップ・コードに表示されます。 「JLS 17.4.5」を参照してください。

参照、ファイナライザおよびガベージ・コレクタ間の相互作用も、happens-before関係を形成します:

  • Reference.reachabilityFence(x) happen-beforeをコールする前のスレッド内のアクションでは、xのファイナライザはファイナライザ・スレッドによって実行されます。
これにより、xReference.reachabilityFence(x) happen-beforeクリーン・アップ・コードより前のスレッド内のアクションがファイナライザ・スレッドで実行されるようになります。 特に、reachabilityFence(x)より前に行われたxの状態に対する変更は、追加の同期なしでファイナライザ・スレッドで実行されているクリーンアップ・コードに表示されます。 「JLS 17.4.5」を参照してください。

導入されたバージョン:
1.2
  • クラス
    説明
    Cleanerは、一連のオブジェクト参照および対応するクリーニング・アクションを管理します。
    Cleanableは、Cleanerに登録されているオブジェクトとクリーニング・アクションを表します。
    ファントム参照オブジェクトです。ファントム参照オブジェクトがキューに入れられるのは、キューに入れておかないとそれらのリファレントが再生される可能性があるとコレクタが判断したときです。
    参照オブジェクトための抽象基底クラスです。
    参照キューです。到達可能性が適切に変更されたことが検出されると、登録されている参照オブジェクトはガベージ・コレクタによって参照キューに追加されます。
    メモリー要求に応じてガベージ・コレクタの判断でクリアされるソフト参照オブジェクトです。
    弱参照オブジェクトです。弱参照オブジェクトは、その弱参照オブジェクトのリファレントがファイナライズ可能になり、ファイナライズされ、そして再生されることを阻止することはありません。