我用Java 8编写了一个服务器应用程序,并使用Java 1.8.0u25运行它。
它可以在最初的几个小时内正常工作,但是在收到大约5k至10k请求之后,VM进程的线程使用了其中一个CPU的100%。
因此,我尝试jstack让VM进程检查有问题的线程是什么,它显示线程(线程ID为14303 = 0x37df)为“ C2 CompilerThread0”:
jstack
"C2 CompilerThread0" #6 daemon prio=9 os_prio=0 tid=0x00002aaabc12a000 nid=0x37df runnable [0x0000000000000000] java.lang.Thread.State: RUNNABLE
使用jstack -m,线程的堆栈跟踪如下:
jstack -m
----------------- 14303 ----------------- 0x00002b99b67693c3 _ZN16PhaseMacroExpand27process_users_of_allocationEP8CallNode + 0x2a3 0x00002b99b676ec3b _ZN16PhaseMacroExpand23eliminate_allocate_nodeEP12AllocateNode + 0x1cb 0x00002b99b676ee65 _ZN16PhaseMacroExpand21eliminate_macro_nodesEv + 0x1a5 0x00002b99b6772769 _ZN16PhaseMacroExpand18expand_macro_nodesEv + 0x19 0x00002b99b640b01b _ZN7Compile8OptimizeEv + 0xa6b 0x00002b99b640c53c _ZN7CompileC1EP5ciEnvP10C2CompilerP8ciMethodibbb + 0x13bc 0x00002b99b635f9c8 _ZN10C2Compiler14compile_methodEP5ciEnvP8ciMethodi + 0x198 0x00002b99b6414c6a _ZN13CompileBroker25invoke_compiler_on_methodEP11CompileTask + 0xc8a 0x00002b99b6417650 _ZN13CompileBroker20compiler_thread_loopEv + 0x620 0x00002b99b69a2e8f _ZN10JavaThread17thread_main_innerEv + 0xdf 0x00002b99b69a2fbc _ZN10JavaThread3runEv + 0x11c 0x00002b99b6860d48 _ZL10java_startP6Thread + 0x108
每一次我尝试一次jstack -m,这个线程的堆栈跟踪一切都是一样的,但在堆栈的顶部的方法(程序计数器?)旁边的数字_ZN16PhaseMacroExpand27process_users_of_allocationEP8CallNode是0x290,0x2b1,0x2a3,或0x29f。
_ZN16PhaseMacroExpand27process_users_of_allocationEP8CallNode
0x290
0x2b1
0x2a3
0x29f
C2 CompilerThread0 看起来像是一个执行JIT编译的线程,并且堆栈跟踪看起来像陷入了无限循环之类。
C2 CompilerThread0
我想知道这是否可能是JVM的JIT编译器的错误。如果是的话,如何指定应用程序的哪种方法使JVM疯狂,如何解决(或解决)此问题?我尝试了-XX:+PrintCompilationoption,但是它没有太大帮助,因为它没有显示哪个线程编译了哪个方法。如果这不是JVM的问题,那么会发生什么呢?
-XX:+PrintCompilation
确实看起来像是JIT编译器错误,大概是在分配消除优化中。 尝试使用-XX:-EliminateAllocationsJVM选项运行。
-XX:-EliminateAllocations
您还可以添加-XX:+UnlockDiagnosticVMOptions -XX:+LogCompilation生成详细的编译日志,每个编译器线程具有单独的输出文件。
-XX:+UnlockDiagnosticVMOptions -XX:+LogCompilation