2012-06-18 42 views
14

私はC++から次のような問題があります。巨大=最大20行。 私は私はあなたが想像できるように、データベースに保存するすべてのオブジェクトのためにそれをやっているので、これはループ内で起こっている、次のAndroid NDKのオーバーフローdalvik JNIローカル参照テーブル

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

をやって、それは時間の多くをhappends。

だから私は、VMの思いやりと私が作成したすべての文字列のローカルREFを削除し、それでも私が取得:

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 

任意のアイデアオーバーフローが起こっている理由を? 私は何が間違っていますか?

+0

その後、 'DeleteLocalRef'を行うかどうかにかかわらず、' NewStringUTF'ごとに 'ReleaseStringUTFChars'を呼び出す必要があると確信しています。 –

+0

意味がありますか?私はvmからjstringにアクセスしていないので、それを送信しています...文字列へのポインタを作成し、そのポインタを使ってreleaseStringUtfCharsを呼び出す必要がありますか? – Tancho

+2

'ReleaseStringUTFChars() '以前に' GetStringUTFChars() 'を呼び出してJava-StringからC-Stringを作成した場合は、それはここでは当てはまりません。 –

答えて

24

使用直後にローカル参照を削除してみます。このように:

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テーブルを埋めるのか説明できます。

+0

システムで新しい参照を取得する方法がわかりません。あなたはgetElementObjectによってポインタのコピーを返すと思いますか?元のものではありませんか? – Tancho

+0

はい、ポインタのコピーを返します(実際にはポインタではなく、ローカル参照)。詳細については、@ jogabonitoの答えをご覧ください。 –

+0

魅力のように動作します、本当にありがとうございます! –

3

@ Davidsの回答は正しいです。 NewStringUTFを使用して作成している一時的な文字列への参照が失われているため、ローカル参照テーブルの領域が不足しています。あなたは、エラーメッセージを見れば、あなたはLjava/LANG /文字列の

392を見ることができます。 28B(ユニークな392)

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

+0

さて、今日試してみて、結果を共有しましょう! – Tancho

関連する問題