JDK自带工具之jstack

jstack是java虚拟机自带的一种堆栈跟踪工具。jstack位于java的bin目录下,主要利用JVM内建的指令对Java应用程序的资源和性能进行实时的命令行的监控,包括了对Heap
size和垃圾回收状况的监控。

Jstat可以用来监视VM内存内的各种堆和非堆的大小及其内存使用量。

1、Jstack命令格式

jstack [ option ] pid

2、常用参数

-F当’jstack [-l] pid’没有相应的时候强制打印栈信息

-l长列表. 打印关于锁的附加信息,例如属于java.util.concurrent的ownable synchronizers列表.

-m打印java和native c/c++框架的所有栈信息.

-h | -help打印帮助信息

pid 需要被打印配置信息的java进程id,可以用jps查询.

3、生成死锁(deadlock)的源代码

package com.jdkTools;

/**

* 简单的应用,供测试JDK自带的jstack使用 本应用会造成deadlock,可能会导致系统崩溃

* 逻辑:一旦两个线程互相等待的局面出现,死锁(deadlock)就发生了

*

* @author 范芳铭

*/

public class EasyJstack extends Thread {

private EasyJstackResourceresourceManger;//资源管理类的私有引用,通过此引用可以通过其相关接口对资源进行读写

private int a, b;// 将要写入资源的数据

public static void main(String[]args) throws Exception {

EasyJstackResourceresourceManager = new EasyJstackResource();

EasyJstack stack1 = newEasyJstack(resourceManager, 1, 2);

EasyJstack stack2 = newEasyJstack(resourceManager, 3, 4);

stack1.start();

stack2.start();

}

publicEasyJstack(EasyJstackResource resourceManager, int a, int b) {

this.resourceManger =resourceManager;

this.a = a;

this.b = b;

}

public void run() {

while (true) {

this.resourceManger.read();

this.resourceManger.write(this.a,this.b);

}

}

}

package com.jdkTools;

/**

* 简单的应用,供测试JDK自带的jstack使用 本应用会造成deadlock,可能会导致系统崩溃

* 逻辑:一旦两个线程互相等待的局面出现,死锁(deadlock)就发生了

* @author 范芳铭

*/

public class EasyJstackResource {

/**

* 管理的两个资源,如果有多个线程并发,那么就会死锁

*/

private Resource resourceA = newResource();

private Resource resourceB = newResource();

public EasyJstackResource() {

this.resourceA.setValue(0);

this.resourceB.setValue(0);

}

public int read() {

synchronized (this.resourceA){

System.out.println(Thread.currentThread().getName()

+ "线程拿到了资源 resourceA的对象锁");

synchronized (resourceB){

System.out.println(Thread.currentThread().getName()

+ "线程拿到了资源 resourceB的对象锁");

return this.resourceA.getValue()+ this.resourceB.getValue();

}

}

}

public void write(int a, int b) {

synchronized (this.resourceB){

System.out.println(Thread.currentThread().getName()

+ "线程拿到了资源 resourceB的对象锁");

synchronized(this.resourceA) {

System.out.println(Thread.currentThread().getName()

+ "线程拿到了资源 resourceA的对象锁");

this.resourceA.setValue(a);

this.resourceB.setValue(b);

}

}

}

public class Resource {

private int value;// 资源的属性

public int getValue() {

return value;

}

public void setValue(intvalue) {

this.value = value;

}

}

}

4、运行结果

Thread-0线程拿到了资源 resourceA 的对象锁

Thread-0线程拿到了资源 resourceB 的对象锁

Thread-0线程拿到了资源 resourceB 的对象锁

Thread-1线程拿到了资源 resourceA 的对象锁

应用已经被锁住了

5、用jstack进行分析

C:\Program Files\Java\jdk1.6.0_25\bin>jps -l

5204 com.jdkTools.EasyJstack

6268 sun.tools.jps.Jps

5412

C:\Program Files\Java\jdk1.6.0_25\bin>jstack 5204

2015-01-21 15:32:22

Full thread dump Java HotSpot(TM) Client VM (11.3-b02mixed mode):

…中间省略

"Signal Dispatcher" daemon prio=10tid=0x01a42000 nid=0x1a5c runnable [0x00000000..0x00000000]

java.lang.Thread.State: RUNNABLE

"Finalizer" daemon prio=8 tid=0x01a2b000nid=0x1798 in Object.wait() [0x0bc3f000..0x0bc3fa68]

java.lang.Thread.State: WAITING (on object monitor)

atjava.lang.Object.wait(Native Method)

