zoukankan      html  css  js  c++  java
  • Java 问题定位工具 ——jstack

    简介

    jstack 主要用于生成虚拟机当前时刻的「线程快照」。线程快照是当前 Java 虚拟机每一条线程正在执行的方法堆栈的集合。

    生成线程快照的主要目的是用于定位线程出现长时间停顿的原因,如线程间死锁、死循环、请求外部资源导致长时间等待。

    基础

    线程的几种状态

    • NEW,未启动的。不会出现在Dump中。
    • RUNNABLE,在虚拟机内执行的。
    • BLOCKED,受阻塞并等待监视器锁。
    • WATING,无限期等待另一个线程执行特定操作。
    • TIMED_WATING,有时限的等待另一个线程的特定操作。
    • TERMINATED,已退出的。

    调用修饰

    表示线程在方法调用时,额外的重要的操作。线程 Dump 分析的重要信息。修饰上方的方法调用。

    • locked <地址> 目标:使用 synchronized 申请对象锁成功,监视器的拥有者。
    • waiting to lock <地址> 目标:使用 synchronized 申请对象锁未成功,在迚入区等待。
    • waiting on <地址> 目标:使用 synchronized 申请对象锁成功后,释放锁幵在等待区等待。
    • parking to wait for <地址> 目标

    死锁

    所谓死锁: 是指两个或两个以上的进程在执行过程中,由于竞争资源或者由于彼此通信而造成的一种阻塞的现象,若无外力作用,它们都将无法推进下去。此时称系统处于死锁状态或系统产生了死锁,这些永远在互相等待的进程称为死锁进程。 说白了,我现在想吃鸡蛋灌饼,桌子上放着鸡蛋和饼,但是我和我的朋友同时分别拿起了鸡蛋和病,我手里拿着鸡蛋,但是我需要他手里的饼。他手里拿着饼,但是他想要我手里的鸡蛋。就这样,如果不能同时拿到鸡蛋和饼,那我们就不能继续做后面的工作(做鸡蛋灌饼)。所以,这就造成了死锁

    线程 Dump 分析

    • 结合代码阅读的推理。需要线程 Dump 和源码的相互推导和印证。
    • 造成 Bug 的根源往往会在调用栈上直接体现,一定格外注意线程当前调用之前的所有调用

    常用参数

    想要学习一个命令,先来看看帮助,使用 jstack -help查看帮助:

    $ jstack --help
    Usage:
        jstack [-l] <pid>
            (to connect to running process)
        jstack -F [-m] [-l] <pid>
            (to connect to a hung process)
        jstack [-m] [-l] <executable> <core>
            (to connect to a core file)
        jstack [-m] [-l] [server_id@]<remote server IP or hostname>
            (to connect to a remote debug server)
    
    Options:
        -F  to force a thread dump. Use when jstack <pid> does not respond (process is hung)
        -m  to print both java and native frames (mixed mode)
        -l  long listing. Prints additional information about locks
        -h or -help to print this help message
    
    • jstack 8005(jps 命令找到了进程的 pid):

    使用命令打印堆栈很简单,但是通过堆栈文件定位问题,需要很深厚的内功,这也是体现一个程序员的价值的一个方面。

    使用 top 命令,看看是哪个线程占用的 cpu 最多,一般使用 top -Hp <pid>

    经验

    • wait on monitor entry: 被阻塞的,肯定有问题
    • runnable : 注意IO线程
    • in Object.wait(): 注意非线程池等待
    • 线程状态为 RUNNABLE。 调用栈在 SocketInputStreamSocketImpl 上,socketRead0 等方法。 调用栈包含了 jdbc 相关的包。很可能发生了数据库死锁。
    • 虚拟机执行Full GC时,会阻塞所有的用户线程。因此,即时获取到同步锁的线程也有可能被阻塞。 在查看线程 Dump 时,首先查看内存使用情况

    总结

    jstack 命令主要用来查看 Java 线程的调用堆栈的,可以用来分析线程问题(如死锁)

    参考

  • 相关阅读:
    [ZJOI2007]时态同步 题解
    Xposed 在android 6.0上报couldn't load class,找不到xposed_init中配置的入口类
    微信小程序http 400问题
    在Mac上 python中使用tesseract OCR (Pytesser) 识别图片中的文字
    微信小游戏跳一跳简单手动外挂(基于adb 和 python)
    第一个微信小程序踩的几个小坑
    android studio/Intellij IDEA(MAC OSX)中android模拟器无法启动的一种原因
    【转载】word2vec原理推导与代码分析
    HTTP Get Post究竟有哪些区别
    初试kotlin:用Kotlin开发桌面/CommandLine 工具
  • 原文地址:https://www.cnblogs.com/michael-xiang/p/10779720.html
Copyright © 2011-2022 走看看