2016-12-10 8 views
0

ファントムリファレンスの使用法と多少混同されます。ガント・コレクターがそれを好きなときはいつでも、ファントム・リファレンスのみを指し示すオブジェクトを収集することができます。しかし、私の例では意図したとおりに動作していません。ファントムリファレンスがGC中に解放されない

import java.lang.ref.PhantomReference; 
import java.lang.ref.Reference; 
import java.lang.ref.ReferenceQueue; 
import java.util.HashMap; 
import java.util.Map; 


public class ClassTest { 
    private static Thread m_collector; 
    private static boolean m_stopped = false; 
    private static final ReferenceQueue refque = new ReferenceQueue(); 
    Map<Reference,String> cleanUpMap = new HashMap<Reference,String>(); 


    public void startThread() { 
     m_collector = new Thread() { 
      public void run() { 
       while (!m_stopped) { 
        try { 
          Reference ref = refque.remove(1000); 
          System.out.println(" Timeout "); 
               if (null != ref) { 
          System.out.println(" ref not null "); 

         } 
        } catch (Exception ex) { 
         break; 
        } 
       } 
      } 
     }; 
     m_collector.setDaemon(true); 
     m_collector.start(); 
    } 

    public void register() { 
     System.out.println("Creating phantom references"); 

     class Referred { 
       } 

      Referred strong = new Referred(); 
      PhantomReference<Referred> pref = new PhantomReference(strong, refque); 
    // cleanUpMap.put(pref, "Free up resources"); 
      strong = null; 

    } 



public static void collect() throws InterruptedException { 
    System.out.println("GC called"); 
    System.gc(); 
    System.out.println("Sleeping"); 
    Thread.sleep(5000); 
} 

public static void main(String args[]) throws InterruptedException { 
    ClassTest test= new ClassTest(); 
    test.startThread(); 

    test.register(); 
    test.collect(); 
    m_stopped = true; 
    System.out.println("Done"); 
} 

} 

上記の例では、私が実行すると、そのオブジェクトが "強く"自動的にガベージコレクションされないことがわかります。私はオブジェクトがヌルに割り当てられているときにオブジェクトが自動的にガベージコレクションを取得することを期待していました。不思議なことに、それは私がレジスタ関数で次の行のコメントを外すときだけガベージコレクションされます。

//cleanUpMap.put(pref, "Free up resources");" 

その背景には何がありますか?しかし、私がMain関数自体に幻の参照を作成した場合、この問題は発生しません。つまり、次のコードのように、main関数内でnullに "strong"が代入されると、オブジェクトは自動的にガベージコレクションされます。

public static void main(String args[]) throws InterruptedException { 
    System.out.println("Creating phantom references"); 

    // The reference itself will be appended to the dead queue for clean up. 
    ReferenceQueue dead = new ReferenceQueue(); 

    PhantomReference<Referred> phantom = new PhantomReference(strong, dead); 


    strong = null; 

    // The object may now be collected 
    System.out.println("Suggesting collection"); 
    System.gc(); 
    System.out.println("Sleeping"); 
    Thread.sleep(5000); 

    // Check for 
    Reference reference = dead.poll(); 
    if (reference != null) { 
     System.out.println("not null"); 
    } 
    System.out.println("Done"); 
} 

両方のシナリオで動作が異なるのはなぜですか?

+1

[ファイナライズを実行するためにのみ使用されるWeakReferenceを強く参照する必要がありますか?](http://stackoverflow.com/questions/32108427/do-i-need-to-keep-弱参照の弱参照、つまりそれだけで使用される) – the8472

答えて

1

あなたのファントム参照は通常のJavaオブジェクトで、到達できない場合はガベージコレクションされます。

参照オブジェクトと同じコレクションの前または上にファントム参照が収集されている場合、参照キューには追加されません。

すべてのファントム参照をコレクションに配置すると、参照が早すぎてガベージコレクションされなくなります。

通常、参照キューと並んで未処理のファントム参照の専用収集が必要です。

this articleには、ファントムリファレンスベースの死後のクリーンアップの実装例があります。

+0

、http://stackoverflow.com/q/41396476/2674303をご覧ください。 – gstackoverflow

関連する問題