初探jstack

作者: poppindevil | 来源:发表于2017-03-30 01:11 被阅读130次

    概述

    最近项目在接入一定数量的设备后,由于链接比之前更多,数据交互更为频繁,也暴露出一些之前没有碰到的问题。服务总是莫名其妙的假死:页面能访问,TCP端口正常,能新建链接,但是解析数据包的线程全部挂掉,导致设备无法上线。后来发现有jstack这个工具可以用来辅助定位问题。

    jstack是什么

    jstack是JVM提供的一个工具,能够查询到当前JVM中每条线程正在执行的方法堆栈信息。这些信息可以辅助定位代码中的问题,例如:线程间的死锁,死循环,高耗时导致的长时间等待。

    如何使用

    jstack基本语法是jstack [option] pid,如果是64位机器,需要指定选项-J-d64。pid通过ps -ef|grep java或者从jdk5.0以后就有的jps -v来获得。命令很简单,很容易就能拿到当前运行的JVM中的线程dump信息。

    分析dump file

    JVM中大体可以分为两类线程:
    1.JVM内部的后台线程,例如垃圾回收。而这些线程在JVM初始化的时候就有;

    2017-03-29 23:57:14
    Full thread dump Java HotSpot(TM) 64-Bit Server VM (24.79-b02 mixed mode):
    
    "Attach Listener" daemon prio=10 tid=0x00007fcf40040800 nid=0x34e3 waiting on condition [0x0000000000000000]
       java.lang.Thread.State: RUNNABLE
    
    "GC Daemon" daemon prio=10 tid=0x00007fcf684d0000 nid=0x1b13 in Object.wait() [0x00007fcf6c14a000]
       java.lang.Thread.State: TIMED_WAITING (on object monitor)
        at java.lang.Object.wait(Native Method)
        - waiting on <0x00000000c40ef7a0> (a sun.misc.GC$LatencyLock)
        at sun.misc.GC$Daemon.run(GC.java:117)
        - locked <0x00000000c40ef7a0> (a sun.misc.GC$LatencyLock)
    
    "Service Thread" daemon prio=10 tid=0x00007fcf680a5800 nid=0x1b0f runnable [0x0000000000000000]
       java.lang.Thread.State: RUNNABLE
    
    "C2 CompilerThread1" daemon prio=10 tid=0x00007fcf680a3000 nid=0x1b0e waiting on condition [0x0000000000000000]
       java.lang.Thread.State: RUNNABLE
    
    "C2 CompilerThread0" daemon prio=10 tid=0x00007fcf680a0000 nid=0x1b0d waiting on condition [0x0000000000000000]
       java.lang.Thread.State: RUNNABLE
    
    "JDWP Event Helper Thread" daemon prio=10 tid=0x00007fcf6809d800 nid=0x1b0c runnable [0x0000000000000000]
       java.lang.Thread.State: RUNNABLE
    
    "JDWP Transport Listener: dt_socket" daemon prio=10 tid=0x00007fcf6809a000 nid=0x1b0b runnable [0x0000000000000000]
       java.lang.Thread.State: RUNNABLE
    
    "Signal Dispatcher" daemon prio=10 tid=0x00007fcf6808d000 nid=0x1b0a runnable [0x0000000000000000]
       java.lang.Thread.State: RUNNABLE
    
    "Finalizer" daemon prio=10 tid=0x00007fcf6806d800 nid=0x1b09 in Object.wait() [0x00007fcf6cfea000]
       java.lang.Thread.State: WAITING (on object monitor)
        at java.lang.Object.wait(Native Method)
        at java.lang.ref.ReferenceQueue.remove(ReferenceQueue.java:135)
        - locked <0x00000000c42a4fe8> (a java.lang.ref.ReferenceQueue$Lock)
        at java.lang.ref.ReferenceQueue.remove(ReferenceQueue.java:151)
        at java.lang.ref.Finalizer$FinalizerThread.run(Finalizer.java:209)
    

    2.用户线程,也就是项目中对应的线程,这类线程才是我们要关注的重点。

    "NioReadThread1" daemon prio=10 tid=0x0000000003595000 nid=0x1b23 in Object.wait() [0x00007fcf27556000]
       java.lang.Thread.State: WAITING (on object monitor)
        at java.lang.Object.wait(Native Method)
        at java.lang.Object.wait(Object.java:503)
        at cn.com.enplus.charge.communicate.tcp.NioTcpReader.run(NioTcpReader.java:42)
        - locked <0x00000000c62ee040> (a java.util.LinkedList)
    

    在项目的运行过程中,通过查看当前线程的CPU使用率,CPU使用耗时来去定位线程所对应的具体代码位置。

    1. 通过top -Hp pid来查看当前程序中的线程信息,如图:
      线程信息
      图中可以看到PID为7011的线程最耗时,通过命令printf "%x\n" 7011转换为16进制结果:1b63。然后去dump file中查找对应的id,结果如下图:
      1b63搜索结果
      可以看到这是一个Quartz定时任务,根据项目中代码实际情况发现的确是个耗时任务。

    相关文章

      网友评论

        本文标题:初探jstack

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