2011-06-30 33 views
0

有沒有什麼辦法可以從對象內部判斷我是否超出範圍?我能否告訴我是否超出範圍?

我有一個必須關閉的對象。如果沒有關閉,則泄漏得到保證。如果可能,我想嘗試自動關閉。

我的一個私有實例變量是在關閉期間必須關閉的線程。我猜測線程的存在會導致未封閉的對象永遠不會被gc'd。

保羅

+0

什麼是「自動關閉」?真正理解你想達到的目標是很困難的。一個通用的解決方案是隻需添加一個你不需要對象時調用的清理方法。這個方法將完成像結束線程,關閉連接等任何需要的操作。 –

回答

2

沒有的「範圍外範圍」在Java中的概念,因爲所有的對象都是在堆上。一旦你說'新',唯一能爲你清理的東西就是gc。你可以使用try/finally,並且你可以有一個終結器等,但就是這樣。

您需要閱讀有關最終化方法,然後也許還需要了解幻影參考。

http://weblogs.java.net/blog/enicholas/archive/2006/05/understanding_w.html

+0

我不想等到最後確定,我想在我超出範圍之後立即關閉(或很快關閉)。另外,我認爲finalize不會被稱爲,因爲我內心的線索我不是GC的候選人。 – OldCurmudgeon

2

Java沒有析構函數。

如果一個對象需要顯式清除超出Java的內存自動垃圾回收,那麼您可以提供一個明確的方法 - 例如close(),terminate()或dispose()。

如果您的線程通過持有引用來阻止對象的垃圾回收,它可能會持有weak reference,這不會阻止垃圾回收。

使用弱引用,可以判斷引用的對象是否已被垃圾收集。但是,您無法分辨是否有合格用於垃圾收集。

+0

我不認爲我在尋找一個析構函數,我正在尋找一個我不再可及的時刻,在這一刻我會打電話給自己關閉。 – OldCurmudgeon

+0

這可能會引用計數,就像在C++中使用boost :: shared_ptr一樣。但是Java垃圾收集器可能會在不可預測的時間內檢測到不可訪問性,或者永遠不會。所以你不能依賴終結器,並且你需要像java.io.InputStream.close()這樣的顯式方法。 –

0

如果您的意思與C++中的RAII是如何相似的,那麼答案是否定的 - Java堅持告訴您何時不再需要某些東西,如果您需要做某些事情來清理它。通常的方式做到這一點是:

Something s = new Something(); 
try 
{ 
    // do things 
} 
finally 
{ 
    s.close(); 
} 

C#有一個using關鍵字是整容了一陣。

0

在研究這個時,我確實想出了一個近乎解決方案。從本質上講,當你的Runnable被創建時,獲取創建你的線程的副本,並偶爾檢查它的堆棧跟蹤。如果它變成空的,你可以放心地假定它們已經完成了......或者你能嗎?

private void testThreads() throws InterruptedException { 

    class ThreadTest implements Runnable { 

    final Thread maker; 

    private ThreadTest() { 
     // Grab the maker's thread. 
     maker = Thread.currentThread(); 
    } 

    private boolean makerIsAlive() { 
     // If maker's stack trace hits empty it is fair to assume they are done. 
     return maker.getStackTrace().length != 0; 
    } 

    public void run() { 
     // Keep checking the stack using a stacktrace. 
     while (makerIsAlive()) { 
     try { 
      // Get out of here if maker has finished. 
      // Wait one second. 
      Thread.sleep(1000); 
     } catch (InterruptedException ex) { 
      break; 
     } 
     } 
     System.out.println("====== Maker has finished! Exiting. ======"); 
    } 
    } 

    Thread thread = new Thread(new ThreadTest()); 
    thread.start(); 
    // Wait for 10 seconds. 
    long finishTime = System.currentTimeMillis() + 10 * 1000; 
    while (System.currentTimeMillis() < finishTime) { 
    Thread.sleep(500); 
    } 
} 
相關問題