Dump

  Dump文件是进程的内存镜像。可以把程序的执行状态通过调试器保存到dump文件中。Dump文件一般用来给驱动程序编写人员调试驱动程序用的,在java中用来分析正在运行的程序在内存中的堆栈信息。

jstack

  Jstack是Jdk自带的线程(栈)跟踪工具,主要用来查看Java线程的调用堆栈,可以用来分析线程问题(如死锁)。可根据指定java进程ID打印指定Java进程的线程堆栈信息。可以定位到线程阻塞、死循环、死锁等源头代码,java程序员必会技能之一。

  用法很简单:jstack pid,一般不加参数直接用就行

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可以针对活着的进程做本地的或远程的线程dump或针对core文件做线程dump。jstack用于生成java虚拟机当前时刻的线程快照。线程快照是当前java虚拟机内每一条线程正在执行的方法堆栈的集合,生成线程快照的主要目的是定位线程出现长时间停顿的原因,如线程间死锁、死循环、请求外部资源导致的长时间等待等。 线程出现停顿的时候通过jstack来查看各个线程的调用堆栈,就可以知道没有响应的线程到底在后台做什么事情,或者等待什么资源。 如果java程序崩溃生成core文件,jstack工具可以用来获得core文件的java stack和native stack的信息,从而可以轻松地知道java程序是如何崩溃和在程序何处发生问题。另外,jstack工具还可以附属到正在运行的java程序中,看到当时运行的java程序的java stack和native stack的信息, 如果现在运行的java程序呈现hung的状态,jstack是非常有用的。

java线程状态

  1.NEW,未启动的。不会出现在Dump中。
  2.RUNNABLE,在虚拟机内执行的。运行中状态,可能里面还能看到locked字样,表明它获得了某把锁。
  3.BLOCKED,受阻塞并等待监视器锁。被某个锁(synchronizers)給block住了。
  4.WATING,无限期等待另一个线程执行特定操作。等待某个condition或monitor发生,一般停留在park(), wait(), sleep(),join() 等语句里。
  5.TIMED_WATING,有时限的等待另一个线程的特定操作。和WAITING的区别是wait() 等语句加上了时间限制 wait(timeout)。
  6.TERMINATED,已退出的。

Monitor

  在多线程的 JAVA程序中,实现线程之间的同步,就是通过Monitor实现的。 Monitor是 Java中用以实现线程之间的互斥与协作的主要手段,它可以看成是对象或者 Class的锁。每一个对象都有,也仅有一个 monitor。

  进入区(Entrt Set):表示线程通过synchronized要求获取对象的锁。如果对象未被锁住,则迚入拥有者;否则则在进入区等待。一旦对象锁被其他线程释放,立即参与竞争。

  拥有者(The Owner):表示某一线程成功竞争到对象锁。

  等待区(Wait Set):表示线程通过对象的wait方法,释放对象的锁,并在等待区等待被唤醒。

  从图中可以看出,一个 Monitor在某个时刻,只能被一个线程拥有,该线程就是 “Active Thread”,而其它线程都是 “Waiting Thread”,分别在两个队列 “ Entry Set”和 “Wait Set”里面等候。在 “Entry Set”中等待的线程状态是 “Waiting for monitor entry”,而在“Wait Set”中等待的线程状态是 “in Object.wait()”。 先看 “Entry Set”里面的线程。我们称被 synchronized保护起来的代码段为临界区。当一个线程申请进入临界区时,它就进入了 “Entry Set”队列。对应的 code就像:

 synchronized(obj) {
//...
}

多线程分析

线程1获取到锁,处于RUNNABLE状态,线程2处于BLOCK状态

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

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

thread-2:waiting for monitor entry [0x000000001e21f000]说明线程2是通过synchronized关键字进入了监视器的临界区,并处于"Entry Set"队列,等待monitor

线程1和2都处于WAITING状态

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

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

死循环

 package io.guangsoft.jstack;

 public class EndlessLoop {
public static void main(String args[]) {
while(true) {
System.out.println("endless loop...");
}
}
}

使用jstack查看堆栈信息

我们可以清晰的看到main线程处于RUNNABLE,并能看到是哪个包哪个类下的第几行。

线程等待

 package io.guangsoft.jstack;

 import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors; class TestTask implements Runnable {
@Override
public void run() {
synchronized (this) {
try {
wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
} public class Wait{
public static void main(String[] args) throws Exception {
ExecutorService ex = Executors.newFixedThreadPool(1);
ex.execute(new TestTask());
}
}

死锁

 package io.guangsoft.jstack;

 import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors; class Task implements Runnable {
private int order;
private Object obj1;
private Object obj2; public Task(int order, Object obj1, Object obj2) {
this.order = order;
this.obj1 = obj1;
this.obj2 = obj2;
} public void test1() throws InterruptedException {
synchronized (obj1) {
//建议线程调取器切换到其它线程运行
Thread.yield();
synchronized (obj2) {
System.out.println("test1");
} }
}
public void test2() throws InterruptedException {
synchronized (obj2) {
Thread.yield();
synchronized (obj1) {
System.out.println("test2");
} }
} @Override
public void run() {
while (true) {
try {
if(this.order == 1){
this.test1();
} else {
this.test2();
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
} public class DeadLock {
public static void main(String[] args) throws Exception {
Object obj1 = new Object();
Object obj2 = new Object();
ExecutorService ex = Executors.newFixedThreadPool(10);
for (int i = 0; i < 10; i++) {
int order = i % 2 == 0 ? 1 : 0;
ex.execute(new Task(order, obj1, obj2));
}
}
}

JDK常用命令(二)jstack的更多相关文章

  1. linux初学 :linux 常用命令(二)

    压缩和解压命令 gzip/guzip   zip/unzip   tar gzip和gunzip一般可用参数是-r,例: gzip test.txt 压缩文件 gzip -r test 压缩所有tes ...

  2. Git的基本原理与常用命令[二]

    标签(linux): git 笔者Q:972581034 交流群:605799367.有任何疑问可与笔者或加群交流 git 的四个区域 四种状态 常用命令 git add #加入暂存(索引区) git ...

  3. linux常用命令二

    linux常用命令一 常用指令 ls        显示文件或目录 -l           列出文件详细信息l(list) -a          列出当前目录下所有文件及目录,包括隐藏的a(all ...

  4. JDK常用命令行工具(基于JDK10)

    虽然我是在jdk10环境下, 但是大体上和jdk8是差不多的. 总共有这么多 本来想着一口气把所有命令都边学边总结一下的, 结果发现....有些还真的不是很常用....或者说我这个水平还接触不到那么多 ...

  5. JDK常用命令(一)jps、jstat

    曾几何时,我们学习java都不再研究jdk而直接使用IDEA.eclipse和Netbeans,仿佛我们就认为我们的程序是这些编辑器编译出来的,这时多么可笑.殊不知,编辑器就是方便我们编辑开发的,而真 ...

  6. linux(三)之linux常用命令二

    今天就是星期五了,又可以休息两天了.有点小激动,开心.不过还是要加油,因为还有很多东西等着我去学习呢! 七.chmod 作用:修改文件的权限 7.1.命令格式:chmod mode filename ...

  7. JDK 常用命令

    一) 引言:    当我们安装完JDK时,除了必须的编译运行以外,它就已经自带了很多辅助工具.正所谓“工欲善其事,必先利其器.”如果能用好这些工具,它们将大大方便你的开发.它们的实用和方便有时甚至会使 ...

  8. JDK常用命令

    转自:https://www.cnblogs.com/saiQsai/p/10353044.html 1.jps 查看java进程,得到进程ID:7854 作用等同于:ps -ef | grep ja ...

  9. Linux学习之常用命令(二)

    1.上次介绍了一些常用的系统命令,这次又总结了一些小命令,故分享一下: 网卡地址查询的命令: ifconfig #不同于Windows系统,它的是ifconfig而不是ipconfig ip -a # ...

随机推荐

  1. JDBC 接口学习

    说明:文章所有内容皆选自实验楼教程[JDBC 入门教程],想要学习更多JDBC,可以点击教程进行学习~ JDBC 简介 JDBC 的全称是 Java Database Connectivity,叫做 ...

  2. 用于模型选择的AIC与BIC

    一.AIC(Akaike information Criterion)准则 二.BIC(Bayesian information Criterion)准则 参考文献: [1]AIC与BIC区别

  3. js中两个!!的理解

    在js中经常有两个!!出现,经常让人难以理解 (function () { var a = 10; var b = 20; function add(num1, num2) { var num1 = ...

  4. centos7及服务器端安装python2.7.13, setuptools, pip

    1. 安装python2.7.13 因为涉及到安装到服务器,所以可能不能直接在usr/bin及usr/local/bin下安装,所以本文详解安装在自定义目录下. 下载安装包: $ wget https ...

  5. Cocos Creator 计时器的延时循环试用方法

    *****计时器的一些运用***** //计算1次的计时器,2秒后执行 this.scheduleOnce(function(){ this.doSomething(); },2); //每隔5秒执行 ...

  6. System.Web.HttpException (0x80004005): 验证视图状态 MAC 失败。如果此应用程序由网络场或群集承载,请确保 <machineKey> 配置指定了相同的 validationKey 和验证算法。不能在群集中使用 AutoGenerate。

    异常描述: Global.asax捕获到异常:System.Web.HttpException (0x80004005): 验证视图状态 MAC 失败.如果此应用程序由网络场或群集承载,请确保 < ...

  7. java开发前的配置

    JAVA语言是1995年由Sun公司退出的一门高级编程语言,在2009年4月20被ORACLE公司收购 看看java体系图

  8. 数据加密之MD5加密

    MD5是一个安全的散列算法,有两个特点:1.输入两个不同的明文(一段原始的数字信息)不会得到相同的输出值2.根据输出值,不能得到原始的明文,即过程不可逆所以要解密MD5没有现成的算法,只能用穷举法,把 ...

  9. css中块级元素、内联元素(行内元素、内嵌元素)

    Block element 块级元素    顾名思义就是以块显示的元素,高度宽度都是可以设置的.比如我们常用 的<div>.<p>.<ul>默认状态下都是属于块级元 ...

  10. VM VirtualBox 全屏模式 && 自动缩放模式 相互切换

    [1]自动缩放模式 热键Host + C 偶然一次机会,把虚拟机切换为了自动缩放模式,如下图: 想要再切换为全屏模式,发现不知如何操作,后来折腾了一会儿,切换成功.以此备录一下. [2]切换为全屏模式 ...