JNI中jByteArray与OpenCV Mat互转引发OutOfMemoryError问题求助
JNI调用OpenCV内存泄漏问题修复
你的内存泄漏完全是因为JNI资源未正确释放和不必要的堆内存分配未回收导致的,以下是具体问题点和修复后的代码:
问题点分析
getMat函数
- 错误的
GetByteArrayElements参数:第二个参数要求是jboolean*(用于标记是否为拷贝),但你错误分配了unsigned char[width * height]的内存块,且从未释放,每次调用都会泄漏对应大小的内存。 - 未释放JNI数组元素:调用
GetByteArrayElements获取的jbae必须用ReleaseByteArrayElements释放,否则Java侧的数组内存无法正常回收,持续累积泄漏。
getJBytes函数
手动new的result_e数组在使用后未delete[],每次调用都会泄漏该数组占用的内存。
修复后的代码
修正getMat函数
cv::Mat getMat(JNIEnv* env, jint width, jint height, jbyteArray arr) { jboolean isCopy = JNI_FALSE; // 获取Java数组元素,正确传递isCopy指针 jbyte* jbae = env->GetByteArrayElements(arr, &isCopy); jsize len = env->GetArrayLength(arr); // 直接用vector构造函数批量初始化,避免循环拷贝 std::vector<unsigned char> captureVector( reinterpret_cast<unsigned char*>(jbae), reinterpret_cast<unsigned char*>(jbae) + len ); cv::Mat mat = cv::imdecode(captureVector, cv::IMREAD_COLOR); // 释放JNI数组元素:JNI_ABORT表示无需同步修改回Java(我们没修改原数组) env->ReleaseByteArrayElements(arr, jbae, JNI_ABORT); return mat; }
修正getJBytes函数
jbyteArray getJBytes(JNIEnv* env, cv::Mat mat) { std::vector<unsigned char> imageDesV; imencode(".bmp", mat, imageDesV); jbyteArray result = env->NewByteArray(imageDesV.size()); // 直接用vector的data()指针传递,省去手动new数组的步骤 env->SetByteArrayRegion( result, 0, imageDesV.size(), reinterpret_cast<jbyte*>(imageDesV.data()) ); return result; }
额外注意事项
- OpenCV的
Mat对象在不再使用时,可以调用mat.release()手动释放内存,避免其内部缓存的内存持续占用。 - 如果JNI函数中创建了大量局部引用(比如多个
jobject、jarray),可以用env->DeleteLocalRef()手动释放,防止JNI引用表溢出。
内容的提问来源于stack exchange,提问作者Alex Segura
相关产品推荐
相关产品推荐

