JNI:从C++;,返回的对象、引用和GC 当C++程序(?)调用返回对象的java方法时,规则是什么?是否有一个突出的参考这个对象? 我必须调用“DeleteLocalRef”以确保该对象是GCd,还是将自动为GCd?我不清楚这一点的原因,是因为在所有示例和官方文档中都说明“DeleteLocalRef”是不必要的,只有当从java调用本机“C/C++”方法时,我才觉得它有意义。但是如果调用线程是C++调用java的方法,JVM会如何知道对象可以是GCD?< /P>

JNI:从C++;,返回的对象、引用和GC 当C++程序(?)调用返回对象的java方法时,规则是什么?是否有一个突出的参考这个对象? 我必须调用“DeleteLocalRef”以确保该对象是GCd,还是将自动为GCd?我不清楚这一点的原因,是因为在所有示例和官方文档中都说明“DeleteLocalRef”是不必要的,只有当从java调用本机“C/C++”方法时,我才觉得它有意义。但是如果调用线程是C++调用java的方法,JVM会如何知道对象可以是GCD?< /P>,java,c++,object,reference,java-native-interface,Java,C++,Object,Reference,Java Native Interface,同样的道理:如果我想缓存对象,我必须调用“NewGlobalRef”吗 找不到对此的任何引用 感谢您的参考和/或澄清事实上,我们对其进行了详细解释: 全球和本地参考 JNI将本机代码使用的对象引用分为两类:本地引用和全局引用。本地引用在本机方法调用期间有效,并在本机方法返回后自动释放。全局引用在显式释放之前保持有效 对象作为本地引用传递给本机方法JNI函数返回的所有Java对象都是本地引用。JNI允许程序员从本地引用创建全局引用。JNI函数期望Java对象同时接受全局引用和本地引用。本机方法可以

同样的道理:如果我想缓存对象,我必须调用“NewGlobalRef”吗

找不到对此的任何引用


感谢您的参考和/或澄清

事实上,我们对其进行了详细解释:

全球和本地参考

JNI将本机代码使用的对象引用分为两类:本地引用和全局引用。本地引用在本机方法调用期间有效,并在本机方法返回后自动释放。全局引用在显式释放之前保持有效

对象作为本地引用传递给本机方法JNI函数返回的所有Java对象都是本地引用。JNI允许程序员从本地引用创建全局引用。JNI函数期望Java对象同时接受全局引用和本地引用。本机方法可以返回对VM的本地或全局引用作为其结果

在大多数情况下,在本机方法返回后,程序员应该依靠VM释放所有本地引用。然而,有时程序员应该显式地释放本地引用。例如,考虑以下情况:< /强>

  • 本机方法访问大型Java对象,从而创建对Java对象的本地引用。然后,本机方法在返回调用方之前执行额外的计算。对大型Java对象的本地引用将防止对该对象进行垃圾收集,即使该对象在剩余的计算中不再使用

  • 本机方法创建大量本地引用,尽管并非所有本地引用都同时使用。由于VM需要一定的空间来跟踪本地引用,因此创建太多的本地引用可能会导致系统内存不足。例如,本机方法循环遍历大量对象,检索作为本地引用的元素,并在每次迭代中对一个元素进行操作。在每次迭代之后,程序员不再需要数组元素的本地引用

JNI允许程序员在本机方法中的任意点手动删除本地引用。为了确保程序员可以手动释放本地引用,JNI函数不允许创建额外的本地引用,除非它们作为结果返回引用

本地引用仅在创建它们的线程中有效。本机代码不能将本地引用从一个线程传递到另一个线程

我认为他的答案遗漏了重要的部分

同样:

实施本地参考

为了实现本地引用,javavm为从
Java本机方法的每个控制转换创建一个注册表。注册表将不可更改的本地引用映射到Java对象,并防止对象被垃圾收集。传递给本机方法的所有Java对象(包括作为JNI函数调用结果返回的对象)都会自动添加到注册表中。在本机方法返回后,注册表将被删除,从而允许对其所有条目进行垃圾收集

我将以我的应用程序为例解释我对此的解释:

我的应用程序流程的高级概述:

  • Android活动在Java中启动
  • 每帧一次,Android活动调用C++运行我们的应用程序的更新循环。
  • 在C++更新循环中,我们的C++代码使用JNI .< /LI>对java进行任意数量的调用。

    我如何解释引用的文档是自动垃圾回收可以并且只会在步骤2发生,当我们的C++更新循环返回到最初调用它的java代码时。


    < C++ > C++ C++,如果你的应用程序在C++中开始执行,然后调用java,我认为你不会有自动的本地引用垃圾收集,除非你再从java调用C++(调用堆栈:代码> C++ +>java> C++ >代码>),在这种情况下,在你返回到Java时,你在最上面的C++函数中所做的任何引用都将被GC。(C++ C++ C++代码> > C++ >代码> C++ > <代码> C++ > > java >。(这是一个C++程序调用一个返回对象的C++方法……在C++调用java的情况下,没有…………在原生方法返回之后……那么,你说你的C++程序是主机还是创建JVM?在这种情况下,我非常肯定你应该调用<代码> DeleTelaCalrf < /C>(如果合适的话)因为你必须自己控制生命周期。这是否意味着在JNI返回之前,传递到JNI中的所有对象都是不可移动的?我可以绕过JNI直接从内存中读取,而不让对象从一条指令移动到另一条指令吗?@JohnnyV我不太清楚,但文档中确实说
    A registry maps nonmo对java对象< /C> >的本地引用。这样,至少在引用之前,将有引用被保证不被移动,直到“<代码>注册表< /C> >被删除(在<代码>转换为“C++”/代码>从C++返回到java)。