2012-06-18 30 views
14

Tôi có vấn đề sau, từ c + + tôi gửi chuỗi lớn [] tới java. lớn = tối đa 20 hàng; Tôi làm như sauAndroid NDK tràn dalvik JNI bảng tham khảo cục bộ

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

điều này xảy ra trong một vòng lặp vì vậy tôi đang làm nó cho mọi đối tượng tôi muốn lưu trong cơ sở dữ liệu, vì vậy khi bạn có thể tưởng tượng, nó happends rất nhiều lần.

Vì vậy, tôi ân cần của VM và xóa các refs địa phương của mỗi chuỗi tôi tạo ra, nhưng tôi vẫn nhận được:

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 

Bất kỳ ý tưởng là tại sao tràn đang xảy ra? Tôi đang làm gì sai?

+0

Tôi khá thuyết phục rằng bạn cần phải gọi 'ReleaseStringUTFChars' cho mỗi' NewStringUTF', bất kể bạn làm 'DeleteLocalRef' sau đó. –

+0

Có hợp lý không? kể từ khi tôi không truy cập một jstring từ vm nhưng gửi một cho nó ... Tôi có phải tạo một con trỏ đến chuỗi và sau đó gọi sử dụng con trỏ để làm releaseStringUtfChars .. – Tancho

+2

Bạn chỉ cần gọi 'ReleaseStringUTFChars() 'nếu trước đó bạn đã gọi' GetStringUTFChars() 'để tạo một chuỗi C từ một chuỗi Java. Đó không phải là trường hợp ở đây. –

Trả lời

24

Cố gắng xóa các tham chiếu cục bộ ngay lập tức sau khi sử dụng. Như thế này:

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

Tôi không chắc liệu GetObjectArrayElement() có trả về cùng một giá trị địa phương hay tạo mới. Nếu nó đang tạo ra một cái mới thì điều đó sẽ giải thích tại sao bạn đang làm đầy bảng localref.

+0

Tôi không thấy cách hệ thống có thể có tham chiếu mới? bạn nghĩ rằng bởi getElementObject họ trả về một bản sao của con trỏ? không phải là bản gốc? – Tancho

+0

Có, nó trả về một bản sao của con trỏ (thực sự nó không chỉ là một con trỏ, nó là một localref). Xem câu trả lời của @ jogabonito để biết thêm chi tiết. –

+0

Làm việc như một sự quyến rũ, thực sự cảm ơn bạn! –

3

@ Câu trả lời của Davids là chính xác. Bạn đang hết dung lượng trong bảng tham chiếu cục bộ vì các tham chiếu đến các chuỗi tạm thời mà bạn đang tạo sử dụng NewStringUTF sẽ bị mất. Nếu bạn nhìn vào thông báo lỗi của mình, bạn có thể thấy

392 của Ljava/lang/String; 28B (392 duy nhất)

Tham chiếu Các đối tượng NewStringUTF bạn đang tạo là "ẩn danh" và sẽ bị mất. Bằng cách xóa tham chiếu đến data, bạn chỉ xóa tham chiếu đến mảng đó. Các chuỗi sẽ vẫn còn trong bộ nhớ cho đến khi chức năng thoát. Tôi cũng cảm thấy rằng đi qua emptyString như là một đối số để NewObjectArray là superflous và NULL sẽ làm tốt

+0

Được rồi, sẽ thử ngay hôm nay và chia sẻ kết quả sau! – Tancho

Các vấn đề liên quan