2016-02-12 169 views
3

假設一方面我們有一個用env->NewDirectByteBuffer()創建的直接字節緩衝區。另一方面,我們有類似的直接緩衝區,但是用ByteBuffer.allocateDirect()創建。顯然,這兩個對象都應該由JVM以相同的方式進行管理,包括管理支持本地緩衝區,第一種情況由用戶提供,第二種情況由JVM從本地堆中分配。JNI直接緩衝區。誰負責本地緩衝區釋放?

當然JVM必須在第二個對象的GC_ing過程中釋放後臺緩衝區(用ByteBuffer.allocateDirect()實例化)。

我的問題:JVM會在第一個對象的GC_ing期間嘗試釋放緩衝區(用env->NewDirectByteBuffer()實例化)?

P.S.在JNI文檔中,我都沒有找到明確的答案。最有用的信息在這裏http://www.ibm.com/developerworks/library/j-nativememory-linux/index.html

直接ByteBuffer對象會自動清理自己的本地緩存 但只能做這麼爲Java堆GC的一部分 - 所以他們不 自動應對壓力本機堆。

所以看起來JVM會在GC傳遞過程中釋放後臺緩衝區,但是沒有任何關於釋放器的提及。是平原free()還是別的什麼。

回答

2

當你調用JNI NewDirectByteBuffer(void* address, jlong capacity)一個DirectByteBuffer對象將被創建,使用下面的構造:

private DirectByteBuffer(long addr, int cap) { 
    super(-1, 0, cap, cap); 
    address = addr; 
    cleaner = null; 
    att = null; 
} 

注意,cleaner屬性爲null。

如果您通過ByteBuffer.allocateDirect()創建DirectByteBuffer,則會設置cleaner屬性(請參閱源代碼DirectByteBuffer)。

現在清潔器是一個實用程序對象,其clean方法當緩衝器是垃圾收集運行(參見本explanation細節)。

對於通過ByteBuffer.allocateDirect()構建的緩衝區,清理程序將釋放直接內存。

對於JNI構造的緩衝區,沒有這樣的操作完成。你需要自己釋放這個記憶。

+0

清除。看起來像Android使用相同的方法。 Android SDK詳盡評論:'/ ** *表示我們不擁有的一塊內存。 (我們沒有取得對應於 *的內存的所有權來指導由JNI NewDirectByteBuffer函數創建的緩衝區。) * /' – Sergio