简体   繁体   English

Android通过jni将大型float数组从本机传递到Java。 如果超过一定大小会出现错误

[英]Android passing large float arrays from native to java via jni. Getting error if over certain size

I am wanting to pass a single large array of floats anywhere up too and beyond float[100000]. 我想在整个float和[100000]之外的任何地方传递一个大型的float数组。 I have a setup successfully passing an array of size 212. But any larger and it crashes giving the following error message in the logcat: 我有一个安装程序成功传递了大小为212的数组。但是任何较大的安装程序都会崩溃,并在logcat中给出以下错误消息:

"Fatal signal 11 (SIGSEGV) at 0xbe949000 (code=1)" “致命信号11(SIGSEGV)位于0xbe949000(代码= 1)”

My code 我的密码

Native function 本机功能

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 Pretty straight forward simply grabbing the array. Java非常简单地获取数组。 If I create and pass a float array larger than 212 though I get the error as shown above. 如果我创建并传递了一个大于212的float数组,尽管出现了如上所述的错误。

float tempArray[] = NativeWrapper.getArrayNative();

Has anyone encountered this problem or can see how I can get around this limit? 有没有人遇到这个问题,或者可以看到我如何解决这个限制? Also I apologise if this question has been answered already, I could not find this specific issue nor an answer. 我也很抱歉,如果这个问题已经得到回答,我找不到这个特定问题或答案。 Any help will be appreciated :) 任何帮助将不胜感激 :)

EDIT: 编辑:

For updating a global jfloatArray to avoid the garbage collector when frequently fetching an array through jni. 用于更新全局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;
}

Problem with your code is that stack is limited in size. 您的代码的问题是堆栈的大小受到限制。 You can not put there large arrays ( jfloat cArray[tempSize] variable). 您不能在其中放置大型数组( jfloat cArray[tempSize]变量)。 If you want to create large array, do that on heap, like Alex is showing you. 如果要创建大型数组,请像Alex所示那样在堆上进行。

If mParticleSystem->mParticlePositions is float array then this code will be better: 如果mParticleSystem->mParticlePositions是浮点数组,则此代码会更好:

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

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

If it is not float array then use following code, no need to create additional float array: 如果不是float数组,则使用以下代码,无需创建其他float数组:

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;

EDIT 编辑

To store jArray somewhere else (for example globally) do following: 要将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;
}

When done free the memory: 完成后释放内存:

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

Your code does not compile: you probably had 您的代码无法编译:您可能有

jfloat *cArray = new jfloat[tempSize];

in your compiled code. 在您的编译代码中。

The mistake in your code is in call to NewFloatArray(). 您的代码中的错误是在调用NewFloatArray()。 You should call NewFloatArray(tempSize), not (sizeof(cArray)). 您应该调用NewFloatArray(tempSize),而不是(sizeof(cArray))。

Also note that there is no need to work with intermediate copy of mParticleSystem->mParticlePositions. 另请注意,无需使用mParticleSystem-> mParticlePositions的中间副本。 If it is an array of float, you can simply use it for SetFloatArrayRegion(). 如果它是一个float数组,则可以将其简单地用于SetFloatArrayRegion()。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM