JNI可以发布Java层对象吗?

时间:2017-03-23 23:53:44

标签: java-native-interface

我通过调用返回jobject值的本机代码来创建Java对象。

Java代码:

Object myObj = nativeCreateObject();

原生代码:

jobject* hold_ref;
JNIEXPORT jobject JNICALL
nativeCreateObject(JNIEnv *env ...) {
    .....
    result = env->NewGlobalRef(jobj);
    hold_ref = &result;
    return result;
}

我的问题是:我是否可以稍后使用hold_ref在本机层中通过引用释放myObj? 例如 本机代码:

*hold_ref = NULL;

然后Java层中的myObj为空? 如果没有,我怎么能用本机代码发布这个对象?

1 个答案:

答案 0 :(得分:2)

我不确定,你想要实现什么,但这是基本的工作方式:

  

我是否可以稍后使用hold_ref在本机层中通过引用释放myObj?

是的,您可以而且应该使用env->DeleteGlobalRef(myObj)释放您创建的全局引用,以便垃圾收集器可以清理并最终销毁该对象。

  

然后Java层中的myObj为空?如果没有,我怎么能用本机代码发布这个对象?

当您从jni本机代码中删除引用时,您的Java变量无法转为null magicaly。 Java本身拥有一个引用来防止垃圾收集对象被删除。

您可能希望以这种方式使用它:

C ++

jobject* hold_ref;

JNIEXPORT jobject JNICALL nativeCreateObject(JNIEnv *env ...) {
   .....
   result = env->NewGlobalRef(jobj);
   hold_ref = &result;
   return result;
}

JNIEXPORT void JNICALL nativeDestroyObject(JNIEnv *env ...) {
   .....
   env->DeleteGlobalRef(jobj);
   hold_ref = nullptr;
}

JAVA

// Creates two references (native and local variable)
Object myObj = nativeCreateObject();

// Deletes the native reference, but not the local one
nativeDeleteObject(myObj);
// myObj != null

myObj = null;
// now there is no reference to your created object
// the garbage collector may destroy it any time

如果你想在某种程度上使你的对象无效,我建议管理状态并抛出一个异常,如果对象被无效这样:

class MyInvalidateableObject {

    private boolean invalidated = false;

    public void invalidate() {
        this.invalidated = true;
    }

    public void foo() {
        if (invalidated) 
            throw new IllegalStateException("Object has been invalidated");
        ... // do the normal stuff
    }
}

只需使用本机代码调用对象上的invalidate()即可防止再次使用它。