c++ - JNI - 返回在 native 函数中创建并由另一个 native 函数使用的 jobject

标签 c++ java-native-interface

我想知道使用在 native 方法中创建并由该方法返回给调用者的本地引用有多安全。

这是一个简单的例子:

jobject getAJObject(JNIEnv* jni) {
    jobject obj = jni->CallStaticVoidMethod(...); // java method that returns a jobject
    return obj;
}

void func(JNIEnv* jni) {
    jobject obj = getAJObject(jni);
    // Code that uses obj
    ...
}

我已经测试了这段代码,它确实可以正常工作,但我担心它不安全。我从阅读 JNI 规范中了解到,本地引用仅在其创建的堆栈帧中有效,并在 native 方法返回时被清除。这是否意味着 obj 可以在 getAJObject 完成后进行垃圾回收,同时仍在 native 端而不返回 java?

这篇文章表明这​​段代码不安全: http://publib.boulder.ibm.com/infocenter/javasdk/v1r4m2/index.jsp?topic=%2Fcom.ibm.java.doc.diagnostics.142j9%2Fhtml%2Fhandlocref.html

但是我仍然看到 JNI 代码的示例正是这样做的!希望得到更多的澄清。

最佳答案

您可以安全地使用 func() 中的 getAJObject()。当 JNI 调用正在进行时, native 对象 obj 的所有垃圾收集和本地引用管理都被卡住。让我来解决两种不同的情况:

  1. 如果您的代码从 Java 线程调用 func()(即,如果可以在调用堆栈中找到 JVM),如果有一个 native Java通过一些调用链调用 func() 的方法,然后这个本地方法定义了 JNI 本地引用框架的范围。

  2. 或者,您的代码从 native 线程 调用func(),这需要调用jint AttachCurrentThread(JavaVM *vm, void **penv, void *args)jint AttachCurrentThreadAsDaemon(JavaVM *vm, void **penv, void *args)获取 JNIEnv* jni。在这种情况下,局部引用等的范围一直保留到该线程调用 jint DetachCurrentThread(JavaVM *vm) 为止。 .

请注意,在情况 2 中,如果线程在未调用 DetachCurrentThread() 的情况下终止,您的 JVM 将崩溃。

您还可以使用 jint PushLocalFrame(JNIEnv *env, jint capacity) 手动管理本地引用范围和 jobject PopLocalFrame(JNIEnv *env, jobject result) .

关于c++ - JNI - 返回在 native 函数中创建并由另一个 native 函数使用的 jobject,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22275035/

相关文章:

C++ 将函数指针插入内存

c++ - C++ 模板的编译器错误表明这不是结构体的成员

c++ - 推导指南和带有可变模板构造函数的可变类模板 - 不匹配的参数包长度

c++ - 如何移动 ArrayFire 3D 阵列

java - JNI native 函数内的自定义内存分配

java - 在理解生成的 JNI 头文件方面需要帮助

android - 无法为 Android 构建 Mupdf(ExceptionInitializerError)

c++ - C++ 中的 SQLite。数据库正忙(多线程)

Java JNI : Specify path to dependent shared library

android - "fatal error: Eigen/Dense: No such file or directory"//特征库