我试图在单独的线程中从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;