【问题标题】:Android NDK overflows dalvik JNI local reference tableAndroid NDK 溢出 dalvik JNI 本地引用表
【发布时间】:2012-06-18 09:17:04
【问题描述】:

我有以下问题,从 c++ 我将巨大的字符串 [] 发送到 java。巨大的 = 最多 20 行; 我正在做以下事情

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);

这是在一个循环中发生的,所以我对每个我想保存在数据库中的对象都这样做,所以你可以想象,它发生了很多次。

所以我很体贴虚拟机并删除了我创建的每个字符串的本地引用,但我仍然得到:

 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

关于为什么会发生溢出的任何想法? 我做错了什么?

【问题讨论】:

  • 我非常确信您需要为每个NewStringUTF 调用ReleaseStringUTFChars,无论您之后是否调用DeleteLocalRef
  • 有意义吗?因为我不是从 vm 访问 jstring,而是向它发送一个 jstring...我是否必须创建一个指向该字符串的指针,然后调用使用该指针来执行 releaseStringUtfChars ..
  • 如果您之前调用了GetStringUTFChars() 从Java 字符串创建C 字符串,则只需调用ReleaseStringUTFChars()。这不是这里的情况。

标签: android java-native-interface dalvik android-ndk


【解决方案1】:

尝试在使用后立即删除本地引用。像这样:

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);

我不确定 GetObjectArrayElement() 是返回相同的 localref 还是创建一个新的。如果它正在创建一个新的,那么这将解释您为什么要填充 localref 表。

【讨论】:

  • 我看不到系统如何获得新的参考?您认为通过 getElementObject 他们返回指针的副本?不是原来的吗?
  • 是的,它返回一个指针的副本(实际上它不仅仅是一个指针,它是一个localref)。有关更多详细信息,请参阅@jogabonito 的答案。
【解决方案2】:

@Davids 的回答是正确的。由于对使用 NewStringUTF 创建的临时字符串的引用丢失了,因此本地引用表中的空间不足。如果您查看错误消息,您会看到

Ljava/lang/String 的 392 个; 28B(392 个唯一)

您正在创建的引用 NewStringUTF 对象是“匿名的”并且将会丢失。通过删除对data 的引用,您只是在删除对数组的引用。在函数退出之前,字符串仍将保留在内存中。我也觉得将emptyString 作为参数传递给NewObjectArray 是多余的,NULL 也可以

【讨论】:

  • 好的,今天就试试,之后分享结果!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-06-06
  • 1970-01-01
  • 2012-11-09
  • 1970-01-01
相关资源
最近更新 更多