2013-03-01 42 views
1

當我將一個直接的ByteBuffer返回給JNI時,直到它能被JVM/GC回收多久?JNI什麼時候決定可以釋放內存?

假設我有這樣的功能:

void* func() 
{ 
    [ ... ] 
    jobject result = env->CallStaticObjectMethod(testClass, doSomethingMethod); 
    void* pointerToMemory = env->GetDirectBufferAddress(result); 
    return pointerToMemory; 

} 

的JVM不可能知道我要多久才能使用pointerToMemory,對不對?如果我想暫時保持這個地址和相應的記憶,該怎麼辦?

假設我想規避這個問題,並從Java到JNI返回一個byte []是這樣的:

ByteBuffer buf; 
byte[] b = new byte[1000]; 
buf = ByteBuffer.wrap(b); 
buf.order(ByteOrder.BIG_ENDIAN); 

return buf.array(); 

然後執行上面一樣,我存儲一個指針字節[]和希望堅持一會兒。如何/何時/爲什麼JVM會在來自Java的支持byte []之後?

void* function() 
{ 
    jbyteArray byteArr = (jbytearray)env->CallStaticObjectMethod(testClass, doSomethingMethod); 
    jbyte *b= env->GetByteArrayElements(byteArr, 0); 
    return b; 
} 

回答

1

簡短的回答是:如果函數實現了一個本地方法,只要返回,指針就會失效。

爲了避免這種情況,您應該爲返回後您打算保持有效的所有對象獲取全局引用。有關更多信息,請參閱local and global references上的文檔。

要更好地理解JNI如何管理來自本地代碼的引用,請參閱documentation on PushLocalFrame/PopLocalFrame

+0

假設我發佈的第二個szenario:我從Java返回一個byte []。它會被複制,對吧?我怎麼知道什麼時候被複制?是否有文檔告訴我字節[]將被複制?我只是假設它,因爲有一個ReleaseByteElements()函數。但是這裏最重要的是:我可以使用free()而不是ReleaseByteElements()調用嗎? – Blub 2013-03-01 12:21:53

+0

不一定。如果您查看文檔,第三個參數('isCopy')到'GetByteArrayAlElements'會告訴您它是否已被複制。但是你不應該假設你可以使用'free()'。它可能適用於某些版本的JVM,但可以在將來或其他JVM中使用。堅持API。 – jop 2013-03-01 12:31:30

+0

jop,你知道嗎,如果我做NewDirectByteBuffer(b)其中b是malloc在C中的內存,JVM會嘗試去觸摸並刪除它嗎?如果不是的話,我認爲對我來說最安全的選擇就是在這個鏈接中創建一個JNI調用,這樣我就可以完全控制我的內存,並且可以隨時在C中釋放它。 http://stackoverflow.com/questions/5060307/bytebuffer-not-releasing-memory我唯一剩下的擔心是我要碰到這個JVM bug,因爲我確實需要很多這些緩衝區。 http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=4857305有沒有辦法用byte [] – Blub 2013-03-01 12:49:28