【发布时间】:2019-11-29 13:36:53
【问题描述】:
我创建了一个 DLL,其中包含一个从 C# 代码调用的 JNI 函数。该函数被 C# 应用程序多次调用,该应用程序是一个长期运行的 GUI 应用程序。
我的 JNI 函数调用 JNI_GetCreatedJavaVMs。如果虚拟机为零,则通过函数JNI_CreateJavaVM() 创建一个,否则我的函数调用AttachCurrentThread()。
然后我的函数调用 FindClass() 并从 JAR 文件加载一个类。
最后我在那个类上调用了一个方法。
在被调用方法的java代码中,我首先调用方法totalMemory(),并将结果写入日志文件。然后该方法执行一些其他操作。
通常方法 totalMemory() 返回大约 6600 万的值,即大约 64 MB,但有时它返回大约 200 万,即 2 MB。当 totalMemory() 只有 2 MB 时,我的 java 方法会抛出 OutOfMemoryError(java 堆空间),因为没有足够的内存来分配我的 java 方法需要做的对象。
请注意,我的 java 方法包含 catch (Throwable) 以便 C# 应用程序可以继续。在 OutOfMemoryError 之后,对于后续调用我的 JNI 函数,totalMemory() 将再次返回 64 MB 的值。
什么会导致分配给 JVM 的总内存从 64 MB 下降到 2 MB?
请注意,我指的是总内存,而不是可用内存。我假设总内存不应该改变。我相信我的日志文件证明了我的假设,因为正如我在上面所写的,它几乎总是 64 MB。它有时只是下降到 2 MB,因此这个问题。为什么总内存有时会降至 2 MB?
我的(精简的)JNI 代码。
#include <jni.h>
void main()
{
JavaVM *jvm;
JNIEnv *env;
JavaVMInitArgs vm_args;
jint rslt;
jclass cls;
jmethodID mid;
jobject jObj;
JavaVMOption* options = new JavaVMOption[1];
options[0].optionString = "-Djava.class.path=jni_test.jar";
vm_args.version = JNI_VERSION_1_10;
vm_args.nOptions = 1;
vm_args.options = options;
vm_args.ignoreUnrecognized = false;
rslt = JNI_CreateJavaVM(&jvm, (void**) &env, &vm_args);
cls = env->FindClass("jni_test/JniTest0");
mid = env->GetStaticMethodID(cls, "getReply", "()Ljava/lang/String;");
jObj = env->CallStaticObjectMethod(cls, mid);
}
在上述 JNI 代码中调用的我的(精简的)java 方法。
public static String getReply() {
long totalMemory = Runtime.getRuntime().totalMemory();
System.out.println("total memory = " + totalMemory);
String reply = "That is the correct answer! Well done!";
return reply;
}
【问题讨论】:
-
查看answer。您可能将总内存与最大内存混淆了。
标签: java java-native-interface