我遇到 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/