当前位置: 首页 > 面试题库 >

使用调用API的JNI内存管理

赏弘
2023-03-14
问题内容

当我使用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,该怎么办?理想情况下,我想将垃圾收集留给VM;完成后,instance如果它还调用c_object_destroy()我提供给它的指针,那就太棒了。这可能吗?

一个单独但相关的问题与我在这种方法中创建的Java实体的范围有关。我必须手动释放,也就是说,classconstructor,或method以上?根据我的判断,JNI文档在适当的内存管理方面令人沮丧地含糊。


问题答案:

有两种回收本地资源(对象,文件描述符等)的策略。

  1. 在finalize()期间调用JNI方法,以释放资源。有人建议不要实施finalize,基本上,您不能真正确定是否释放了本地资源。对于诸如内存之类的资源,这可能不是问题,但是例如,如果您有一个文件需要在可预测的时间刷新,则finalize()可能不是一个好主意。

  2. 手动调用清除方法。如果您有一个时间点知道必须清除资源,这将很有用。当我拥有必须在JNI代码中卸载DLL之前必须重新分配的资源时,便使用了此方法。为了允许以后重新加载DLL,在尝试卸载DLL之前,我必须确保已真正释放对象。仅使用finalize(),就不会保证这一点。可以将其与(1)结合使用,以允许在finalize()期间或在手动调用的清理方法中分配资源。(您可能需要一个WeakReferences的规范映射来跟踪哪些对象需要调用其清理方法。)

  3. 推测 PhantomReference 也可以用来解决此问题,但是我不确定这种解决方案将如何工作。

实际上,我在JNI文档上与您意见不一致。我发现JNI规范在大多数重要问题上都格外清晰,即使有关管理本地和全局引用的部分可以做得更加详细。



 类似资料:
  • 问题内容: 我有两个问题: 如果我有对方法的JNI调用而JNI方法泄漏内存该怎么办。此方法完成后,JVM垃圾收集器将能够取回该内存。我听说JVM不管理JNI使用的堆空间吗?但是JNI使用的内存是Java进程使用的内存的一部分吗? 使用JNI来实现IPC是否绝对必要?还有哪些其他流行的Java技术?或者是否有一个开放源代码库来实现Java共享内存? 问题答案: 否:“ JNI框架不为在本机端执行的代

  • 我有一个Java应用程序,它合并了一些大文件。Java应用程序不在我的控制之下。Java应用程序的结果以大约90MB的大字符串返回给我的C程序,我在其中的一些算法中使用它。我多次调用execute方法。我的问题是,每次调用Java应用程序时,它都会保留更多内存,但不会释放内存。从这个垃圾收集和JNI调用问题中,我想到手动调用垃圾收集器,但它不会释放内存。有没有办法解决这个问题? 这是我的C程序

  • 问题内容: 我有一个JNI回调: 当我像这样(空有用的代码)运行它时,会发生内存泄漏。如果我注释掉整个方法,则不会泄漏。连接/分离线程的正确方法是什么? 我的应用程序处理实时声音数据,因此负责数据处理的线程必须尽快完成,以便为下一批做好准备。因此,对于这些回调,我创建了新线程。每秒有数十个甚至数百个它们,它们将自己附加到JVM,调用一个回调函数来重绘图形,分离并消亡。这是做这些事情的正确方法吗?如

  • 问题内容: 我有以下JNI方法,它可以本地创建Java对象的集合,然后将其返回给Java: 我需要释放用本机代码创建的对象,还是由GC自动完成?如果可以,我该如何将其返回Java? 问题答案: 您不需要释放在本机代码中创建的Java对象。实际上,您不能。当没有其他引用时,垃圾收集器可以释放对象。 有时在本机代码中释放对Java对象的 引用 很有用。当本机代码保存但不再需要对大型对象的引用或大量引用

  • 问题内容: 我有一个C程序,它使用JNI在Java存储中存储一些对象。(在有人问之前,这里需要使用Java存储,而我必须用C编写一个客户端,该客户端才能从该存储中添加和检索对象)。 我制作了程序,并尝试添加100000个大小为1KB的对象。但是在仅添加50000个对象之后,我得到了“内存不足”消息(请注意,每当我无法使用NewStringUTF和NewByteArray函数分配新的字符串或字节数组

  • 我有一个Android应用程序,需要使用库。我正在使用与它进行接口。该库使用一个结构(我们称之为)。使用一组初始参数,其中包括指向函数的指针,它使用这些函数从我的应用程序请求更多数据,并将这些数据合并到计算过程中。一旦它拥有了所需的一切,它就会通过回调函数返回一个结果,它还需要一个指针。我需要将所有的回调函数挂接到我的应用程序中,从用户那里获取更多的数据,然后将这些数据返回到中,最后通过最终的回调