gpt4 book ai didi

java - 使用调用 API 的 JNI 内存管理

转载 作者:塔克拉玛干 更新时间:2023-11-03 04:46:39 25 4
gpt4 key购买 nike

当我使用 JNI 方法构建一个 java 对象时,为了将它作为参数传递给我使用 JNI 调用 API 调用的 java 方法,我该如何管理它的内存?

这是我正在使用的:

我有一个 C 对象,它有一个比 free() 更复杂的析构函数方法。此 C 对象将与 Java 对象相关联,一旦应用程序完成了 Java 对象,我就不再需要 C 对象了。

我正在像这样创建 Java 对象(为清楚起见省略了错误检查):

c_object = c_object_create ();
class = (*env)->FindClass (env, "my.class.name");
constructor = (*env)->GetMethodID (env, class, "<init>", "(J)V");
instance = (*env)->NewObject (env, class, constructor, (jlong) c_object);

method = (*env)->GetMethodID (env, other_class, "doSomeWork", "(Lmy.class.name)V");
(*env)->CallVoidMethod (env, other_class, method, instance);

那么,既然我已经完成了 instance,我该如何处理它呢?理想情况下,我希望将垃圾收集留给虚拟机;当它使用 instance 完成时,如果它还调用了我提供给它的指针上的 c_object_destroy() 那就太棒了。这可能吗?

一个单独但相关的问题与我在这样的方法中创建的 Java 实体的范围有关;我必须手动释放上面的 classconstructormethod 吗? JNI 文档在适当的内存管理方面含糊不清(根据我的判断)。

最佳答案

JNI 规范涵盖了谁“拥有”在 JNI 方法中创建的 Java 对象的问题 here .您需要区分本地全局 引用。

当 JVM 对 native 代码进行 JNI 调用时,它会设置一个注册表来跟踪调用期间创建的所有对象。在 native 调用期间创建的任何对象(即从 JNI 接口(interface)函数返回)都将添加到此注册表中。对此类对象的引用称为本地引用。当本地方法返回到 JVM 时,在本地方法调用期间创建的所有本地引用都将被销毁。如果您在 native 方法调用期间调用回 JVM,则当控制权返回 native 方法时,本地引用仍然有效。如果从 native 代码调用的 JVM 再次调用 native 代码,则会创建一个新的本地引用注册表,并应用相同的规则。

(事实上,您可以使用 JNI 接口(interface)实现您自己的 JVM 可执行文件(即 java.exe),方法是创建一个 JVM(从而接收一个 JNIEnv * 指针),在命令行中查找给定的类,并在其上调用 main() 方法。)

从 JNI 接口(interface)方法返回的所有引用都是本地的。这意味着在正常情况下您不需要手动释放 JNI 方法返回的引用,因为它们在返回到 JVM 时会被销毁。有时您仍然希望“过早地”销毁它们,例如当您想要在返回 JVM 之前删除大量本地引用时。

全局引用是通过使用 NewGlobalRef() 创建的(从本地引用)。它们被添加到一个特殊的注册表中,必须手动释放。全局引用仅用于 native 代码需要跨多个 JNI 调用保存对 Java 对象的引用,例如,如果您有 native 代码触发事件,这些事件应该传播回 Java。在这种情况下,JNI 代码需要存储对接收事件的 Java 对象的引用。

希望这能稍微澄清内存管理问题。

关于java - 使用调用 API 的 JNI 内存管理,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/214699/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com