- waitingon <0x03b50b38> (a java.lang.ref.ReferenceQueue$Lock)

atjava.lang.ref.ReferenceQueue.remove(ReferenceQueue.java:116)

- locked<0x03b50b38> (a java.lang.ref.ReferenceQueue$Lock)

atjava.lang.ref.ReferenceQueue.remove(ReferenceQueue.java:132)

atjava.lang.ref.Finalizer$FinalizerThread.run(Finalizer.java:159)

"Reference Handler" daemon prio=10tid=0x01a29c00 nid=0x1e38 in Object.wait() [0x0bbef000..0x0bbefae8]

java.lang.Thread.State: WAITING (on object monitor)

atjava.lang.Object.wait(Native Method)

- waitingon <0x03b50a40> (a java.lang.ref.Reference$Lock)

atjava.lang.Object.wait(Object.java:485)

atjava.lang.ref.Reference$ReferenceHandler.run(Reference.java:116)

- locked<0x03b50a40> (a java.lang.ref.Reference$Lock)

"VM Thread" prio=10 tid=0x01a26800 nid=0x1cecrunnable

"VM Periodic Task Thread" prio=10tid=0x01a80000 nid=0x10e0 waiting on condition

JNI global references: 594

Found one Java-level deadlock:

=============================

"Thread-1":

waiting to lockmonitor 0x01a2dea4 (object 0x03b8ed40, acom.jdkTools.EasyJstackResource$Resource),

which is held by"Thread-0"

"Thread-0":

waiting to lockmonitor 0x01a2eb3c (object 0x03b8ed30, acom.jdkTools.EasyJstackResource$Resource),

which is held by"Thread-1"

Java stack information for the threads listed above:

===================================================

"Thread-1":

atcom.jdkTools.EasyJstackResource.read(EasyJstackResource.java:27)

- waitingto lock <0x03b8ed40> (a com.jdkTools.EasyJstackResource$Resource)

- locked<0x03b8ed30> (a com.jdkTools.EasyJstackResource$Resource)

atcom.jdkTools.EasyJstack.run(EasyJstack.java:34)

"Thread-0":

atcom.jdkTools.EasyJstackResource.write(EasyJstackResource.java:42)

- waitingto lock <0x03b8ed30> (a com.jdkTools.EasyJstackResource$Resource)

- locked<0x03b8ed40> (a com.jdkTools.EasyJstackResource$Resource)

atcom.jdkTools.EasyJstack.run(EasyJstack.java:35)

Found 1 deadlock.

能够明确看到“Found one Java-level deadlock:”能够找到系统中的死锁。

6、分析结果

Java stack information for the threads listed above:

===================================================

"Thread-1":

atcom.jdkTools.EasyJstackResource.read(EasyJstackResource.java:27)

- waitingto lock <0x03b8ed40> (a com.jdkTools.EasyJstackResource$Resource)

- locked<0x03b8ed30> (a com.jdkTools.EasyJstackResource$Resource)

atcom.jdkTools.EasyJstack.run(EasyJstack.java:34)

"Thread-0":

atcom.jdkTools.EasyJstackResource.write(EasyJstackResource.java:42)

- waitingto lock <0x03b8ed30> (a com.jdkTools.EasyJstackResource$Resource)

- locked<0x03b8ed40> (a com.jdkTools.EasyJstackResource$Resource)

atcom.jdkTools.EasyJstack.run(EasyJstack.java:35)

Found 1 deadlock.

仔细看这一段文字,告诉我们 EasyJstackResource.java:27出了状况。如果出现了这种情况,我们就要从这里开始顺藤摸瓜,解决问题。

7、其他状态和简单解读

  1. 死锁,Deadlock(重点关注) 
  2. 执行中,Runnable
  3. 等待资源,Waiting on condition(重点关注)
  4. 等待获取监视器,Waiting on monitor entry(重点关注)
  5. 暂停,Suspended
  6. 对象等待中,Object.wait() 或 TIMED_WAITING
  7. 阻塞,Blocked(重点关注)  
  8. 停止,Parked
时间: 2024-10-09 19:51:35

JDK自带工具之jstack的相关文章

JDK自带工具之jmap

Jmap是JDK自带的一个轻量级小工具.位于java的bin目录下,它能够打印出某个java进程(使用pid)内存中所有'对象'的情况(如:产生那些对象,及其数量).它不仅可以输出所有内存中对象的工具,甚至可以将VM 中的heap,以二进制输出成文本.使用方法 jmap -histo pid.也可以将其保存到文本中去,在一段时间后,使用文本对比工具,可以对比出GC回收了哪些对象.还可以和jhat (Java Heap Analysis Tool)一起使用,能够以图像的形式直观的展示当前内存是否有

