I am wanting to pass a single large array of floats anywhere up too and beyond float[100000]. 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:
"Fatal signal 11 (SIGSEGV) at 0xbe949000 (code=1)"
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. If I create and pass a float array larger than 212 though I get the error as shown above.
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.
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). If you want to create large array, do that on heap, like Alex is showing you.
If mParticleSystem->mParticlePositions
is float array then this code will be better:
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:
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:
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;
}