首页 > 解决方案 > 当我构建一个线程来调用 JNI C++ 函数时,程序崩溃了

问题描述

我想在子线程中使用这三个函数,但是程序崩溃了。

这是树 C++ 函数:

//here are three JNI interface 
public native byte[] readImage(String str);
public native byte[] FPGAEnhancement(String str, int flag);
public native byte[] FPGASobel(String str, int flag);

这三个函数可以在android程序中正确使用,但是当我建立一个子线程并使用这三个函数时,程序崩溃了。

经测试,似乎这条线崩溃了,结果无法返回。

env->SetByteArrayRegion(jarrRV, 0, length, data);

这是 readImage 函数:

Java_wearablepc_ftcl_hit_edu_cn_fpga_MainActivity_readImage(
    JNIEnv *env, jobject, jstring jstr) {
FILE *fp;
fp = fopen(jstringTostring(env, jstr), "rb");
if (fp != NULL) {
    int length = getFileLength(fp);
    Log_i("fp length");
    if(length<=0) {
        jbyteArray jarrRV = env->NewByteArray(1);
        return jarrRV;
    } else {
        jbyteArray jarrRV = env->NewByteArray(length);
        jbyte data[length];
        readImage(fp, data, length);
        fclose(fp);
        env->SetByteArrayRegion(jarrRV, 0, length, data);
        return jarrRV;
    }
} else {
    jbyteArray jarrRV = env->NewByteArray(1);
    return jarrRV;
}

我想我在子线程中调用 C++ 函数的方式可能有问题,但我不知道它到底是什么。谢谢!!

标签: javaandroidc++java-native-interface

解决方案


当图像文件很大时,在堆栈上分配data[length]可能会耗尽堆栈,并且案例崩溃。你实际上根本不需要这个数组,你可以安全地直接访问新创建的jarrRV的字节:

    jbyteArray jarrRV = env->NewByteArray(length);
    jboolean isCopy;
    jbyte data = env->GetByteArrayElements(env, jarrRV, &isCopy);
    readImage(fp, data, length);
    fclose(fp);
    env->ReleaseByteArrayElements(jarrRV, data, 0);

对您的 C++ 代码的其他一些评论:

  • 似乎在某些情况下,文件不会被关闭。
  • 在所有情况下,jstringTostring()都可能泄漏本机和 Java 对象。请不要低估这种泄漏在多线程环境中的影响。

推荐阅读