万隆的笔记 万隆的笔记
博文索引
笔试面试
  • 在线学站

    • 菜鸟教程 (opens new window)
    • 入门教程 (opens new window)
    • Coursera (opens new window)
  • 在线文档

    • w3school (opens new window)
    • Bootstrap (opens new window)
    • Vue (opens new window)
    • 阿里开发者藏经阁 (opens new window)
  • 在线工具

    • tool 工具集 (opens new window)
    • bejson 工具集 (opens new window)
    • 文档转换 (opens new window)
  • 更多在线资源
  • Changlog
  • Aboutme
GitHub (opens new window)
博文索引
笔试面试
  • 在线学站

    • 菜鸟教程 (opens new window)
    • 入门教程 (opens new window)
    • Coursera (opens new window)
  • 在线文档

    • w3school (opens new window)
    • Bootstrap (opens new window)
    • Vue (opens new window)
    • 阿里开发者藏经阁 (opens new window)
  • 在线工具

    • tool 工具集 (opens new window)
    • bejson 工具集 (opens new window)
    • 文档转换 (opens new window)
  • 更多在线资源
  • Changlog
  • Aboutme
GitHub (opens new window)
  • 大纲

  • 走近Java

  • 内存与垃圾回收

  • 字节码与类加载

  • 性能监控与调优

  • 监控与性能调优案例

    • JVM监控与性能调优案例概述
    • Tomcat堆溢出分析
    • 堆溢出
    • 方法区溢出
    • GC overhead limit exceeded
    • 线程溢出
    • 调整堆大小提高服务的吞吐量
    • JVM优化之JIT优化
    • 合理配置堆内存
    • CPU占用很高排查方案
      • 案例演示
      • 问题分析
      • 解决
    • G1并发执行的线程数对性能的影响
    • 调整垃圾回收器提高服务的吞吐量
    • 日均百万级订单交易系统如何设置JVM参数
    • 内存泄漏与内存溢出
  • Java虚拟机
  • 监控与性能调优案例
2022-03-19
目录

CPU占用很高排查方案

# CPU占用很高排查方案

说明:一般CPU占用很高是由于线程并发过程中,导致的线程阻塞、死锁等等。设计到线程的测试建议放大虚拟机中执行。

排查的过程,主要是使用到了jstack命令。

# 案例演示

死锁代码:

public class JstackDeadLockDemo {
    /**
     * 必须有两个可以被加锁的对象才能产生死锁,只有一个不会产生死锁问题
     */
    private final Object obj1 = new Object();
    private final Object obj2 = new Object();

    public static void main(String[] args) {
        new JstackDeadLockDemo().testDeadlock();
    }

    private void testDeadlock() {
        Thread t1 = new Thread(() -> calLock_Obj1_First());
        Thread t2 = new Thread(() -> calLock_Obj2_First());
        t1.start();
        t2.start();
    }

    /**
     * 先synchronized  obj1,再synchronized  obj2
     */
    private void calLock_Obj1_First() {
        synchronized (obj1) {
            sleep();
            System.out.println("已经拿到obj1的对象锁,接下来等待obj2的对象锁");
            synchronized (obj2) {
                sleep();
            }
        }
    }

    /**
     * 先synchronized  obj2,再synchronized  obj1
     */
    private void calLock_Obj2_First() {
        synchronized (obj2) {
            sleep();
            System.out.println("已经拿到obj2的对象锁,接下来等待obj1的对象锁");
            synchronized (obj1) {
                sleep();
            }
        }
    }

    /**
     * 为了便于让两个线程分别锁住其中一个对象,
     * 一个线程锁住obj1,然后一直等待obj2,
     * 另一个线程锁住obj2,然后一直等待obj1,
     * 然后就是一直等待,死锁产生
     */
    private void sleep() {
        try {
            Thread.sleep(100);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}

把代码上传到Linux系统进行编译运行执行,如果linux报错如下:

Error: Could not find or load main class JstackDeadLockDemo

解决方案:在系统的etc/profile或者用户的~/.profile中的增加当前目录的配置,即.:

export CLASSPATH=.:$JAVA_HOME/lib/tools.jar

此外,记得删除源码的package路径。运行结果:

perf_case4_1.png

可以看到,程序依然处于运行状态,现在我们知道是线程死锁造成的问题。

# 问题分析

如果是生产环境的话,怎么样才能发现目前程序有问题呢?我们可以推导一下,如果线程死锁,那么线程一直在占用CPU,这样就会导致CPU一直处于一个比较高的占用率。所示我们解决问题的思路应该是:

  1. 首先查看Java进程ID(jps、jcmd命令)
  2. 根据进程 ID 检查当前使用异常线程的pid (top -Hp ID,根据进程 ID 检查当前使用异常线程的pid)
  3. 把线程pid变为16进制如 31695 -> 7bcf 然后得到0x7bcf
  4. jstack <pid> | grep -A20 0x7bcf 得到相关进程的代码

执行1、2步如下图,可以看得出来当前占用CPU比较高的线程ID是34864,转换为16进制 (opens new window)为:0x8830(后面dump线程日志会使用)

perf_case4_2.png

鉴于我们当前代码量比较小,线程也比较少,所以我们就把所有的信息全部导出来:jstack 34864 > jstack.log。打开jstack.log文件查找一下刚刚我们转换完的16进制线程ID,0x8830是否存在 :

perf_case4_3.png

可以看的出来jstack命令生成的thread dump信息包含了JVM中所有存活的线程,里面确实是存在我们定位到的线程 ID ,在thread dump中每个线程都有一个nid,在nid=0x8830的线程调用栈中,我们发现两个线程在互相等待对方释放资源:

perf_case4_4.png

到此就可以检查对应的代码是否有问题,也就定位到我们的死锁问题。

xx大厂问题排查过程

......
4、ps aux | grep java 查看到当前Java进程使用cpu、内存、磁盘的情况获取使用量异常的进程
5、top -Hp 进程pid 检查当前使用异常线程的pid
6、把线程pid变为16进制如 31695 - 》 7bcf 然后得到0x7bcf
7、jstack 进程的pid | grep -A20 0x7bcf 得到相关进程的代码

# 解决

调整锁的顺序,保持一致或者采用定时锁,一段时间后,如果还不能获取到锁就释放自身持有的所有锁。

#JVM监控与性能调优案例
上次更新: 5/28/2023, 10:57:53 PM
G1并发执行的线程数对性能的影响

G1并发执行的线程数对性能的影响→

最近更新
01
2025
01-15
02
Elasticsearch面试题
07-17
03
Elasticsearch进阶
07-16
更多文章>
Theme by Vdoing
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式