我试图在单独的线程中从Java调用以下函数:

extern "C" JNIEXPORT jdoubleArray

JNICALL
Java_de_bastian_sip2labor_MainActivity_filtertest(JNIEnv *env, jobject, jdoubleArray ka)
{
  double b_y1[121];
  int k;
  int j;
  static const double dv0[12] = { 1.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0,
0.0, 0.0, 0.65 };

  jdouble *sig1;
  sig1=env->GetDoubleArrayElements(ka, 0);


  memset(&b_y1[0], 0, 121U * sizeof(double));
  for (k = 0; k < 12; k++) {
    for (j = k; j + 1 < 122; j++) {
     b_y1[j] += dv0[k] * sig1[j - k];
    }
  }

  env->ReleaseDoubleArrayElements(ka,sig1,JNI_ABORT);

  jdoubleArray output = env->NewDoubleArray( sizeof(b_y1) );
  env->SetDoubleArrayRegion( output, 0, sizeof(b_y1), &b_y1[0] );

  return output;
}


它是一个过滤器,接受一个双精度数组,对其进行修改,然后将其作为函数结果返回给java。

该应用程序在启动时崩溃,我认为是因为这一行:

env->SetDoubleArrayRegion( output, 0, sizeof(b_y1), &b_y1[0] );


我第一次遇到此问题是在调用onPause()之后发生的,而带有该调用的单独线程可能仍在运行。因此,我认为这与生命周期有关。是否有可能在尝试执行SetDoubleArrayRegion()之前以某种方式检查活动是否仍处于活动状态,或者这可能是另一个问题?

奇怪的是,直到最近,代码仍可以正常工作:
我开始读取文件,然后将其用作过滤器的输入。全新安装后首次启动该应用程序时,它会要求用户授予文件读取权限。如果用户授予他们,则该应用程序可以正常运行,您可以看到过滤器输出。从那时起,当应用程序启动时,已授予读取文件的权限,并且该应用程序尝试立即启动过滤器,然后崩溃。

简单的logcat输出:

A/libc: Fatal signal 11 (SIGSEGV), code 2, fault addr 0x89fa2830 in tid 8498 (Thread-5)


Logcat的详细输出:

#00 pc 0001a21e  /system/lib/libc.so (memcpy+46)
    #01 pc 004394a6  /system/lib/libart.so (_ZN3art3JNI23SetPrimitiveArrayRegionIP13_jdoubleArraydNS_6mirror14PrimitiveArrayIdEEEEvP7_JNIEnvT_iiPKT0_+1174)
    #02 pc 0041e87c  /system/lib/libart.so (_ZN3art3JNI20SetDoubleArrayRegionEP7_JNIEnvP13_jdoubleArrayiiPKd+44)
    #03 pc 0015c9d2  /system/lib/libart.so (_ZN3art8CheckJNI23SetPrimitiveArrayRegionEPKcNS_9Primitive4TypeEP7_JNIEnvP7_jarrayiiPKv+1474)
    #04 pc 00144665  /system/lib/libart.so (_ZN3art8CheckJNI20SetDoubleArrayRegionEP7_JNIEnvP13_jdoubleArrayiiPKd+53)
    #05 pc 00000e10  /data/app/de.bastian.sip2labor-FUb-fvR-Nwyxco0g-cmxow==/lib/x86/libsip2labor-lib.so (_ZN7_JNIEnv20SetDoubleArrayRegionEP13_jdoubleArrayiiPKd+160)
    #06 pc 00000fcc  /data/app/de.bastian.sip2labor-FUb-fvR-Nwyxco0g-cmxow==/lib/x86/libsip2labor-lib.so (Java_de_bastian_sip2labor_MainActivity_filtertest+428)
    #07 pc 0063ec67  /system/lib/libart.so (art_quick_generic_jni_trampoline+71)
    #08 pc 000049d3  /dev/ashmem/dalvik-jit-code-cache (deleted)


我在这里做错了什么?预先感谢您的努力。

最佳答案

调用b_y1时,您正在读取env->SetDoubleArrayRegion( output, 0, sizeof(b_y1), &b_y1[0] );数组末尾的内容

sizeof(b_y1)


返回以字节为单位的数组大小,而不是元素数。在我的平台上,这是968,但是您的b_y1只有121个元素,因此这是未定义的行为。

您可以通过传递121(数组的实际大小)而不是sizeof(b_y1)来解决此问题。但是由于您使用的是C ++,所以我建议切换到使用std::array,因为它可以为您保留大小,并且通常具有更高级的api:

std::array<double, 121> b_y1;
int k;
int j;
static const double dv0[12] = { 1.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.65 };

jdouble *sig1;
sig1 = env->GetDoubleArrayElements(ka, 0);

b_y1.fill(0);
for (k = 0; k < 12; k++) {
    for (j = k; j + 1 < 122; j++) {
        b_y1[j] += dv0[k] * sig1[j - k];
    }
}

env->ReleaseDoubleArrayElements(ka, sig1, JNI_ABORT);

jdoubleArray output = env->NewDoubleArray(b_y1.size());
env->SetDoubleArrayRegion(output, 0, b_y1.size(), b_y1.data());

return output;

10-06 07:49