2010-01-04 74 views
7

我想在C分配一些內存,並把它與Java對象實例相關聯的,是這樣的:Java JNI - 將C中分配的資源與java對象關聯起來?

void configure(JNIEnv *object, jobject obj, ....) { 
    char *buf = new char[1024]; 
    // associated <buf> with <obj> somehow 
} 

再後來釋放內存的Java對象被垃圾回收時 - 通過調用我能做到這一點java對象的finalize()方法的JNI函數。

問題是,如何將C指針與java對象關聯?在對象中保留一個長字段並將指針指向long?有沒有更好的辦法?

+2

dup:http://stackoverflow.com/questions/214699/jni-memory-management-using-the-invocation-api – falstro 2010-01-04 07:59:59

+0

排序,在這個問題中沒有討論如何將C對象關聯到java實例。在提供的例子中,指針被投射得很長。這是唯一的方法嗎? – Viktor 2010-01-04 08:44:19

回答

16

通常,如果您想將指針從C傳輸到Java,建議使用long,以便在平臺爲64位時有足夠的位來存放指針值。

然後,看看ByteBuffer.allocateDirect()它創建了一個ByteBuffer實例哪些存儲器可以與C.共享可以從Java端分配這樣的直接ByteBuffer然後將它作爲jobject到JNI函數和此JNI函數內您使用GetDirectBufferAddress函數。

另一種方法是用本機端的NewDirectByteBuffer JNI函數來包裝內存本地區域。它給你一個jobject你傳回到Java端(注意本地和全局引用)。請注意,一旦創建了包裝本機內存的直接ByteBuffer,您仍然負責管理本機內存:在某些時候,您必須在您的本機代碼中調用delete buf;,Java不會這樣做爲你。

+0

謝謝!如果我理解正確,使用ByteBuffer.allocateDirect()將避免指針傳遞+內存管理;這種方式ByteBuffer管理內存。 – Viktor 2010-01-04 10:06:28

+1

從Java端分配直接的ByteBuffer讓Java分配內存塊,當'finalize'運行時將釋放內存塊。唯一的缺點是你不知道垃圾收集器何時通過,所以你不知道內存什麼時候分開釋放,它會在你完成緩衝區後釋放。 – 2010-01-04 10:14:16

+0

+1整潔!好答案。 – JesperE 2010-01-04 13:18:46

0

Java沒有任何原生指針的概念,因此將它存儲爲long是唯一真正的選項。但是您不應該依賴finalize來釋放指針;最終確定方法作爲清理資源的手段並不可靠。有關更多詳細信息,請參閱this question