You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

JNI中jByteArray与OpenCV Mat互转引发OutOfMemoryError问题求助

JNI调用OpenCV内存泄漏问题修复

你的内存泄漏完全是因为JNI资源未正确释放和不必要的堆内存分配未回收导致的,以下是具体问题点和修复后的代码:

问题点分析

getMat函数

  1. 错误的GetByteArrayElements参数:第二个参数要求是jboolean*(用于标记是否为拷贝),但你错误分配了unsigned char[width * height]的内存块,且从未释放,每次调用都会泄漏对应大小的内存。
  2. 未释放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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.03 14:01:15