java - 新建时JNI中C++代码中的数组如何释放数组的缓冲区?
问题描述
我目前正在使用 Java 作为 GUI 在 C++ 中编写一个小型仿真器。为了实现这一点,我从我的 C++ 代码中进行 JNI 调用,将数据数组传递给 GUI 应用程序。但是,由于我在测试运行中进行的调用量非常大,很明显在我传递数据的函数中发生了内存泄漏。
在我的程序由于内存不足而运行并崩溃后:( 请忽略此程序当前使用的 CPU 使用率,我知道通过 JNI 重复调用效率低下,我有其他解决方法)
在对发生的事情进行彻底分析后,我得出结论,导致内存泄漏的不是 Java GUI 类,而是将数据数组传递给 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 的示例代码(例如:here),我注意到他们从不释放他们创建的数组。在挖掘JNI 文档时,我遇到了Release<NativeType>ArrayElements
我认为是我正在寻找的方法,因为描述:
ReleaseArrayElements 例程 void ReleaseArrayElements(JNIEnv *env, ArrayType 数组, NativeType *elems, jint 模式); 通知 VM 本机代码不再需要访问 elems 的一系列函数。elems 参数是使用相应的 GetArrayElements() 函数从数组派生的指针。如有必要,此函数会将对 elems 所做的所有更改复制回原始数组。mode 参数提供有关如何释放数组缓冲区的信息。如果 elems 不是数组中元素的副本,则模式无效。否则,mode 会产生如下影响,如下表所示:
真正让我希望这是我特别需要的线是
mode 参数提供有关如何释放数组缓冲区的信息
然而,经过进一步检查,我不太确定这是我最初认为的方法,并且这已经在测试中证明了自己,并且它似乎会exit()
导致失败(因为 JNI 如此臭名昭著)并且每次都会发生这种失败我使用文档中提供的任何模式运行它。
所以我真正的问题是:New<PrimitiveType>Array
在 JNI 中从 C++ 代码创建时,如何释放<PrimitiveType>Array
's 缓冲区?
解决方案
经过一番挖掘后,我发现我需要在使用 NewIntArray 创建的数组上调用 ReleaseIntArrayElements 吗?@gerbit 的简短回答:
您只需要发布参考:
jintArray pixels = env->NewIntArray(width * height); env->DeleteLocalRef(pixels)
所以很明显,当在 Java 调用 C++ 的方向上使用 JNI 时,你不需要清理你<PrimitiveType>Array
的 's,因为 java 会为你处理这个。但是从C++方向调用Java时,DeleteLocalRef()
为了防止内存泄漏,需要调用。
推荐阅读
- java - 如何让用户输入进入for循环并使程序循环直到用户输入退出
- sql - 查询一个多值列的多个值
- java - 获取矩阵的平均值
- windows - 如何使用 .bat 文件打开新的 Chrome 标签页
- excel - 使用 Find 方法取消隐藏列
- python - 加载脚本时出错:无法获取未定义或空引用的属性“版本”
- reactjs - 有没有办法在 react-responsive-carousal 中为每张幻灯片设置不同的时间间隔?
- javascript - 如何在 Web 开发中禁用 Firebase 的实时更新?
- ruby-on-rails - 从 RoR 中的同一模型获取两个索引请求的最佳方法是什么?
- r - 如何修复 R Studio 停止按空格键来完成每个单词?