参考表溢出(最大=512)JNI。

11
我在这个问题上有点困惑... 引用表溢出(最大值=512),我确信与本地方法调用中创建的本地引用数量有关...为了解决这个问题,我甚至尝试从本地调用中删除本地引用; 但是我仍然无法解决问题...我正在传递一个大小约为1024×1024的二维数组...
以下是我参考的错误跟踪信息...我确定创建的整数对象数量对我的情况造成了问题...正如您应该能够看到的,创建了506个整数对象...然后JNI遇到了瓶颈...
/dalvikvm(9498): GC_CONCURRENT freed 1981K, 41% free 6891K/11527K, external 1625K/2137K, paused 2ms+3ms
/dalvikvm(9498): ReferenceTable overflow (max=512)
/dalvikvm(9498): Last 10 entries in JNI local reference table:
/dalvikvm(9498):   502: 0x40710920 cls=[I (4092 bytes)
/dalvikvm(9498):   503: 0x40711920 cls=[I (4092 bytes)
/dalvikvm(9498):   504: 0x40712920 cls=[I (4092 bytes)
/dalvikvm(9498):   505: 0x40713920 cls=[I (4092 bytes)
/dalvikvm(9498):   506: 0x40714920 cls=[I (4092 bytes)
/dalvikvm(9498):   507: 0x40715920 cls=[I (4092 bytes)
/dalvikvm(9498):   508: 0x40716920 cls=[I (4092 bytes)
/dalvikvm(9498):   509: 0x40717920 cls=[I (4092 bytes)
/dalvikvm(9498):   510: 0x40718920 cls=[I (4092 bytes)
/dalvikvm(9498):   511: 0x40719920 cls=[I (4092 bytes)
/dalvikvm(9498): JNI local reference table summary (512 entries):
/dalvikvm(9498):     1 of Ljava/lang/Class; 236B
/dalvikvm(9498):     1 of Ljava/lang/Class; 284B
/dalvikvm(9498):     1 of Ljava/lang/Class; 572B
/dalvikvm(9498):     2 of Ljava/lang/String; 28B (2 unique)
/dalvikvm(9498):   506 of [I 4092B (506 unique)
/dalvikvm(9498):     1 of [Ljava/lang/String; 28B
/dalvikvm(9498): Memory held directly by tracked refs is 2071728 bytes
/dalvikvm(9498): Failed adding to JNI local ref table (has 512 entries)
/dalvikvm(9498): "main" prio=5 tid=1 RUNNABLE
/dalvikvm(9498):   | group="main" sCount=0 dsCount=0 obj=0x4001f198 self=0xce60
/dalvikvm(9498):   | sysTid=9498 nice=0 sched=0/0 cgrp=default handle=-1345006528
/dalvikvm(9498):   | schedstat=( 6990020745 1042358411 1629 )
/dalvikvm(9498):   at pv.ndk.UcMobile.losInitialization(Native Method)
/dalvikvm(9498):   at pv.ndk.NdkActivity.onCreate(NdkActivity.java:69)
/dalvikvm(9498):   at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1047)
/dalvikvm(9498):   at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:1611)

这是我正在使用的代码: 请告诉我我做错了什么?

JNIEXPORT jboolean JNICALL Java_pv_ndk_UcMobile_losInitialization
  (JNIEnv * env, jobject jobj , jint height, jint width , jobjectArray elements){

   elevData = new unsigned int*[height];

for(i=0; i< height; i++) {
    elevData[i] = new unsigned int[width];

    jintArray oneDim=
    (jintArray)env->GetObjectArrayElement(
                         elements, i);
     jint *element=env->GetIntArrayElements(oneDim, 0);
     for(j=0; j< width; j++) {
         elevData[i][j]= element[j];
     }
     // This does not seem to be providing with the desired result
     // env->DeleteLocalRef(element);

     //I even tried with this approach
     env->ReleaseIntArrayElements(oneDim, element , 0);

  }

return losObject.Init(elevData,1,10,2,2);
}
1个回答

4
您需要从oneDim对象中删除本地引用:env->DeleteLocalRef(oneDim);

这个解决方案确实帮助我创建了更多的对象...但可能为我的应用程序包(pv.ndk)创建了另一个问题 - 我希望它们没有关联..就在此之后,VM崩溃了,没有任何错误消息。D/vending(18272): [11] LocalAssetCache.updateOnePackage(): pv.ndk没有本地信息。 - Pranav
嗯,那很奇怪。你在 ReleaseIntArrayElements() 之后确实放置了 DeleteLocalRef() 吗? - beetoom
我只是想确认一下,这个问题我需要同时使用吗?目前我只使用DeleteLocalRef [因为我达到了本地引用表的512限制]。我认为我需要使用DeleteLocalRef或ReleaseIntArrayElements中的一个;它们在不同的方式上都有相同的作用。 - Pranav
是的,你需要两个函数都使用。GetObjectArrayElement 返回一个带有本地引用的对象,因此您需要删除本地引用。但是,只有在处理完数组元素后才应该这样做。因此,在 ReleaseIntArrayElements(oneDim) 之后,您应该放置 DeleteLocalRef(oneDim)。顺便问一下,您是否考虑过使用 JNI 库,例如 JNIpp - beetoom
请问在哪里详细记录了在释放数组后应使用 DeleteLocalRef?根据这个网址:http://www.ibm.com/developerworks/library/j-jni/(查看列表9),在每次使用数组元素后都要调用 DeleteLocalRef… - lysergic-acid
据我所知,@lysergic-acid,您已经回答了自己的问题。在使用数组元素后,您需要调用DeleteLocalRef。使用数组元素后,需要对元素进行释放。然后,您可以删除管理/引用此数组(因此这些元素)的arrayObject。这就是为什么您首先需要释放oneDim对象的releaseIntArrayElements,然后再释放oneDim对象本身。 - Marcin K.

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接