2012-06-18 13 views
14

Ho il seguente problema, da C++ invio stringa enorme [] a java. enorme = al massimo 20 file; sto facendo il seguenteNDK Android trabocca dalvik Tabella di riferimento locale 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); 

questo sta accadendo in un ciclo così lo sto facendo per ogni oggetto voglio salvare nel database, così come si può immaginare, è happends un sacco di volte.

Quindi io sono rispettoso della macchina virtuale ed eliminare gli arbitri locali di ogni stringa che creo, ma ancora ottengo:

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 

Tutte le idee sul perché l'overflow sta accadendo? cosa sto sbagliando?

+0

Sono abbastanza convinto che è necessario chiamare 'ReleaseStringUTFChars' per ogni' NewStringUTF', indipendentemente dal fatto che si fa 'DeleteLocalRef' dopo. –

+0

Ha senso? dato che non sto accedendo a una jstring dal vm ma ne sto mandando uno ... Dovrei creare un puntatore alla stringa e poi chiamare usare quel puntatore per fare il rilascioStringUtfChars .. – Tancho

+2

Devi solo chiamare 'ReleaseStringUTFChars() 'se in precedenza hai chiamato' GetStringUTFChars() 'per creare una C-String da una stringa Java. Questo non è il caso qui. –

risposta

24

Provare a eliminare i riferimenti locali immediatamente dopo l'uso. Come questo:

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

io non sono sicuro se GetObjectArrayElement() sta tornando la stessa localref o la creazione di uno nuovo. Se ne sta creando uno nuovo, questo spiegherebbe perché stai riempiendo la tabella localref.

+0

Non vedo come il sistema può ottenere un nuovo riferimento? pensi che da getElementObject restituiscano una copia del puntatore? non quello originale? – Tancho

+0

Sì, restituisce una copia del puntatore (in realtà non è solo un puntatore, è un riferimento locale). Vedi la risposta di @ jogabonito per maggiori dettagli. –

+0

Funziona come un incantesimo, davvero grazie! –

3

@ La risposta di Davids è corretta. Si sta esaurendo lo spazio nella tabella di riferimento locale poiché i riferimenti alle stringhe temporanee che si stanno creando utilizzando NewStringUTF si vanno perdere. Se guardate il vostro messaggio di errore potete vedere

392 di Ljava/lang/String; 28B (392 unique)

I riferimenti agli oggetti NewStringUTF che si stanno creando sono "anonimi" e andranno persi. Eliminando il riferimento a data si sta cancellando solo il riferimento all'array. Le stringhe saranno ancora in memoria fino all'uscita dalla funzione. Ritengo inoltre che il passaggio emptyString come argomento a NewObjectArray è superfluo e NULL farò così

+0

Ok, ci proverò oggi e condividerò i risultati dopo! – Tancho

Problemi correlati