C2 CompilerThread 长时间占用CPU 100% 解决方案

问题描述

        近期在项目维护中,生产机器存在服务器的CPU占比很高的问题,经过确证是C2 CompilerThread CPU占比很高。C2线程调用栈如下所示:

...
Thread 1 (process 68):                                                                                                                                                                                                           
#0  0xf6abda90 in MemBarCPUOrderNode::Opcode() const () from /usr/java/jdk1.8.0_152/jre/lib/i386/server/libjvm.so                                                                                                                
#1  0xf6e8462c in MemNode::can_see_stored_value(Node*, PhaseTransform*) const () from /usr/java/jdk1.8.0_152/jre/lib/i386/server/libjvm.so                                                                                       
#2  0xf6e84afb in LoadNode::Value(PhaseTransform*) const () from /usr/java/jdk1.8.0_152/jre/lib/i386/server/libjvm.so                                                                                                            
#3  0xf6f5368a in PhaseIterGVN::transform_old(Node*) () from /usr/java/jdk1.8.0_152/jre/lib/i386/server/libjvm.so                                                                                                                
#4  0xf6f51084 in PhaseIterGVN::optimize() () from /usr/java/jdk1.8.0_152/jre/lib/i386/server/libjvm.so                                                                                                                          
#5  0xf6aece24 in Compile::Optimize() () from /usr/java/jdk1.8.0_152/jre/lib/i386/server/libjvm.so                                                                                                                               
#6  0xf6aeea0a in Compile::Compile(ciEnv*, C2Compiler*, ciMethod*, int, bool, bool, bool) () from /usr/java/jdk1.8.0_152/jre/lib/i386/server/libjvm.so                                                                           
#7  0xf6a43a4d in C2Compiler::compile_method(ciEnv*, ciMethod*, int) () from /usr/java/jdk1.8.0_152/jre/lib/i386/server/libjvm.so                                                                                                
#8  0xf6af92b1 in CompileBroker::invoke_compiler_on_method(CompileTask*) () from /usr/java/jdk1.8.0_152/jre/lib/i386/server/libjvm.so                                                                                            
#9  0xf6afa0c7 in CompileBroker::compiler_thread_loop() () from /usr/java/jdk1.8.0_152/jre/lib/i386/server/libjvm.so                                                                                                             
#10 0xf7031f48 in compiler_thread_entry(JavaThread*, Thread*) () from /usr/java/jdk1.8.0_152/jre/lib/i386/server/libjvm.so                                                                                                       
#11 0xf703cadf in JavaThread::thread_main_inner() () from /usr/java/jdk1.8.0_152/jre/lib/i386/server/libjvm.so                                                                                                                   
#12 0xf703cc5b in JavaThread::run() () from /usr/java/jdk1.8.0_152/jre/lib/i386/server/libjvm.so                                                                                                                                 
#13 0xf6f0c179 in java_start(Thread*) () from /usr/java/jdk1.8.0_152/jre/lib/i386/server/libjvm.so                                                                                                                               
#14 0xf77b8b2c in start_thread () from /lib/libpthread.so.0                                                                                                                                                                      
#15 0xf76cf17e in clone () from /lib/libc.so.6

可以看出cpu一直在MemNode::can_see_stored_value函数内循环。

问题解决思路

        完全禁用C2编译器。我们可以通过提供-XX:TieredStopAtLevel=1 Java选项来实现这一点。这个选项可以解决空闲状态下的CPU消耗,因此它验证了我们关于C2导致问题的假设。然而,这种变通方法可能对生产系统无效和/或不可取,因为它禁用了复杂的C2编译器,因此可能会导致应用程序性能大大降低。

class ciMethod : public ciMetadata {
...
private:  // General method information.
  ciFlags          _flags;
  ciSymbol*        _name;
  ciInstanceKlass* _holder;
  ciSignature*     _signature;
...
}

        结合openjdk中C2编译器源码观察上图,在第7帧中有ciMethod参数,我们可以抓取core文件,通过gdb和hsdb命令分析core.dump文件,获取compile_method()函数的入参。通过该入参可知具体是在哪个方法进行C2编译时导致死循环。可通过以下java选项将该方法添加到排除列表中。

-XX:CompileCommand=XXXXXX::xxxxxx

        

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值