JVM调优工具之jstack

简介: JVM调优工具之jstack

jstack(Stack Trace for Java)命令用于生成虚拟机当前时刻的线程快照(一般称为threaddump或者javacore文件)。线程快照就是当前虚拟机内每一条线程正在执行的方法堆栈的集合,生成线程快照的主要目的是定位线程出现长时间停顿的原因,如线程间死锁、死循环、请求外部资源导致的长时间等待等都是导致线程长时间停顿的常见原因。


线程出现停顿的时候通过jstack来查看各个线程的调用堆栈,就可以知道没有响应的线程到底在后台做些什么事情或者等待着什么资源。


jstack命令格式

jstack [option] vmid

option选项如下:

选项 作用
-F 当正常输出的请求不被响应时,强制输出线程堆栈
-l 除堆栈外,显示关于锁的附加信息
-m 如果调用到本地方法的话,可以显示C/C++的堆栈

可以不用选项直接使用jstack pid查看堆栈dump。

jstack命令生成的thread dump信息包含了JVM中所有存活的线程,为了分析指定线程,必须找出对应线程的调用栈,应该如何找?


已经获取到了占用cpu资源较高的线程pid,将该pid转成16进制的值,在thread dump中每个线程都有一个nid,找到对应的nid即可;隔段时间再执行一次stack命令获取thread dump,区分两份dump是否有差别。


通过thread dump分析线程状态

大多数情况下会基于thead dump分析当前各个线程的运行情况,如是否存在死锁、是否存在一个线程长时间持有锁不放等等。


在dump中,线程一般存在如下几种状态:

  • RUNNABLE,线程处于执行中
  • BLOCKED,线程被阻塞
  • WAITING,线程正在等待

测试代码如下:

public class JstackCase {
    public static Executor executor = Executors.newFixedThreadPool(5);
    public static Object lock = new Object();
    public static void main(String[] args){
        Task task1=new Task();
        Task task2=new Task();
        executor.execute(task1);
        executor.execute(task2);
    }
    //如果不用static修饰,则必须如 Task task1=new JstackCase().new Task();
    static class Task implements Runnable{
        @Override
        public void run() {
            synchronized (lock){
                calculate();
            }
        }
        public void calculate(){
            int i=0;
            while (true){
                i++;
            }
        }
    }
}


多线程竞争synchronized锁

很明显:线程1获取到锁,处于RUNNABLE状态,线程2处于BLOCK状态


locked <0x00000000d5fbd698>说明线程1对地址为<0x00000000d5fbd698>对象进行了加锁;

waiting to lock <0x00000000d5fbd698>说明线程2在等待地址为<0x00000000d5fbd698>对象上的锁;

通过wait挂起线程


线程1和2都处于WAITING状态:


线程1和2都是先locked <0x00000000d5fbd6c8>,再waiting on <0x00000000d5fbd6c8>。之所以先锁再等同一个对象,是因为wait方法需要先通过synchronized获得该地址对象的monitor;

waiting on <0x00000000d5fbd6c8>说明线程执行了wait方法之后,释放了monitor,进入到"Wait Set"队列,等待其它线程执行地址为 <0x00000000d5fbd6c8>对象的notify方法,并唤醒自己。

线程pid如何获取


线程pid如何获取

Linux下可以使用top命令,Windows下可以使用任务管理器查看。

目录
相关文章
|
14天前
|
运维 Java Shell
手工触发Full GC:JVM调优实战指南
本文是关于Java应用性能调优的指南,重点介绍了如何使用`jmap`工具手动触发Full GC。Full GC是对堆内存全面清理的过程,通常在资源紧张时进行以缓解内存压力。文章详细阐述了Full GC的概念,并提供了两种使用`jmap`触发Full GC的方法:通过`-histo:live`选项获取存活对象统计信息,或使用`-dump`选项生成堆转储文件以分析内存状态。同时,文中也提醒注意手动Full GC可能带来的性能开销,建议在生产环境中谨慎操作。
|
20小时前
|
Arthas 监控 数据可视化
JVM监控工具
Arthas 是一款线上监控诊断产品,通过全局视角实时查看应用 load、内存、gc、线程的状态信息,并能在不修改应用代码的情况下,对业务问题进行诊断,包括查看方法调用的出入参、异常,监测方法执行耗时,类加载信息等,大大提升线上问题排查效率。
4 0
|
4天前
|
监控 算法 Java
JVM调优-简介(一)
JVM调优-简介(一)
5 0
|
1月前
|
设计模式 NoSQL Java
京东面试:如何进行JVM调优?
JVM 调优是一个很大的话题,在回答“如何进行 JVM 调优?”之前,首先我们要回答一个更为关键的问题,那就是,我们为什么要进行 JVM 调优? 只有知道了为什么要进行 JVM 调优之后,你才能准确的回答出来如何进行 JVM 调优? 要进行 JVM 调优无非就是以下两种情况: 1. **目标驱动型的 JVM 调优**,如,我们是为了最短的停顿时间所以要进行 JVM 调优,或者是我们为了最大吞吐量所以要进行 JVM 调优等。 2. **问题驱动型的 JVM 调优**,因为生产环境出现了频繁的 FullGC 了,导致程序执行变慢,所以我们要进行 JVM 调优。 所以,针对不同的 JVM 调
39 1
|
19天前
|
Java 应用服务中间件 Linux
Tomcat 调优及 JVM 参数优化
Tomcat 调优及 JVM 参数优化
|
27天前
|
存储 算法 Java
JVM性能调优:内存模型及垃圾收集算法
JVM性能调优:内存模型及垃圾收集算法
31 0
|
1月前
|
Arthas 人工智能 监控
JVM工作原理与实战(三十五):性能调优
JVM作为Java程序的运行环境,其负责解释和执行字节码,管理内存,确保安全,支持多线程和提供性能监控工具,以及确保程序的跨平台运行。本文主要介绍了性能调优、性能调优案例等内容。
35 1
|
1月前
|
Prometheus 监控 Cloud Native
JVM工作原理与实战(三十三):监控GC过程的工具
JVM作为Java程序的运行环境,其负责解释和执行字节码,管理内存,确保安全,支持多线程和提供性能监控工具,以及确保程序的跨平台运行。本文主要介绍了jstat工具、VisualVM插件、Prometheus + Grafana、GC日志等内容。
42 0
|
1月前
|
监控 负载均衡 算法
JVM工作原理与实战(三十二):GC调优
JVM作为Java程序的运行环境,其负责解释和执行字节码,管理内存,确保安全,支持多线程和提供性能监控工具,以及确保程序的跨平台运行。本文主要介绍了GC调优、GC调优的核心指标等内容。
27 0
|
1月前
|
Arthas Prometheus 监控
JVM工作原理与实战(二十九):监控内存泄漏的工具
JVM作为Java程序的运行环境,其负责解释和执行字节码,管理内存,确保安全,支持多线程和提供性能监控工具,以及确保程序的跨平台运行。本文主要介绍了解决内存溢出的步骤、Top命令、VisualVM、Arthas、Prometheus + Grafana等内容。
62 0