2016-12-06 54 views
1

是JCLASS和jobject参考delete一个这样正确的方式JNI deleteRef为JCLASS和jobject

JNIEXPORT void JNICALL Java_method(JNIEnv *env,jobject, jobject objArray) 
{ 
    int n = env->GetArrayLength(objArray); 

    for (int i = 0; i<n ; ++i) 
    { 
     jobject sObject = env->GetObjectArrayElement(objArray, i); 
     jclass sObjectClass = env->GetObjectClass(sObject); 

     dosomething(sObjectClass, sObject); 

     env->DeleteLocalRef(sObject); 
     env->DeleteLocalRef(sObjectClass); 
    } 
+0

是的,对于本地引用,这是正确的。它应该防止参考表溢出。 – mkaes

+0

为什么你需要在循环里面虽然'GetObjectClass'?你期望数组中的元素具有不同的类型吗? – Michael

回答

1

简短的回答:

是的,这是一个正确的做法。呼叫DeleteLocalRef不是必需的,但是如果objArray很大或者如果函数执行时间很长,则它非常有用。

较长的答案:

的Oracle参考文档指出

基本类型,例如整数,字符等,复制Java和本机代码之间 。任意Java对象,在另一手 手,通过引用传递。 VM必须跟踪已传递给本机代码的所有对象 ,以便这些对象不会被垃圾收集器释放。本地代码反过来必须 有办法通知VM不再需要该对象。在 另外,垃圾收集器必须能够移动由本地代码引用的对象 。

因此,当本机代码确实需要该对象时,本机代码使用的任何对象都必须标记为符合从本机代码角度进行垃圾回收的条件。 JNI有两种类型的引用 - 全局和本地引用。

所有Java对象通过JNI函数返回的是本地引用:因为GetObjectArrayElementGetObjectClass检索到的文献是本地的。

VM自动释放所有局部引用,当一个本地函数返回。所以在大多数情况下,没有必要通过DeleteLocalRef释放这些引用,因为VM会自动释放它们。

但是如果有一个函数调用需要大量的本地引用或通话时间长那么就值得明确立即释放他们并不需要它们时,不等待函数返回。释放有助于虚拟机进行更好的内存管理。