【问题标题】:When does JNI decide that it can release memory?JNI 什么时候决定可以释放内存?
【发布时间】:2013-03-01 12:05:32
【问题描述】:

当我将一个直接的 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();

然后像上面一样做,我存储一个指向那个字节[]的指针,并想保留它一段时间。 JVM 如何/何时/为什么会在 Java 的支持字节 [] 之后出现?

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

【问题讨论】:

    标签: jvm java-native-interface


    【解决方案1】:

    简短的回答是:如果函数实现了原生方法,那么一旦你返回,指针就会失效。

    为避免这种情况,您应该为所有打算在返回后保持有效的对象获取一个全局引用。有关详细信息,请参阅local and global references 上的文档。

    要更好地了解 JNI 如何管理来自本机代码的引用,请参阅 documentation on PushLocalFrame/PopLocalFrame

    【讨论】:

    • 假设我发布的第二个场景:我从 Java 返回一个 byte[]。它会被复制,对吧?我怎么知道什么时候被复制了?是否有文档告诉我 byte[] 将被复制?我只是假设它确实如此,因为有一个 ReleaseByteElements() 函数。但最重要的是:我可以使用 free() 代替 ReleaseByteElements() 调用吗?
    • 不一定。如果您查看文档,GetByteArrayAlElements 的第三个参数 (isCopy) 会告诉您它是否已被复制。但是你不应该假设你可以使用free()。它可能适用于某些版本的 JVM,但在将来或在其他 JVM 中会中断。坚持使用 API。
    • jop,你知道如果我执行 NewDirectByteBuffer(b) 其中 b 是 C 中的 malloc'ed 内存,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 中得到修复。如果不是这样,我会很生气:/
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-07-15
    • 1970-01-01
    • 2012-04-06
    相关资源
    最近更新 更多