Java JNI引用类型,传递ByteBuffers

时间:2015-04-22 21:37:13

标签: java c reference garbage-collection java-native-interface

我在native中创建并分配DirectByteBuffer。然后我将它传回Java。由于DirectByteBuffer是在C中分配的,因此它驻留在堆内存中并且免受"免疫"到Java的垃圾收集器,对吗?解放它的唯一方法是使用free()?

但是在JNI中缓冲对象上调用(* env) - > GetObjectRefType()会返回1,这意味着它是本地引用。当JNI方法返回时,Java的GC会自动释放本地引用。在这种情况下,有人可以澄清GC被释放的内容吗?我应该使用(* env) - > NewGlobalRef(env,bb)将分配的缓冲区转换为Global ref吗?

C:

JNIEXPORT jobject JNICALL Java_main_Main_byteBufferTest2(JNIEnv *env, jobject obj){
    double *dp = malloc(sizeof(double)*100);
    jobject bb = (*env)->NewDirectByteBuffer(env, (void*)dp, sizeof(double)*100);
    return bb;
}

爪哇:

ByteBuffer dbb = byteBufferTest2();

1 个答案:

答案 0 :(得分:0)

当JNI方法返回时,将释放本地引用。但是,如果您返回对Java代码的本地引用,那么Java代码现在可以引用它。当没有引用时,对象可以垃圾收集这不是一回事。

  

由于DirectByteBuffer是在C中分配的,它驻留在堆内存中并且对Java的垃圾收集器“免疫”,对吗?

错误。

  

释放它的唯一方法是从C使用free()?

错误。它是一个Java对象,与任何其他Java对象一样受GC影响。如果您尝试free()它将会崩溃。

  

但是在JNI中缓冲对象上调用(* env) - > GetObjectRefType()会返回1,这意味着它是本地引用。

正确。

  

当JNI方法返回时,Java的GC会自动释放本地引用。

没有。你正在混合对象和引用。该引用由JNI释放。当没有更多引用时,可以释放对象

  

我应该使用(* env) - > NewGlobalRef(env,bb)将分配的缓冲区转换为全局参考吗?

除非你想在后续的JNI方法中再次使用它而不将其作为参数传递。