java - 垃圾收集和 JNI 调用

标签 java garbage-collection java-native-interface

我遇到 JNI 程序内存随机耗尽的问题。

这是一个 32 位 java 程序,它读取一个文件,进行一些图像处理,通常使用 250MB 到 1GB。然后丢弃所有这些对象,然后程序对通常需要 100-250MB 的 JNI 程序进行一系列调用。

交互式运行时,我从未见过问题。但是,当连续对许多文件运行批处理操作时,JNI 程序将随机耗尽内存。可能有一个或两个文件出现内存问题,然后接下来的10个文件运行正常,然后再次出现故障。

我在 JNI 调用之前转储了可用内存量,它遍布整个 map ,有时是 100MB,有时是 800MB。我的解释是,Java 垃圾回收有时会在图像处理后立即运行,有时则不会。如果不是,则可能没有足够的内存用于 JNI 程序。

我已经阅读了所有关于 GC 是非确定性的、不应该调用它、不会产生任何影响等的所有内容,但在开始 JNI 调用之前强制执行 GC 似乎肯定会改善这种情况。

但是有没有办法真正保证在继续之前有一定数量的空闲内存呢?

要回答有关 JNI 程序的问题,该程序由另一家公司提供,我对它如何分配内存一无所知。我所知道的是它是在 c++ 中,没有垃圾收集。我被告知它需要 100-250MB 的内存,我看到的数字可以证实这一点。

也许我应该将问题改写为:如果我要进行一个我知道需要 250MB 内存的 JNI 调用,我如何才能确保它有那么多可用内存?

当然,一种可能的解决方案是进行 64 位构建。但是,此批处理操作是 32 位版本 QA 的一部分,因此我想测试真实的东西。

最佳答案

我自己解决这个问题的方法是简单地调用 System.gc(),但是从 inside 本地代码:

#include <jni.h>
// ...
int my_native_function(JNIEnv* env, jobject obj) {
    jclass    systemClass    = nullptr;
    jmethodID systemGCMethod = nullptr;
    // ...
    // Take out the trash.
    systemClass    = env->FindClass("java/lang/System");
    systemGCMethod = env->GetStaticMethodID(systemClass, "gc", "()V");
    env->CallStaticVoidMethod(systemClass, systemGCMethod);
}

我希望这对你也有用。

关于java - 垃圾收集和 JNI 调用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38681108/

相关文章:

java - 在永久堆空间中处理许多符合 GC 条件的大型对象

java - 为什么jdk中没有ConcurrentLinkedHashMap类?

java - Android相机通过OpenGL编码

java - 如何知道用户何时关闭 Java 中使用 exec() 执行的程序

java - 小心 : Splitting a string by newlines can cause bothering bugs

python - 覆盖对象实例不释放内存?

garbage-collection - 无法识别的选项 : -XLoggc:

java - 我可以从 cpp 程序调用带有数据库调用的 Java 程序吗

java - 如何使用 JNI 将图像作为结构参数传递给 libfprint 的 C 函数

android - Dalvik 正在寻找扩展名为 '.0' 的 .so 文件 - 为什么?