我從C代碼調用Java方法。每次撥打電話時,我都會調用AttachCurrentThread,並在呼叫完成後調用DetachCurrentThread。爲什麼調用DetachCurrentThread()會導致垃圾收集過多?
這工作正常,但問題是,我看到由該即幾乎每個通過JNI調用引起的後續垃圾收集。 VisualVM上的小圖集合基本上都是綠色的!從本地代碼到Java的調用速率是每秒數百次。在那些調用期間,我還可以看到過多的Java線程被創建,如Thread-34543,Thread-34544,Thread-34545等,這可能是GC的原因。看起來每個通話都是通過不同的線程完成的。
任何人都看到了?
只是添加到,當我不DetachCurrentThread根本沒有GC,但VisualVM中的線程視圖顯示數百個線程連接到虛擬機。有小費嗎?
JVM設置
-Xms2048m -Xmx2048m -XX:MaxDirectMemorySize = 256M -XX:+ HeapDumpOnOutOfMemoryError -Dfile.encoding = UTF-8 -Dcom.sun.management.jmxremote.ssl =假-Dcom.sun。 management.jmxremote.authenticate =假-Dcom.sun.management.jmxremote.port = 3333
平臺: Ubuntu的12.04 的Linux 3.2.0-35泛型#55-Ubuntu的SMP星期三12月05日17點42分16秒UTC 2012 x86_64 x86_64 x86_64 GNU/Linux
Java:
OpenJDK的運行時環境(1.11.5 IcedTea6)(6b24-1.11.5-0ubuntu1〜12.04.1) OpenJDK的64位服務器VM(構建20.0-B12,混合模式)
UPDATE 2013年3月30日
我覺得我的問題在別的地方。 我打印出線程的ID,看起來只有幾個線程正在調用我的JNI代碼。 上次運行顯示13個線程。問題是,在運行時
if ((*vm)->GetEnv(vm, (void**)&env, JNI_VERSION_1_4) == JNI_OK)
return env;
else
return NULL;
得到的JNIEnv *與當前線程關聯,我得到的錯誤代碼-2(JNI_EDETACHED)。爲了清楚起見,我根本不會調用DetachCurrentThread,因爲我期待這些線程回到我的本地庫。 在這種情況下,我再次附加本地線程,這可能會導致在JVM中創建過多的線程abject。 最後運行顯示
29 [478e](get_env) Thread 2633996032 has env: (nil), err was: -2
47 [478e](get_env) Thread 2642388736 has env: (nil), err was: -2
32 [478e](get_env) Thread 2650781440 has env: (nil), err was: -2
31 [478e](get_env) Thread 2659174144 has env: (nil), err was: -2
37 [478e](get_env) Thread 2667566848 has env: (nil), err was: -2
30 [478e](get_env) Thread 2675959552 has env: (nil), err was: -2
32 [478e](get_env) Thread 2684352256 has env: (nil), err was: -2
33 [478e](get_env) Thread 2760873728 has env: (nil), err was: -2
33 [478e](get_env) Thread 2769266432 has env: (nil), err was: -2
37 [478e](get_env) Thread 2777659136 has env: (nil), err was: -2
36 [478e](get_env) Thread 2786051840 has env: (nil), err was: -2
31 [478e](get_env) Thread 2794444544 has env: (nil), err was: -2
52 [478e](get_env) Thread 3707176704 has env: (nil), err was: -2
,其中第一列是連接線程不具有與它相關聯的有效ENV電話號碼。 任何想法爲什麼會發生?
解釋一下。在我的情況下,本地線程創建在我的JNI庫之外,所以我無法控制這些線程的數量。我注意到,當沒有太多活動時,只有4-5個原生線程正在使用。只有在重載線程數量增加的情況下。奇怪的是,虛擬機不會以任何方式嘗試重用JVM線程對象。另外我注意到,在我的情況下,整個應用程序工作更有效率,當我不分離。很顯然,我需要早晚分離,所以我正在考慮某種本地線程管理器,它會分離未曾調用過VM代碼的線程一段時間。 – ivenhov
謝謝parsifal。請參閱我的更新瞭解我所觀察到的更多細節。感謝有關清理處理程序和setspecific的提示 – ivenhov