14

次の問題があります.c ++から巨大なstring []をjavaに送信します. huge = 最大 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);

これはループで発生しているため、データベースに保存するすべてのオブジェクトに対して実行しています。ご想像のとおり、何度も発生します。

したがって、私は 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

オーバーフローが発生している理由についてのアイデアはありますか? 私は何を間違っていますか?

4

2 に答える 2

25

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. If it is creating a new one then that would explain why you are filling up the localref table.

于 2012-06-18T09:42:28.203 に答える
3

@Davidsの答えは正しいです。NewStringUTF使用して作成している一時文字列への参照が失われているため、ローカル参照テーブルのスペースが不足しています。エラーメッセージを見るとわかります

392 の Ljava/lang/String; 28B (392 固有)

作成している参照 NewStringUTF オブジェクトは「匿名」であり、失われます。への参照をdata削除すると、配列への参照のみが削除されます。関数が終了するまで、文字列はメモリ内に残ります。emptyStringまた、引数として渡すのNewObjectArrayは不必要であり、NULLでも同様に機能すると思います

于 2012-06-18T13:14:45.360 に答える