2014-09-21 45 views
1

我有JNI的C++代碼調用Java對象的方法,例如:Android的JNI:崩潰全局和局部參考變量

jclass JIOManager = CJavaEnv::getInstance()->env()->FindClass(ioManagerName); 

    ..... some code 

CJavaEnv::getInstance()->env()->DeleteLocalRef(JIOManager); 

這個作品真的很好,當主線程執行,但是當我嘗試執行此在另一個線程 它崩潰,因爲它說它是在另一個線程中創建的:哦!但在我閱讀過谷歌Android開發者網站之後,他們說從任何線程訪問全局引用都沒有問題,所以我改變了代碼。

jclass JIOManager = (jclass)CJavaEnv::getInstance()->env()->NewGlobalRef(CJavaEnv::getInstance()->env()->FindClass(ioManagerName)); 

    ..... some code 

CJavaEnv::getInstance()->env()->DeleteGlobalRef(JIOManager); 

,但我得到這個崩潰:

09-21 15:38:13.259: E/dalvikvm(3210): JNI ERROR (app bug): local reference table overflow (max=512) 
09-21 15:38:13.259: W/dalvikvm(3210): JNI local reference table (0x76fb50) dump: 
09-21 15:38:13.259: W/dalvikvm(3210): Last 10 entries (of 512): 
09-21 15:38:13.259: W/dalvikvm(3210):  511: 0x40a609a8 java.lang.Class<libcore.icu.NativeConverter> 
09-21 15:38:13.259: W/dalvikvm(3210):  510: 0x42349610 byte[] (1 elements) 
09-21 15:38:13.259: W/dalvikvm(3210):  509: 0x41d866b8 java.lang.Class<com.Cocoa.CocoaAndroidSDK.CocoaUnicodeConverter> 
09-21 15:38:13.259: W/dalvikvm(3210):  508: 0x423495f8 byte[] (2 elements) 
09-21 15:38:13.259: W/dalvikvm(3210):  507: 0x42349428 byte[] (1 elements) 
09-21 15:38:13.259: W/dalvikvm(3210):  506: 0x41d866b8 java.lang.Class<com.Cocoa.CocoaAndroidSDK.CocoaUnicodeConverter> 
09-21 15:38:13.259: W/dalvikvm(3210):  505: 0x42349410 byte[] (2 elements) 
09-21 15:38:13.259: W/dalvikvm(3210):  504: 0x422b3f08 byte[] (1 elements) 
09-21 15:38:13.259: W/dalvikvm(3210):  503: 0x41d866b8 java.lang.Class<com.Cocoa.CocoaAndroidSDK.CocoaUnicodeConverter> 
09-21 15:38:13.259: W/dalvikvm(3210):  502: 0x422b3ef0 byte[] (2 elements) 
09-21 15:38:13.259: W/dalvikvm(3210): Summary: 
09-21 15:38:13.259: W/dalvikvm(3210):  172 of java.lang.Class (3 unique instances) 
09-21 15:38:13.259: W/dalvikvm(3210):   1 of java.lang.String 
09-21 15:38:13.259: W/dalvikvm(3210):   8 of byte[] (8 unique instances) 
09-21 15:38:13.259: W/dalvikvm(3210):  20 of byte[] (1 elements) (20 unique instances) 
09-21 15:38:13.259: W/dalvikvm(3210):  27 of byte[] (2 elements) (27 unique instances) 
09-21 15:38:13.259: W/dalvikvm(3210):   2 of byte[] (3 elements) (2 unique instances) 
09-21 15:38:13.259: W/dalvikvm(3210):  16 of byte[] (4 elements) (16 unique instances) 
09-21 15:38:13.259: W/dalvikvm(3210):  40 of byte[] (5 elements) (40 unique instances) 
09-21 15:38:13.259: W/dalvikvm(3210):   2 of byte[] (6 elements) (2 unique instances) 
09-21 15:38:13.259: W/dalvikvm(3210):   4 of byte[] (7 elements) (4 unique instances) 
09-21 15:38:13.259: W/dalvikvm(3210):  22 of byte[] (8 elements) (22 unique instances) 
09-21 15:38:13.259: W/dalvikvm(3210):  15 of byte[] (9 elements) (15 unique instances) 
09-21 15:38:13.259: W/dalvikvm(3210):  40 of byte[] (10 elements) (40 unique instances) 
09-21 15:38:13.259: W/dalvikvm(3210):   3 of byte[] (11 elements) (3 unique instances) 
09-21 15:38:13.259: W/dalvikvm(3210):  17 of byte[] (12 elements) (17 unique instances) 
09-21 15:38:13.259: W/dalvikvm(3210):   7 of byte[] (14 elements) (7 unique instances) 
09-21 15:38:13.259: W/dalvikvm(3210):   8 of byte[] (15 elements) (8 unique instances) 
09-21 15:38:13.259: W/dalvikvm(3210):  15 of byte[] (16 elements) (15 unique instances) 
09-21 15:38:13.259: W/dalvikvm(3210):   8 of byte[] (17 elements) (8 unique instances) 
09-21 15:38:13.259: W/dalvikvm(3210):  16 of byte[] (18 elements) (16 unique instances) 
09-21 15:38:13.259: W/dalvikvm(3210):   3 of byte[] (21 elements) (3 unique instances) 
09-21 15:38:13.259: W/dalvikvm(3210):   3 of byte[] (22 elements) (3 unique instances) 
09-21 15:38:13.259: W/dalvikvm(3210):  17 of byte[] (24 elements) (17 unique instances) 
09-21 15:38:13.259: W/dalvikvm(3210):   4 of byte[] (28 elements) (4 unique instances) 
09-21 15:38:13.259: W/dalvikvm(3210):   8 of byte[] (30 elements) (8 unique instances) 
09-21 15:38:13.259: W/dalvikvm(3210):   1 of byte[] (32 elements) 
09-21 15:38:13.259: W/dalvikvm(3210):   4 of byte[] (33 elements) (4 unique instances) 
09-21 15:38:13.259: W/dalvikvm(3210):   8 of byte[] (34 elements) (8 unique instances) 
09-21 15:38:13.259: W/dalvikvm(3210):   5 of byte[] (36 elements) (5 unique instances) 
09-21 15:38:13.259: W/dalvikvm(3210):   2 of byte[] (41 elements) (2 unique instances) 
09-21 15:38:13.259: W/dalvikvm(3210):   3 of byte[] (42 elements) (3 unique instances) 
09-21 15:38:13.259: W/dalvikvm(3210):   1 of byte[] (56 elements) 
09-21 15:38:13.259: W/dalvikvm(3210):   4 of byte[] (66 elements) (4 unique instances) 
09-21 15:38:13.259: W/dalvikvm(3210):   4 of byte[] (72 elements) (4 unique instances) 
09-21 15:38:13.259: W/dalvikvm(3210):   2 of byte[] (82 elements) (2 unique instances) 
09-21 15:38:13.259: E/dalvikvm(3210): Failed adding to JNI local ref table (has 512 entries) 
09-21 15:38:13.259: I/dalvikvm(3210): "AsyncTask #2" prio=5 tid=16 RUNNABLE 
09-21 15:38:13.259: I/dalvikvm(3210): | group="main" sCount=0 dsCount=0 obj=0x41decfd8 self=0x776200 
09-21 15:38:13.259: I/dalvikvm(3210): | sysTid=3236 nice=10 sched=0/0 cgrp=bg_non_interactive handle=7541280 
09-21 15:38:13.259: I/dalvikvm(3210): | schedstat=(0 0 0) utm=82 stm=70 core=1 
09-21 15:38:13.259: I/dalvikvm(3210): at libcore.icu.NativeConverter.openConverter(Native Method) 
09-21 15:38:13.259: I/dalvikvm(3210): at java.nio.charset.CharsetEncoderICU.newInstance(CharsetEncoderICU.java:71) 
09-21 15:38:13.259: I/dalvikvm(3210): at java.nio.charset.CharsetICU.newEncoder(CharsetICU.java:27) 
09-21 15:38:13.259: I/dalvikvm(3210): at java.nio.charset.Charset.encode(Charset.java:451) 
09-21 15:38:13.259: I/dalvikvm(3210): at java.lang.String.getBytes(String.java:870) 
09-21 15:38:13.259: I/dalvikvm(3210): at com.Cocoa.CocoaAndroidSDK.CocoaUnicodeConverter.UTF8_TO_UTF16(CocoaUnicodeConverter.java:16) 
09-21 15:38:13.259: I/dalvikvm(3210): at com.Cocoa.CocoaAndroidSDK.CocoaSDKNativeLib.load(Native Method) 
09-21 15:38:13.259: I/dalvikvm(3210): at com.Cocoa.CocoaViewer.MainActivity$LongOperation.doInBackground(MainActivity.java:1498) 
09-21 15:38:13.259: I/dalvikvm(3210): at com.Cocoa.CocoaViewer.MainActivity$LongOperation.doInBackground(MainActivity.java:1) 
09-21 15:38:13.259: I/dalvikvm(3210): at android.os.AsyncTask$2.call(AsyncTask.java:264) 
09-21 15:38:13.259: I/dalvikvm(3210): at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:305) 
09-21 15:38:13.259: I/dalvikvm(3210): at java.util.concurrent.FutureTask.run(FutureTask.java:137) 
09-21 15:38:13.259: I/dalvikvm(3210): at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1076) 
09-21 15:38:13.259: I/dalvikvm(3210): at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:569) 
09-21 15:38:13.259: I/dalvikvm(3210): at java.lang.Thread.run(Thread.java:856) 
09-21 15:38:13.259: E/dalvikvm(3210): VM aborting 
09-21 15:38:13.259: A/libc(3210): Fatal signal 11 (SIGSEGV) at 0xdeadd00d (code=1) 

