2013-10-31 98 views
3

如何檢測Java對象的GC調用的最佳方法?釋放原生對象

我爲C++代碼構建了一個Java包裝器,每次調用GC時都需要在C++代碼中分配內存

我看到了一些解決方案,但都沒有讓我滿意。

之一是:

Object obj = null; 
try{ 
    obj = new Object(); 
    // do things 
} finally { 
    if(obj != null){ 
     obj.freeCObjects(); 
    } 
} 
+1

_I每次調用GC時都需要釋放內存_是不是GC已經在做什麼? –

+0

@SotiriosDelimanolis我在談論從C++包裝對象釋放內存。 – Victor

+0

其他解決方案有什麼問題?你在尋找什麼樣的改進? – Keppil

回答

1

有隻垃圾收集器要做到這一點沒有可靠的方法。通常的方法(例如,由使用本地組件的SWT UI工具包採用)是要求客戶端在對象上調用disposedestroy方法。

+0

這是一個好方法。我已經這麼做了。但是沒有其他解決方案? – Victor

+0

@Victor沒有其他可靠的解決方案,沒有。終結器不能保證永遠運行,即使它們運行,JVM也可能在很長一段時間內無法運行,特別是如果JVM看不到對象使用的Java堆空間太多(因爲它們主要在其他地址空間)。此外,雖然在終結器中提供「救援」關閉操作是很好的,但在文檔中指出這一點將不可避免地導致懶惰的程序員無法正確關閉資源並遇到麻煩。 – chrylis

2

您可能需要考慮java.lang.Object上的finalize()方法。

It is called by the garbage collector on an object when garbage collection determines 
that there are no more references to the object. 

一般情況下,最好是避免終結,因爲JVM不保證finalize()被稱爲有史以來的任何對象,然而,當有需要清理原生(通常非Java)的資源,終結者可能是有用的。

下面是一個簡單的例子:

Object obj = new Object() { 
     @Override 
     protected void finalize() throws Throwable { 
      System.out.println("finalize object"); 
      super.finalize(); 
     } 
    }; 

終結可以通過垃圾收集被調用。

0

每次GC運行時都很難釋放內存。當GC運行時,您更希望將內存釋放給未使用的對象。

你可以通過提供一個封裝來實現finalize()來釋放資源。當包裝被丟棄時,您可以清理資源。如果你真的希望這消失在每個GC上,你可以持有一個WeakReference到包裝器。

順便說一句OpenJDK/Oracle HotSpot JVM有另一個更輕量級的機制來釋放資源。這涉及使用未添加到最終化隊列中的Cleaner對象(意味着它可以更快地釋放)請參閱以Cleaner爲例的直接ByteBuffer。