10

他のスレッドから参照されなくなったときに、Closeableオブジェクトを適切に閉じたい。

私はいくつかの小さなテストを書きましたが、オブジェクトがエンキューされた後、getメソッドはnullを返します。つまり、pollメソッドは参照対象のない適切なオブジェクトを返します。

  public static void main(String[] args)
  {
   ReferenceQueue<Closeable> reaped = new ReferenceQueue<Closeable>();
   Closeable s = <SOME CLOSEABLE IMPL>;
   WeakReference<Closeable> ws = new WeakReference<Closeable>(s, reaped);
   s = null;

   System.gc();
   Closeable ro = (Closeable)reaped.poll().get();
   ro.close();
  }

前もって感謝します。どんな助けでもありがたいです。

4

2 に答える 2

7

まず、閉じるだけの場合は、を使用しますPhantomReference。次に、参照キューから、参照poll()が返されることを保証するものではありません。そして、実際のオブジェクト(指示対象)を取り戻すことは決してありません。

が閉じていることを確認したい場合はCloseable、自分でそれらを追跡する必要がありますMap<Reference<?>, Closeable>。次にpoll()、参照キューを取得すると、最終的に取得し、refそれを使用しCloseableてマップからを取得する必要があります。

   class MyThing {
      Closeable c;
   }

   Map<Reference<MyThing>, Closeable> m = new HashMap();
   ReferenceQueue<MyThing> reaped = new ReferenceQueue<MyThing>();

   MyThing mt = new MyThing();
   mt.c = new MyClosable();

   Reference<MyThing> pref = new PhantomReference<MyThing>(mt, reaped);
   m.put(pref, mt.c);

   mt = null;


   System.gc();
   Reference<MyThing> rf = reaped.poll();
   while (rf != null) {
     m.get(rf).close(); 
     rf = reaped.poll();
   }

これを行う本当の理由がない場合、または実際に何をしているのかわからない場合は、このようなことをしないでください。

あなたはあなたのファイルを閉じることができますfinallyそしてところでそれがファイルやソケットなどに関するものであれば、それらはあなたのために閉じられます(彼らはすでに実装していますfinalize()

于 2012-06-04T09:28:01.633 に答える
0

Here I want to mention a couple of points

  1. The get() method is not meant to be used for finalization task The purpose of get() method is to have access to the referent object because we use WeakReference object to have reference to an object which doesn't have a direct reference (i.e not strongly reachable). The referent object could be garbage collected any time. The get() method is expected to return the referent object until it is not garbage collected, and return null when it is garbage collected. This make sense because the referent object is not available post garbage collection. The get() method is not meant for doing finalization task like closing Closable object.

  2. The approach to do finalization task is not straight forward. The approach to do finalization task is to retrieve the WeakReference object after it's enqueued in ReferenceQueue post garbage collection. and call it's clear() method. You can not have the referent object to do finalization. Because at this point it is believed that the referent object has been garbage collected. The approach is to have a custom implementation of the Reference object that will extend WeakReference. You can override the clear() method to place any cleanup logic. Still you cant have any reference to the referrent object in the implementaion as it will block the referrent object from being garbage collected. If you have to cleanup some states , for example the referent object has some closeble object or connection etc, they need to be saved as the instance variable under the implementaion and in the clear method they can be finalized. As the clear() method gets called the finaliation logic will be executed. Thus the Reference object will facilitate the finalization.

  3. Still the above approach is not useful here as even the custom implementation of WeakReference object can not keep reference to the referent object itself as it will block the referent object to be garbage collected. You are facing such difficulty because using WeakReference for Closeble and expecting to close it as a post-mortem activity is not right usecase. Because closing a Closeble is not qualified to be a post mortem activity. Post mortem activity is what is done after an object is garbage collected i.e it doesn't have it states at all. Closing a Closeble object is a pre-mortem activity i.e expected to be done in the finally block or as it is in the thread where it is created. There is no point of delaying it post the garbage collection of the Closeble. ReferenceQueue is designed to be used in post-mortem activity , not for pre-mortem activity.

于 2021-05-08T17:05:42.917 に答える