任何幫助表示讚賞。

回答

2

還必須附加「其他」線程才能使用JIOManager。爲什麼不在那裏獲得當地的參考?另一方面,你的崩潰轉儲表明實際上你只看3個類。所以你可以創建這些全局引用(如果你覺得更容易,甚至可以在JNI_OnLoad()之內),並從你的所有本地線程中使用它們。

+0

謝謝你,你給了我如何解決問題的想法 – Kamilia 2014-09-24 10:33:14

2

每個線程的局部引用數量有限制,並且超出了它。執行此操作的最常見方法是在循環中創建本地引用,而不是隨時刪除它們。

當執行程序返回到虛擬機時,本地引用會自動清除(並且幾乎是即時),因此爲了簡單起見,最好讓虛擬機執行此操作。但是,如果您創建的本地引用超過16個,最好手動進行清理。

FindClass的調用會創建一個本地引用。致電NewGlobalRef會創建一個全局引用,而不會破壞本地引用。你應該修改你的代碼看起來像這樣:

jclass temp = CJavaEnv::getInstance()->env()->FindClass(ioManagerName); 
jclass JIOManager = (jclass)CJavaEnv::getInstance()->env()->NewGlobalRef(temp); 
CJavaEnv::getInstance()->env()->DeleteLocalRef(temp); 

全局引用不被破壞,除非你明確地消滅他們,所以要小心泄露他們。當啓用CheckJNI時,有幾千個上限;如果沒有CheckJNI,他們可以無限制地積累。

另請參閱JNI Tips

+0

非常感謝您的回答,但我仍然崩潰也許我做錯了事情,我想不使用jni和線程,並試圖使用c + + 11 codecvt和wstring_convert但它不在gcc std庫我知道他們在clang編譯器中,如果你能幫助我,我怎麼用clang而不是gcc構建。 – Kamilia 2014-09-22 09:08:22

+0

謝謝,您的信息非常有幫助! – Kamilia 2014-09-24 10:32:52