2012-03-02 101 views
1

我正在嘗試編寫一個Java單元測試,用於測試對終結器調用對象的影響。爲什麼在這個單元測試中不能調用finalize函數?

爲了確保終結器被調用,我使用了一個WeakReference方法,我在其他地方看到了stackoverflow。

我的問題是,在本次測試TestFinalizer的finalize方法不會被調用即使WeakReference的只是一個迭代後出現空:

public class FinalizerTest {  
    private static class TestFinalizer { 
     public static class Callback { 
      public int NumFinalize = 0; 

      public void finalized(){ 
       NumFinalize++; 
      } 
     } 
     private Callback callback; 

     public TestFinalizer(Callback callback){ 
      this.callback = callback; 
     } 

     @Override 
     public void finalize() throws Throwable { 
      callback.finalized(); 
      super.finalize(); 
     } 
    } 

    @Test 
    public void testForceFinalizer(){ 
     TestFinalizer.Callback callback = new TestFinalizer.Callback(); 
     TestFinalizer testFinalizer = new TestFinalizer(callback); 
     // Try to force finalizer to be called 
     WeakReference<Object> ref = new WeakReference<Object>(testFinalizer); 
     testFinalizer = null; 
     int maxTries = 10000, i=0; 
     while (ref.get() != null && i<maxTries) { 
      ++i; 
      System.gc(); 
     } 
     if (ref.get() != null) 
      fail("testFinalizer didn't get cleaned up within maxTries"); 

     // Last line passes, next fails! 
     assertEquals("Should be exactly one call to finalizer", 1, callback.NumFinalize); 
    } 
} 

回答

0

在固定我的機器在這個問題上的單元測試添加了Thread.sleep(3000):

@Test 
    public void testForceFinalizer() throws InterruptedException 
    { 
    FinalizerTest.TestFinalizer f = new FinalizerTest.TestFinalizer(null); 
    FinalizerTest.TestFinalizer.Callback callback = f.new Callback(); 
    TestFinalizer testFinalizer = new TestFinalizer(callback); // Try to 
            // force 
            // finalizer 
            // to be 
            // called 
    WeakReference<Object> ref = new WeakReference<Object>(testFinalizer); 
    testFinalizer = null; 
    int maxTries = 10000, i = 0; 
    while (ref.get() != null && i < maxTries) 
    { 
     ++i; 
     System.gc(); 
    } 
    if (ref.get() != null) 
     fail("testFinalizer didn't get cleaned up within maxTries"); // Last 
            // line 
            // passes, 
            // next 
            // fails! 
    System.out.println("Value: " + callback.NumFinalize); 
    Thread.sleep(3000); 
    assertEquals("Should be exactly one call to finalizer", 1, 
     callback.NumFinalize); 

    System.out.println("Value after: " + callback.NumFinalize); 

    } 

這是assertEquals呼叫前右執行。正如其他人所說,調用System.gc()是一個建議,如果可以選擇,系統可以忽略你。作爲補充,我也確定沒有什麼是靜態的,不確定這是否重要。

+0

是的,Thread.sleep(3000);就在那裏爲我修好了。我想這是因爲儘管弱裁判已經被淘汰,但終結者線程還是要做到這一點...... – tdaffin 2012-03-03 00:16:05

4

您對System.gc通話只是一個建議,不是命令。

沒有明確保證任何終結器將被調用。

在您的情況下,可能會在VM退出時調用終結器。

0

調用gc方法表明Java虛擬機花費的努力是回收未使用的對象,以使它們當前佔用的內存可供快速重用。

System.gc()不會觸發垃圾回收。

可能幸運地看到,如果你添加一個 Thread.sleep(xxx)到while循環,只是等待一段時間被稱爲終結。 (沒有幫助,只是測試)

+0

雖然爲我工作 - 請參閱我標記爲答案的答覆。 – tdaffin 2012-03-03 00:16:54

相關問題