JDK常用命令(二)jstack
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的更多相关文章
- linux初学 :linux 常用命令(二)
压缩和解压命令 gzip/guzip zip/unzip tar gzip和gunzip一般可用参数是-r,例: gzip test.txt 压缩文件 gzip -r test 压缩所有tes ...
- Git的基本原理与常用命令[二]
标签(linux): git 笔者Q:972581034 交流群:605799367.有任何疑问可与笔者或加群交流 git 的四个区域 四种状态 常用命令 git add #加入暂存(索引区) git ...
- linux常用命令二
linux常用命令一 常用指令 ls 显示文件或目录 -l 列出文件详细信息l(list) -a 列出当前目录下所有文件及目录,包括隐藏的a(all ...
- JDK常用命令行工具(基于JDK10)
虽然我是在jdk10环境下, 但是大体上和jdk8是差不多的. 总共有这么多 本来想着一口气把所有命令都边学边总结一下的, 结果发现....有些还真的不是很常用....或者说我这个水平还接触不到那么多 ...
- JDK常用命令(一)jps、jstat
曾几何时,我们学习java都不再研究jdk而直接使用IDEA.eclipse和Netbeans,仿佛我们就认为我们的程序是这些编辑器编译出来的,这时多么可笑.殊不知,编辑器就是方便我们编辑开发的,而真 ...
- linux(三)之linux常用命令二
今天就是星期五了,又可以休息两天了.有点小激动,开心.不过还是要加油,因为还有很多东西等着我去学习呢! 七.chmod 作用:修改文件的权限 7.1.命令格式:chmod mode filename ...
- JDK 常用命令
一) 引言: 当我们安装完JDK时,除了必须的编译运行以外,它就已经自带了很多辅助工具.正所谓“工欲善其事,必先利其器.”如果能用好这些工具,它们将大大方便你的开发.它们的实用和方便有时甚至会使 ...
- JDK常用命令
转自:https://www.cnblogs.com/saiQsai/p/10353044.html 1.jps 查看java进程,得到进程ID:7854 作用等同于:ps -ef | grep ja ...
- Linux学习之常用命令(二)
1.上次介绍了一些常用的系统命令,这次又总结了一些小命令,故分享一下: 网卡地址查询的命令: ifconfig #不同于Windows系统,它的是ifconfig而不是ipconfig ip -a # ...
随机推荐
- JSPatch解析
defineClass('JPViewController', { handleBtn: function(sender) { var tableViewCtrl = JPTableViewContr ...
- Java之网络编程
1.网络编程的基本概念 1.1 网络的概念 网络:一组相互连接的计算机,多台计算机组成,使用物理线路进行连接 1.2 网络连接的功能 1.3 网络编程的三要素 1) IP 地址:唯一标识网络上的每一台 ...
- 编写一种递归方法,它返回数N的二进制中表示1的个数。
/** * 编写一种递归方法,它返回数N的二进制中表示1的个数.利用这样一个事实:N为奇数,其1的个数为N/2的二进制中1的个数加1. * @author wulei * */public class ...
- RDD、DataFrame、Dataset三者三者之间转换
转化: RDD.DataFrame.Dataset三者有许多共性,有各自适用的场景常常需要在三者之间转换 DataFrame/Dataset转RDD: 这个转换很简单 val rdd1=testDF. ...
- css 扩大点击范围
业务场景:比如某个按钮大小已经固定了,但是需求点击按钮周边就可以触发点击事件. 设置一下before属性里面的height,width就是设置你要点击的范围. rem是css3中新增加的一个单位属性( ...
- 【Redis学习之七】Redis持久化
环境 虚拟机:VMware 10 Linux版本:CentOS-6.5-x86_64 客户端:Xshell4 FTP:Xftp4 jdk8 redis-2.8.18 什么是持久化? 将数据从掉电易失的 ...
- C# 数值类型和无穷大
在c#语言中的数字有两个特性要了解.例如:任何数除以0所得的结果是无穷大,不在int long 和decimal类型的范围内.所以计算(一个数除以0会出错),但是在double和float类型中有一个 ...
- c# 控件的基类——Control
控件的基类用于Windows窗体应用的控件都派生自Control类,并继承了许多通用成员,这些成员都是平时使用控件的过程中最常用的. Name:控件实例的名字,通常通过“属性”窗口设置,控件实例名称变 ...
- golang学习笔记19 用Golang实现以太坊代币转账
golang学习笔记19 用Golang实现以太坊代币转账 在以太坊区块链中,我们称代币为Token,是以太坊区块链中每个人都可以任意发行的数字资产.并且它必须是遵循erc20标准的,至于erc20标 ...
- php CI框架中URL特殊字符处理与SQL注入隐患
php CI框架中URL特殊字符处理与SQL注入隐患 php CI框架中URL特殊字符有很多是不支持的,导致像c++,括号这些常用的分类,字符都无法正常显示很头痛,而在配置里增加单引号' 反斜杠\ 这 ...