机器人通过JNI传递大浮阵列从天然到Java。 获取错误,如果超过一定的规模(Android p

2019-08-05 06:23发布

我想传递一个大阵的花车任何地方涨得超越浮动[100000]。 我有一个安装成功通过大小212的阵列,但任何较大和崩溃给予在logcat的下面的错误消息:

“致命信号11(SIGSEGV)在0xbe949000(代码= 1)”

我的代码

本机的功能

NIEXPORT jfloatArray JNICALL  Java_carron_graphics_benchmark_NativeWrapper_getArrayNative(JNIEnv * env, jclass cls) {

    int tempSize = mParticleSystem->mSizeOfSystem*2;

    jfloat cArray[tempSize];
    jsize len = sizeof(cArray);

    jfloatArray jArray = (*env).NewFloatArray(len);

    if (jArray != NULL) {

        jint i;

        for (i = 0; i < tempSize; i++) {
            cArray[i] = mParticleSystem->mParticlePositions[i];
        }
        (*env).SetFloatArrayRegion(jArray, 0, len, cArray);
    }
    return jArray;
}

Java的非常简洁明了简单地抓住了阵。 如果创建并传递一个float数组比212大,虽然我得到的错误,如上所示。

float tempArray[] = NativeWrapper.getArrayNative();

有没有人遇到这个问题,或者能看到我怎样才能解决这个限制? 此外,我很抱歉,如果这个问题已经被回答了,我找不到这个具体问题,也不是一个答案。 任何帮助将不胜感激 :)

编辑:

用于更新全局jfloatArray以避免垃圾收集器时频繁取通过JNI的阵列。

static jfloatArray gArray = NULL;

JNIEXPORT jfloatArray JNICALL Java_carron_graphics_benchmark_NativeWrapper_getArrayNative(JNIEnv * env, jclass cls)  {
    int arrayLength = mParticleSystem->mSizeOfSystem*2;

    if (gArray == NULL)
    {
        // create array
        jfloatArray jArray;
        jArray = env->NewFloatArray(arrayLength);
        gArray = (jfloatArray)env->NewGlobalRef(jArray);
    }

    // Update global 
    env->SetFloatArrayRegion(gArray, 0, arrayLength, mParticleSystem->mParticlePositions);

    return gArray;
}

Answer 1:

与您的代码的问题是,堆栈的大小是有限的。 你不能把有大阵列( jfloat cArray[tempSize]变量)。 如果你想创建大阵,这样做对堆,像亚历克斯向您展示。

如果mParticleSystem->mParticlePositions是float数组那么这个代码会更好:

int tempSize = mParticleSystem->mSizeOfSystem*2;
jfloatArray jArray = env->NewFloatArray(tempSize);

if (jArray != NULL)
{
    env->SetFloatArrayRegion(jArray, 0, tempSize, mParticleSystem->mParticlePositions);
}
return jArray;

如果不是浮阵列,然后使用下面的代码,无需创建额外的浮动阵列:

int tempSize = mParticleSystem->mSizeOfSystem*2;
jfloatArray jArray = env->NewFloatArray(tempSize);

if (jArray != NULL)
{
    if (float* ptr = env->GetFloatArrayElements(jArray, NULL))
    {
        for (int i=0; i<tempSize; i++)
        {
            ptr[i] = mParticleSystem->mParticlePositions[i];
        }
        env->ReleaseFloatArrayElements(jArray, ptr, JNI_COMMIT);
    }
}

return jArray;

编辑

为了存储jArray其他地方(例如全球)执行以下操作:

static jfloatArray gArray = NULL;

jfloatArray fun(...)
{
    jfloatArray jArray;

    if (gArray == NULL)
    {
        // create array
        jArray = env->NewFloatArray(tempSize);
        gArray = (jfloatArray)env->NewGlobalRef(jArray);
    }
    else
    {
        jArray = gArray;
    }

    // ... here fill/modify jArray
    // SetFLoatArrayRegion/GetFloatArrayElemeents/ReleaseFloatArrayElements

    return jArray;
}

完成后释放内存:

void freeArray(...)
{
    env->DeleteGlobalRef(gArray);
    gArray = NULL;
}


Answer 2:

您的代码无法编译:你可能有

jfloat *cArray = new jfloat[tempSize];

在你的编译代码。

在你的代码错就错在调用NewFloatArray()。 你应该叫NewFloatArray(tempSize),不是(的sizeof(CARRAY))。

另外请注意,没有必要与mParticleSystem-> mParticlePositions的中间拷贝工作。 如果它是浮动的数组,你可以简单地使用它SetFloatArrayRegion()。



文章来源: Android passing large float arrays from native to java via jni. Getting error if over certain size