JDK自带工具之jhat

Jhat是JDK自带的一个轻量级小工具.jhat位于java的bin目录下,是用来分析java堆的命令,可以将堆中的对象以html的形式显示出来,包括对象的数量,大小等等,并支持对象查询语言,jhat工具一般和jmap工具配合使用. 1.Jstat命令格式 Jhat dumpFile 2.使用步骤 第一步:导出堆 第二步:分析堆文件 第三步:查看html 有时dump出来的堆很大,在启动时会报堆空间不足的错误,可以使用如下参数: jhat -J-Xmx512m <heap dump file>

JDK自带工具之jstat

Jstat是JDK自带的一个轻量级小工具.全称"Java Virtual Machine statistics monitoring tool". Jstat位于java的bin目录下,主要利用JVM内建的指令对Java应用程序的资源和性能进行实时的命令行的监控,包括了对Heap size和垃圾回收状况的监控. Jstat可以用来监视VM内存内的各种堆和非堆的大小及其内存使用量. 1.Jstat命令格式 jstat [optionsvmid [interval[s|ms]  [coun

JDK自带工具之jinfo

Jinfo是JDK自带Java配置信息工具.位于java的bin目录下,jinfo的作用是实时地查看和调整虚拟机的各项参数,虽然使用Jps命令的-v参数可以查看虚拟机启动时显示指定的参数列表.但是如果想要知道没有被明确指出的系统默认值,就需要用到jinfo. Jinfo还能够修改一部分运行期间能够调整的虚拟机参数. 1.Jinfo命令格式 jinfo [ option ] pid 2.常用参数 Usage: jinfo <option> <pid> (to connect to a

JDK自带工具之JPS

jps(Java Virtual Machine Process Status Tool)是JDK提供的一个显示当前所有java进程pid的命令,简单实用,非常适合在linux/unix/windows平台上简单察看当前java进程的一些简单情况. jps它的作用是显示当前JAVA进程的id号,并可通过opt来查看这些进程的详细启动参数. jps位于jdk的bin目录下. 1.JPS命令格式 jps [ options ] [ hostid ]  2.常用参数 -q 只显示pid,不显示clas

JDK 自带工具试用(一)

简述: 运维监控会用到JDK的小工具 说明: 1. jps 用来查看当前运行的Java进程 我在eclipse中起了一个web 应用 或者用jps -l 可以查看的更清楚一点 jps -v 看到10376之后用taskkill指令关闭 2. jstat 虚拟机统计信息监视工具 先用jps查看当前启动的应用 于是使用 [plain] view plaincopy cd C:\Users\Administrator\Desktop\jvm monitor gcutil 监视Java堆状况,主要关注已

如何使用JDK自带工具JConsole

前言 jconsole.exe为jdk自带的监控工具,操作简便,比较容易上手.jconsole可以实时的监控Java程序在运行过程中的内存,cpu,线程的使用情况,并可以对加载的相关类进行分析.下面开始一起看看如何使用jconsole吧! 打开jconsole步骤: 1.首先进入到jdk的安装目录bin目录下:双击"jconsole.exe"打开jconsole 双击jconsole打开,并进入管理控制页面,如果本地有正在运行的Java进程的话会自动检测出来:这里分为监控本地进程或远程

JDK自带工具列表

JDK是一个功能强大的Java开发套装,它不仅仅为我们提供了Java运行环境,还给开发人员提供了许多有用的开发组件(位于bin目录中,如下图所示).仅仅使用JDK,就能够解决我们在Java开发过程中遇到的许多问题. 下图是JDK1.7版本下的工具列表:后续会针对每一个工具 下面,我们就按照工具文件名称的英文顺序来逐一介绍JDK内置的工具. 工具名称 描述 appletviewer.exe 用于运行并浏览applet小程序. apt.exe 注解处理工具(Annotation Processing

第七章:JDK自带工具

JDK内置的工具 工具名称 描述 appletviewer.exe 用于运行并浏览applet小程序. apt.exe 注解处理工具(Annotation Processing Tool),主要用于注解处理. extcheck.exe 扩展检测工具,主要用于检测指定jar文件与当前已安装的Java SDK扩展之间是否存在版本冲突. idlj.exe IDL转Java编译器(IDL-to-Java Compiler),用于为指定的IDL文件生成Java绑定.IDL意即接口定义语言(Interfac