当我将直接的ByteBuffer返回给JNI时,要多久才能被JVM / GC回收?
假设我有一个像这样的函数:
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();
然后执行与上述相同的操作,我存储了一个指向该byte []的指针,并想保留一会儿。 从Java支持字节[]之后,JVM如何/何时/为什么会出现?
void* function()
{
jbyteArray byteArr = (jbytearray)env->CallStaticObjectMethod(testClass, doSomethingMethod);
jbyte *b= env->GetByteArrayElements(byteArr, 0);
return b;
}
简短的答案是:如果函数实现了本机方法,则返回后指针将立即无效。
为避免这种情况,您应该获得返回后打算保持有效的所有对象的全局引用。 有关更多信息,请参见有关本地和全局参考的文档。
为了更好地理解JNI如何管理本机代码中的引用,请参阅PushLocalFrame / PopLocalFrame上的文档。
假设我发布了第二个szenario:我从Java返回了byte []。它将被复制,对不对?我怎么知道什么时候被复制?是否有文档告诉我byte []将被复制?我只是假设这样做,因为有一个ReleaseByteElements()函数。但这是最重要的事情:我可以使用free()代替ReleaseByteElements()调用吗?
不必要。如果您查看文档,则GetByteArrayAlElements的第三个参数(isCopy)会告诉您是否已复制它。但是您不应该假设可以使用free()。它可能适用于某些版本的JVM,但将来或其他JVM中会中断。坚持使用API??。
乔普,您知道如果我执行NewDirectByteBuffer(b),其中b是C中的已分配内存,那么JVM是否会尝试触摸并删除它?如果没有,我认为对我来说最安全的选择是像在此链接中那样进行JNI调用,这样我就可以完全控制自己的内存,并可以随时在C中释放它。 stackoverflow.com/questions/5060307/我唯一剩下的担心是,我将遇到此JVM错误,因为我确实需要许多这些缓冲区。 bugs.sun.com/bugdatabase/view_bug.do?bug_id=4857305是否有办法用byte []完成所有这些操作?
我认为最好的解决方案可能是简单地从我从Java创建的缓冲区中获得的直接缓冲区地址中手动复制所有内容。这样,Java GC可以让我一个人呆着,但是我可以随意释放内存。所以我只希望此DirectBuffer错误在1.6或1.7中得到修复。否则我会很生气:/