我从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