Java JVM总内存通常为64MB,但有时仅为2MB

Java JVM总内存通常为64MB,但有时仅为2MB,java,java-native-interface,Java,Java Native Interface,我创建了一个DLL,其中包含一个从C#代码调用的JNI函数。该函数被C#应用程序多次调用,C#应用程序是一个长期运行的GUI应用程序 我的JNI函数调用。如果有零个VM,则通过函数创建一个VM,否则我的函数调用 然后,我的函数从JAR文件调用并加载一个类 最后,我对该类调用了一个方法 在被调用方法的java代码中,我首先调用方法并将结果写入日志文件。然后,该方法执行一些其他操作 通常方法totalMemory()返回的值约为6600万,即约64 MB,但有时返回的值约为200万,即2 MB。当t

我创建了一个DLL,其中包含一个从C#代码调用的JNI函数。该函数被C#应用程序多次调用,C#应用程序是一个长期运行的GUI应用程序

我的JNI函数调用。如果有零个VM,则通过函数创建一个VM,否则我的函数调用

然后,我的函数从JAR文件调用并加载一个类

最后,我对该类调用了一个方法

在被调用方法的java代码中,我首先调用方法并将结果写入日志文件。然后,该方法执行一些其他操作

通常方法
totalMemory()
返回的值约为6600万,即约64 MB,但有时返回的值约为200万,即2 MB。当
totalMemory()
只有2MB时,我的java方法抛出(java堆空间),因为没有足够的内存来分配我的java方法需要执行的对象

请注意,我的java方法包含
catch(Throwable)
,以便C#应用程序可以继续。在发生
OutOfMemoryError
之后,对于对我的JNI函数的后续调用,
totalMemory()
将再次返回64 MB的值

是什么导致分配给JVM的总内存从64MB下降到2MB

请注意,我指的是总内存,而不是可用内存。我假设总内存不应该改变。我相信我的日志文件证明了我的假设,因为正如我在上面所写的,它几乎总是64MB。它只是有时候会下降到2MB,所以这个问题就出现了。为什么总内存有时会下降到2MB

我的(精简的)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);
}

据我所知,JVM内存模型:

maxMemory
是JVM可以使用的最大数量(由-Xmx定义)

maxMemory
=
totalMemory
+未分配内存

totalMemory
-
freemory
=
已使用

虽然JVM将内存释放回操作系统是很少见的, 这是可能的,它会解释你正在经历什么

totalMemory
不应低于
-Xms
定义的值, 因此,使用固定内存值运行jvm可能会解决您的问题。
例如:
-Xms64m-Xmx64m

我的怀疑似乎被证明是正确的。有时错误消息可能会产生误导。我从一开始就有一种直觉,那就是这个问题不是真正的记忆问题,就像我说的,看起来我是对的

我的代码使用java日志在Windows临时文件夹中写入日志文件。事实证明,另一个不相关的进程也会将日志文件写入同一文件夹。事实上,它会将数千个文件写入该文件夹,而这些文件永远不会被删除。一旦我们删除了那些文件,问题就消失了

所以问题是,临时文件夹已经满了文件,没有一个是由我的代码编写的。检查是否有人遇到类似问题,并由于互联网搜索而出现此问题。

检查此项。您可能混淆了总内存和最大内存。