使用JNI从C调用Java代码时发生内存泄漏

我有一个C程序,它使用JNI在Java存储中存储一些对象。(在有人问之前,这里需要使用Java存储,而我必须用C编写一个客户端,该客户端才能从该存储中添加和检索对象)。

我制作了程序,并尝试添加100000个大小为1KB的对象。但是在仅添加50000个对象之后,我得到了“内存不足”消息(请注意,每当我无法使用NewStringUTF和NewByteArray函数分配新的字符串或字节数组时,便会打印这些“内存不足”消息)。当时我的应用程序仅使用80MB的内存。我不明白为什么这些方法都返回NULL。有什么我想念的吗?

此外,即使我释放了为Java创建的字节数组和字符串,内存也继续增加。

这是源代码。

    void create_jvm(void)

{

JavaVMInitArgs vm_args;

JavaVMOption vm_options;

vm_options.optionString = "-Djava.class.path=c:\\Store";

vm_args.version = JNI_VERSION_1_4;

vm_args.nOptions = 1;

vm_args.options = &vm_options;

vm_args.ignoreUnrecognized = 0;

JNI_CreateJavaVM(&jvm, (void**)&env, &vm_args);

if(env != null)

{

j_store = (*env)->FindClass(env, "com/store");

if(j_store == null)

{

printf("unable to find class. class name: JStore");

}

}

}

void add(char* key, char* value, int length)

{

jstring j_key = (*env)->NewStringUTF(env, key);

jbyteArray j_value = (*env)->NewByteArray(env, length);

(*env)->SetByteArrayRegion(env, j_value, 0, length, (jbyte *)value);

ret = (*env)->CallStaticBooleanMethod(env, j_store, method_id, j_key, j_value);

if(j_value != null)

{

(*env)->ReleaseByteArrayElements(env, j_value, (jbyte *)value, 0);

}

if(j_key != null)

{

(*env)->ReleaseStringUTFChars(env, j_key, key);

}

}

Java端将数据接收到byte []中并将其存储在哈希表中。问题是每次代码运行时,内存只会累加,而不会释放。我试图添加1 MB对象并对其进行调试。

当我调用NewByteArray时,进程内存增加了1MB。但是,当调用CallStaticBooleanMethod时,进程内存将增加4MB。对ReleaseByteArrayElements的调用根本不会释放任何内存。

如果在此之后添加另一个1MB对象,则在调用NewByteArray时进程内存将保持不变,而在调用CallStaticBooleanMethod时进程内存将增加1MB,但在尝试释放字节数组时将保持不变。

回答:

调用New …函数时,将创建一个“本地引用”-在本地堆栈框架中对此对象的引用。这样可以防止Java

VM在仍需要该对象时从其GC。如果您要实现某些本机方法,这很好-

它的局部框架仅在方法调用期间创建。但是,当您从与Java关联的本机线程创建对象时,该对象将绑定到该线程堆栈框架,该框架仅会被该线程破坏。

因此,当您处理完一个对象时,可以调用DeleteLocalRef()告诉您不再需要它。或者,您可以将整个add()函数用一对PushLocalFrame()/

PopLocalFrame()包围起来,以在其持续时间内创建一个单独的本地帧。

以上是 使用JNI从C调用Java代码时发生内存泄漏 的全部内容, 来源链接: utcz.com/qa/405595.html

回到顶部