JVM 调优之 CPU 高占用问题

简介: jstack(Stack Trace for Java) 命令用于生成当前时刻的线程快照(一般称为 threaddump 文件)。

jstack 工具


jstack(Stack Trace for Java) 命令用于生成当前时刻的线程快照(一般称为 threaddump 文件)。


线程快照就是当前虚拟机每条线程正在执行的方法堆栈集合,生成线程快照的目的通常是定位线程出现长时间停顿的原因,如线程间死锁,死循环、请求外部资源导致的长时间挂起等,都是导致线程长时间停顿的原因。


线程出现停顿是通过 jstack 来查看各个线层呢的调用堆栈,就可以获知没有响应的线程到底在后台做什么,或者等待什么资源。


jstack 命令格式:


jstack [option] vmid


下面我们就开始实践,说下环境:jdk 1.8, 操作系统 ubantu 20.04


排查 CPU 高占用问题


我们先写一个简单的死循环程序,来模拟 CPU 高占用问题。


测试代码如下:


public class MathTest {
    public int compute() {
        int a = 1026;
        int b = 2018;
        return (a + b) * 10;
    }
    public static void main(String[] args) {
        MathTest math = new MathTest();
        //System.out.println(math.compute());
        while (true) {
            math.compute();
        }
    }
}


编译和执行命令如下:


// 编译
javac MathTest.java
// 后台执行
java MathTest &


核心步骤


  1. jps 打印 Java 进程(查看是否启动)


zhengsh@zhengsh:/opt/apps$ jps
4541 MathTest
4559 Jps


  1. top 命令,查询指定进程的线程信息,然后通过 shift + p 通过 cpu 占用排序


top -Hp 4541


结果如下:


image.png


找到高占用 cpu 的线程 id 4542


  1. 通过 pid 转化为 16 进制


printf "%x\n" 4542
11be


  1. 查询所在的后面 30 行


jstack 4541|grep 11be -A 30
// 显示结果如下:
"main" #1 prio=5 os_prio=0 tid=0x00007f8efc00a800 nid=0x11be runnable [0x00007f8f016a3000]
   java.lang.Thread.State: RUNNABLE
  at MathTest.main(MathTest.java:13)
"VM Thread" os_prio=0 tid=0x00007f8efc074000 nid=0x11c1 runnable 
"GC task thread#0 (ParallelGC)" os_prio=0 tid=0x00007f8efc01f800 nid=0x11bf runnable 
"GC task thread#1 (ParallelGC)" os_prio=0 tid=0x00007f8efc021000 nid=0x11c0 runnable 
"VM Periodic Task Thread" os_prio=0 tid=0x00007f8efc0d9000 nid=0x11c8 waiting on condition 
JNI global references: 5


我们可以查询到 MathTest 类 13 行正在运行,在回看代码:


image.png


这里是有死循环调用,导致 CPU 过高。问题找到,解决完毕。


参考资料


  • 《深入理解 JVM 虚拟机 第四版》周志明


相关文章
|
存储 设计模式 监控
快速定位并优化CPU 与 JVM 内存性能瓶颈
本文介绍了 Java 应用常见的 CPU & JVM 内存热点原因及优化思路。
1186 166
|
存储 监控 算法
jvm-性能调优(二)
jvm-性能调优(二)
|
监控 Java 编译器
Java虚拟机调优指南####
本文深入探讨了Java虚拟机(JVM)调优的精髓,从内存管理、垃圾回收到性能监控等多个维度出发,为开发者提供了一系列实用的调优策略。通过优化配置与参数调整,旨在帮助读者提升Java应用的运行效率和稳定性,确保其在高并发、大数据量场景下依然能够保持高效运作。 ####
368 58
|
11月前
|
存储 设计模式 监控
如何快速定位并优化CPU 与 JVM 内存性能瓶颈?
如何快速定位并优化CPU 与 JVM 内存性能瓶颈?
325 0
如何快速定位并优化CPU 与 JVM 内存性能瓶颈?
|
监控 架构师 Java
Java虚拟机调优的艺术:从入门到精通####
本文作为一篇深入浅出的技术指南,旨在为Java开发者揭示JVM调优的神秘面纱,通过剖析其背后的原理、分享实战经验与最佳实践,引领读者踏上从调优新手到高手的进阶之路。不同于传统的摘要概述,本文将以一场虚拟的对话形式,模拟一位经验丰富的架构师向初学者传授JVM调优的心法,激发学习兴趣,同时概括性地介绍文章将探讨的核心议题——性能监控、垃圾回收优化、内存管理及常见问题解决策略。 ####
|
存储 缓存 监控
Docker容器性能调优的关键技巧,涵盖CPU、内存、网络及磁盘I/O的优化策略,结合实战案例,旨在帮助读者有效提升Docker容器的性能与稳定性。
本文介绍了Docker容器性能调优的关键技巧,涵盖CPU、内存、网络及磁盘I/O的优化策略,结合实战案例,旨在帮助读者有效提升Docker容器的性能与稳定性。
1281 7
|
算法 Java
JVM进阶调优系列(4)年轻代和老年代采用什么GC算法回收?
本文详细介绍了JVM中的GC算法,包括年轻代的复制算法和老年代的标记-整理算法。复制算法适用于年轻代,因其高效且能避免内存碎片;标记-整理算法则用于老年代,虽然效率较低,但能有效解决内存碎片问题。文章还解释了这两种算法的具体过程及其优缺点,并简要提及了其他GC算法。
 JVM进阶调优系列(4)年轻代和老年代采用什么GC算法回收?
|
Arthas 监控 Java
JVM进阶调优系列(9)大厂面试官:内存溢出几种?能否现场演示一下?| 面试就那点事
本文介绍了JVM内存溢出(OOM)的四种类型:堆内存、栈内存、元数据区和直接内存溢出。每种类型通过示例代码演示了如何触发OOM,并分析了其原因。文章还提供了如何使用JVM命令工具(如jmap、jhat、GCeasy、Arthas等)分析和定位内存溢出问题的方法。最后,强调了合理设置JVM参数和及时回收内存的重要性。
|
监控 Java 测试技术
Elasticsearch集群JVM调优垃圾回收器的选择
Elasticsearch集群JVM调优垃圾回收器的选择
483 1