美文网首页java 内存分析
java进程 cpu load过高分析过程

java进程 cpu load过高分析过程

作者: Brave_Coder | 来源:发表于2018-02-01 15:18 被阅读51次

    1\  jps -v列出所有的java进程 , top找出cpu占用过高的对应的java 进程pid

    2\ 使用top -H -p PID 命令查看对应进程里的哪个线程占用CPU过高,取该线程pid

    3\将线程的pid 转成16进制

    4\jstack [进程pid]|grep -A 100 [线程pid的16进制]  dump出jvm该线程的后100行,或者整个输出到文件

    jstack -lpid>xxxfile

    案例分析

    现象:应用发布后,过二十分钟后load突然上升,居高不下. dump内存后没发现有内存泄漏,初步怀疑有线程在不断执行退不出.

    验证:根据上面的方法找出占用cpu最高的java线程,dump出线程的后100行发现:

    20881-thread-200" daemon prio=10 tid=0x0000000046edb800 nid=0x3bbb runnable [0x0000000044ad6000]  

       java.lang.Thread.State: RUNNABLE  

    at com.ibatis.sqlmap.engine.execution.SqlExecutor.getFirstResultSet(SqlExecutor.java:341)  

    at com.ibatis.sqlmap.engine.execution.SqlExecutor.handleMultipleResults(SqlExecutor.java:299)  

    at com.ibatis.sqlmap.engine.execution.SqlExecutor.executeQuery(SqlExecutor.java:190)  

    at com.ibatis.sqlmap.engine.mapping.statement.GeneralStatement.sqlExecuteQuery(GeneralStatement.java:205)  

    at com.ibatis.sqlmap.engine.mapping.statement.GeneralStatement.executeQueryWithCallback(GeneralStatement.java:173)  

    at com.ibatis.sqlmap.engine.mapping.statement.GeneralStatement.executeQueryForObject(GeneralStatement.java:104)  

    at com.ibatis.sqlmap.engine.impl.SqlMapExecutorDelegate.queryForObject(SqlMapExecutorDelegate.java:566)  

    at com.ibatis.sqlmap.engine.impl.SqlMapExecutorDelegate.queryForObject(SqlMapExecutorDelegate.java:541)  

    at com.ibatis.sqlmap.engine.impl.SqlMapSessionImpl.queryForObject(SqlMapSessionImpl.java:106)  

    at org.springframework.orm.ibatis.SqlMapClientTemplate$1.doInSqlMapClient(SqlMapClientTemplate.java:273)  

    at org.springframework.orm.ibatis.SqlMapClientTemplate.execute(SqlMapClientTemplate.java:209)  

    at org.springframework.orm.ibatis.SqlMapClientTemplate.queryForObject(SqlMapClientTemplate.java:271)  

    可以看到SqlExecutor.getFirstResultSet在这个地方一直处于runnable.打开源码如下:

    [java] view plain copy

    while (hasMoreResults) {  

         rs = stmt.getResultSet();  

    if (rs != null) {  

    break;  

         }  

         hasMoreResults = moveToNextResultsIfPresent(stmt);  

       }  

    debug后发现在这个地方一直死循环

    原因:review dao代码时发现一条update的操作是用selectForObject来跑的,接手过来的历史代码伤不起啊,以前跑在oracle的时候不会出现这个问题,这次去o换成mysql后这个隐藏的雷终于爆发了.把相应的select改成update问题解决.

    额外注意:问题能在测试环节发现,就不是问题,关键在于测试环节测试人员一直没发现这个问题,到线上一下子就出来了.原因有两个,一是测试环境走不到这个分支,也就是测试用例不充分;二是测试环境操作有限,死几个线程问题不大,因为测试环境设置的超时时间比较短,导致问题没有明显暴露出来,到线上一下子就出来了.

    相关文章

      网友评论

        本文标题:java进程 cpu load过高分析过程

        本文链接:https://www.haomeiwen.com/subject/hnmdzxtx.html