首页 > 解决方案 > JNI - SIGSEGV 信号 SIGSEGV:在工作线程中时地址无效

问题描述

我有一个来自 android 的 JNI 调用,我在其中发送数据(字节、宽度和高度)以进行图像处理。从主 android 线程执行时,该函数工作正常。我想从另一个线程调用,以避免阻塞 UI,但是当我这样做时,JNI 会引发内存错误。如果我从主线程调用,工作正常。

该错误是从env->GetIntArrayRegion(...)引发的。

extern "C"
JNIEXPORT jobjectArray JNICALL
Java_topcodes_TopCodesScanner_searchTopCodesNative(JNIEnv *env, jobject thiz, jint image_width,
                                                   jint image_height, jintArray image_data) {
    auto image_data_size = env->GetArrayLength(image_data);
    jint image_data_buf[image_data_size];
    // error in this line
    env->GetIntArrayRegion(image_data, 0, image_data_size, image_data_buf);

我创建新线程的方式是这样的:

private val executorService by lazy { Executors.newFixedThreadPool(4) }

    override fun analyze(image: ImageProxy) {
        
        executorService.submit {  // if comment, works fine
            try {
                val blocks = findBlocks(image)
                handler.post { listener(blocks); }
            } finally {
                image.close()
            }
        }                         // if comment, works fine
    }

这是堆栈跟踪。

memcpy 0x0000007f8f938d9c
art::JNI::*GetIntArrayRegion(_JNIEnv, _jintArray*, int, int, int*) 0x0000007f8bddcea0
art::CheckJNI::GetPrimitiveArrayRegion(char const*, art::Primitive::Type, _JNIEnv*, _jarray*, int, int, void*) 0x0000007f8bbf07fc
<unknown> 0x0000007f750c0aec
<unknown> 0x0000007f750c0708
topcodes.TopCode[] topcodes.TopCodesScanner.searchTopCodesNative(int, int, int[]) 0x0000007f7844218c
art_quick_invoke_stub 0x0000007f8bbb6ca8
art::ArtMethod::Invoke(art::Thread*, unsigned int*, unsigned int, art::JValue*, char const*) 0x0000007f8bbc5b80
artInterpreterToCompiledCodeBridge 0x0000007f8bf64574
bool art::interpreter::DoCall<false, false>(art::ArtMethod*, art::Thread*, art::ShadowFrame&, art::Instruction const*, unsigned short, art::JValue*) 0x0000007f8bd3fc48
art::JValue art::interpreter::ExecuteGotoImpl<false, false>(art::Thread*, art::DexFile::CodeItem const*, art::ShadowFrame&, art::JValue) 0x0000007f8bb76e44
art::interpreter::EnterInterpreterFromEntryPoint(art::Thread*, art::DexFile::CodeItem const*, art::ShadowFrame*) 0x0000007f8bd1d9c4
artQuickToInterpreterBridge 0x0000007f8bfd4944
art_quick_to_interpreter_bridge 0x0000007f8bbc0a28
<unknown> 0x0000007f8bbc0b90

我搜索过类似的问题。提前致谢。

标签: androidc++multithreadingjava-native-interface

解决方案


auto image_data_size = env->GetArrayLength(image_data);
jint image_data_buf[image_data_size];

如果您在编译时不知道大小,请不要创建 C 样式的数组。
请参阅:为什么 C++ 允许非动态分配的可变长度数组?

改为使用std::vector<jint> image_data_buf(image_data_size)


推荐阅读