在JNI中从C ++代码创建New< PrimitiveType> Array时,如何释放< PrimitiveType> Array的缓冲区? [英] When creating New<PrimitiveType>Array from C++ code in JNI how to release the <PrimitiveType>Array's buffer?

查看:101
本文介绍了在JNI中从C ++代码创建New< PrimitiveType> Array时,如何释放< PrimitiveType> Array的缓冲区?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我目前正在使用Java作为GUI在C ++中编写一个小型仿真器.为了实现这一点,我正在通过C ++代码进行JNI调用,将数据数组传递给GUI应用程序.但是,由于我在测试运行中进行的调用数量很少,因此很明显,在我传递数据的函数中发生了内存泄漏.

I am currently writing a small emulator in C++ using Java as a GUI. In order to achieve this I am making JNI calls from my C++ code passing arrays of data to the GUI application. However due to the shear amount of calls I made in a test run, it has become clear that in my function to pass data a memory leak is occurring.

在我的程序运行之前:

Before my program has run:

我的程序由于内存不足而运行并崩溃后: (请忽略该程序当前使用的CPU使用率,我知道通过JNI重复调用效率低下,对此我还有其他解决方法)

After my program has run and crashed due to lack of memory: (Please ignore the CPU usage this program currently uses, I am aware that repeated calls through JNI is inefficient and I have other workarounds to this)

在对发生的情况进行了全面分析之后,我得出结论,不是导致内存泄漏的Java GUI类,而是将数据数组传递给Java GUI的函数中的代码:

After thorough analysis of whats going on I have concluded that it is not the Java GUI class causing the memory leak but rather the code in the function that passes the data array to the Java GUI:


//java.env is the JNIEnv*
//setDisplay_ is a valid non-null jmethodID at runtime
//displayObject is a valid non-null jobject at runtime

void Display::setDisplay(vector<uint32_t>& a)
{
    jint* buffer = new jint[a.size()];
    for(int i = 0; i < a.size(); i++)
        buffer[i] = (jint)a[i];
    jintArray par = java.env->NewIntArray(a.size());
    java.env->SetIntArrayRegion(par, 0, a.size(), buffer);
    java.env->CallVoidMethod(displayObject, setDisplay_, par);
    //java.env->ReleaseIntArrayElements(par, buffer, 0);
    delete buffer;
}

我唯一能看到此函数导致内存泄漏的原因是jintArray,我绝对不知道它超出范围时会发生什么,所以我只能认为是释放缓冲区时出现的问题.但是,请看其他人使用带有数组的JNI的示例代码(例如: JNI文档我遇到了Release<NativeType>ArrayElements方法,由于该描述,我认为这正是我要寻找的方法:

The only thing I can see this function causing a memory leak over is the jintArray which I have absolutely no idea what happens to when it goes out of scope so I can only assume is the issue as I release the buffer. However looking at sample code from other people using the JNI with arrays (ex: here) I notice that they never release the Array that they create. While digging through the JNI Documentation I came across the Release<NativeType>ArrayElements Method which I assumed was what I was looking for due to the description:

ReleaseArrayElements例程 void ReleaseArrayElements(JNIEnv * env, ArrayType array,NativeType * elems,jint模式); 通知VM本地代码不再需要访问elems的一系列功能. elems参数是使用相应的GetArrayElements()函数从数组派生的指针.如有必要,此函数将对elems所做的所有更改复制回原始阵列. mode参数提供有关应如何释放数组缓冲区的信息.如果elems不是数组中元素的副本,则mode无效.否则,模式会产生以下影响,如下表所示:

ReleaseArrayElements Routines void ReleaseArrayElements(JNIEnv *env, ArrayType array, NativeType *elems, jint mode); A family of functions that informs the VM that the native code no longer needs access to elems. The elems argument is a pointer derived from array using the corresponding GetArrayElements() function. If necessary, this function copies back all changes made to elems to the original array. The mode argument provides information on how the array buffer should be released. mode has no effect if elems is not a copy of the elements in array. Otherwise, mode has the following impact, as shown in the following table:

真正让我希望这是我特别需要的那一行

The line that really gave me hope this was what i needed in particular was

mode参数提供有关如何释放数组缓冲区的信息

但是,在进一步检查时,我不太确定这是我原本认为的方法,并且这已经在测试中证明了自己,并且似乎在失败时会调用exit()(因为JNI臭名昭著)并且每次我使用文档中提供的任何模式运行它时,都会发生此故障.

However upon further inspection, im not quite sure this is the method i orrignally thought it was, and this has proved itself in testing as well as it appears to call exit() upon a failure (as JNI is so notorious for) and this failure occurs every time I run it with any of the Modes provided in the documentation.

所以我的真正问题是: 从JNI中的C ++代码创建New<PrimitiveType>Array时,如何释放<PrimitiveType>Array的缓冲区?

So my Real Questions is: When creating New<PrimitiveType>Array from C++ code in JNI how do I release the <PrimitiveType>Array's buffer?

推荐答案

经过进一步的挖掘,我发现

After a bit more digging I came upon Do I need to call ReleaseIntArrayElements on an array created with NewIntArray? with a short answer from @gerbit :

您只需要发布参考:

You have to release only reference:

jintArray pixels = env->NewIntArray(width * height);
env->DeleteLocalRef(pixels)

因此,显然,在Java调用C ++的方向上使用JNI时,您不需要清理<PrimitiveType>Array,因为Java会为您处理.但是,从C ++方向调用Java时,您需要调用DeleteLocalRef()以防止内存泄漏.

So apparently when using the JNI in the direction of Java calling C++, you dont need to clean up your <PrimitiveType>Array's as java handles this for you. However when calling from the direction of C++ to Java, You need to call DeleteLocalRef() in order to prevent memory leaks.

这篇关于在JNI中从C ++代码创建New&lt; PrimitiveType&gt; Array时,如何释放&lt; PrimitiveType&gt; Array的缓冲区?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