2013-03-01 77 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