简体   繁体   English

Android NDK溢出dalvik JNI本地参考表

[英]Android NDK overflows dalvik JNI local reference table

I have the following problem, from c++ I send huge string[] to java. 我有以下问题,从c ++我发送巨大的字符串[]到java。 huge = at most 20 rows; 巨大的=最多20行; I am doing the following 我正在做以下事情

jint jtype = 2;
jstring emptyString = env->NewStringUTF("");
jobjectArray data = (jobjectArray)env->NewObjectArray(7, env->FindClass("java/lang/String"), emptyString);

env->SetObjectArrayElement( data,0,env->NewStringUTF(item->get_id().c_str());
env->SetObjectArrayElement( data,1,env->NewStringUTF(item->get_number().c_str());
env->SetObjectArrayElement( data,2,env->NewStringUTF(item->get_fullname().c_str());
env->SetObjectArrayElement( data,3,env->NewStringUTF(item->get_mf().c_str());
env->SetObjectArrayElement( data,4,env->NewStringUTF(item->get_dob().c_str());
env->CallVoidMethod(dao, jsaveItem, data, jtype);
int i;
for (i = 0; i < 5; ++i) {
   jstring string = (jstring) env->GetObjectArrayElement(data, i);
   env->DeleteLocalRef(string);
}
env->DeleteLocalRef(emptyString);
env->DeleteLocalRef(data);
env->DeleteLocalRef(dao);

this is happening in a loop so I am doing it for every object I want to save in the database, so as you can imagine, it happends lots of times. 这是在一个循环中发生的所以我正在为我想要保存在数据库中的每个对象执行它,所以你可以想象,它发生了很多次。

So I am considerate of the VM and delete the local refs of every string I create, but still I get : 所以我考虑了VM并删除了我创建的每个字符串的本地引用,但我仍然得到:

 ReferenceTable overflow (max=512)
Last 10 entries in JNI local reference table:
  502: 0x40552880 cls=Ljava/lang/String; (28 bytes)
  503: 0x405528b8 cls=Ljava/lang/String; (28 bytes)
  504: 0x4051f8d0 cls=Ljava/lang/Class; 'Lcom/project/storage/userdata/DataDao;' (212 bytes)
  505: 0x4052eb38 cls=Lcom/project/storage/userdata/DataDao; (12 bytes)
  506: 0x4051f8d0 cls=Ljava/lang/Class; 'Lcom/project/storage/userdata/DataDao;' (212 bytes)
  507: 0x4052eb38 cls=Lcom/project/storage/userdata/DataDao; (12 bytes)
  508: 0x4051f8d0 cls=Ljava/lang/Class; 'Lcom/project/storage/userdata/DataDao;' (212 bytes)
  509: 0x4052eb38 cls=Lcom/project/storage/userdata/DataDao; (12 bytes)
  510: 0x4051f8d0 cls=Ljava/lang/Class; 'Lcom/project/storage/userdata/DataDao;' (212 bytes)
  511: 0x4052eb38 cls=Lcom/project/storage/userdata/DataDao; (12 bytes)
JNI local reference table summary (512 entries):
   58 of Ljava/lang/Class; 212B (1 unique)
    1 of Ljava/lang/Class; 236B
   25 of Ljava/lang/Class; 284B (1 unique)
    1 of Ljava/lang/Class; 572B
  392 of Ljava/lang/String; 28B (392 unique)
    1 of Ljava/lang/String; 36B
    1 of [Ljava/lang/String; 28B
    2 of [Ljava/lang/String; 92B (2 unique)
   31 of Lcom/project/storage/userdata/DataDao; 12B (1 unique)
Memory held directly by tracked refs is 12540 bytes

Any ideas as to why the overflow is happening? 关于为什么发生溢出的任何想法? what am I doing wrong? 我究竟做错了什么?

Try to delete the local refs immediately after use. 尝试在使用后立即删除本地引用。 Like this: 像这样:

jstring string;
string = env->NewStringUTF(item->get_id().c_str());
env->SetObjectArrayElement( data,0,string);
env->DeleteLocalRef(string);
string = env->NewStringUTF(item->get_number().c_str());
env->SetObjectArrayElement( data,1,string);
env->DeleteLocalRef(string);
string = env->NewStringUTF(item->get_fullname().c_str());
env->SetObjectArrayElement( data,2,string);
env->DeleteLocalRef(string);
string = env->NewStringUTF(item->get_mf().c_str());
env->SetObjectArrayElement( data,3,string);
env->DeleteLocalRef(string);
string = env->NewStringUTF(item->get_dob().c_str());
env->SetObjectArrayElement( data,4,string);
env->DeleteLocalRef(string);
env->CallVoidMethod(dao, jsaveItem, data, jtype);

I'm not sure if GetObjectArrayElement() is returning the same localref or creating a new one. 我不确定GetObjectArrayElement()是返回相同的localref还是创建一个新的。 If it is creating a new one then that would explain why you are filling up the localref table. 如果它正在创建一个新的,那么这将解释为什么要填充localref表。

@Davids's answer is correct. @ Davids的回答是正确的。 You are running out of space in the local reference table since the references to the temporary strings you are creating using NewStringUTF are getting lost. 由于使用NewStringUTF创建的临时字符串的引用丢失,因此本地引用表中的空间不足。 If you look at your error message you can see 如果您查看错误消息,您可以看到

392 of Ljava/lang/String; Ljava / lang / String中的392; 28B (392 unique) 28B(392独特)

The references NewStringUTF objects you are creating are "anonymous" and will be lost. 您正在创建的引用NewStringUTF对象是“匿名的”,将丢失。 By deleting the reference to data you are only deleting the reference to the array. 通过删除对data的引用,您只删除对数组的引用。 The strings will still be in memory till the function exits. 字符串仍将在内存中,直到函数退出。 I also feel that passing emptyString as an argument to NewObjectArray is superflous and NULL will do as well 我也觉得将emptyString作为参数传递给NewObjectArray是超级的,NULL也会这样做

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

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