通过java自带的工具和linux命令来分析死锁

Java死锁案例分析
本文通过一个具体的Java程序示例,详细分析了如何使用jstack工具诊断并解决死锁问题,帮助读者理解死锁产生的原因及其解决方法。

  当我们编写java程序时,由于不合理的设计,可能会出现程序死循环/死锁问题。

下面我就以程序的死锁为例,来进行分析

我编写的测试类是Run类

1.查找Run类对应的PID,使用命令:ps -ef | grep Run

 

gl    6765  4121  0 13:52 ?        00:00:00 /opt/java/jdk1.8.0_101/bin/java -Dfile.encoding=UTF-8 -classpath /home/lupeng/java_development/MultiThread/bin Run
gl    6795  2766  0 13:53 pts/0    00:00:00 grep --color=auto Run

 

 

2.利用java自带的工具jstack进行分析

jstack 6765

结果如下

 

Java stack information for the threads listed above:
===================================================
"Thread-1":
	at DeadThread.run(DeadThread.java:37)
	- waiting to lock <0x00000000ec1df068> (a java.lang.Object)
	- locked <0x00000000ec1df078> (a java.lang.Object)
	at java.lang.Thread.run(Thread.java:745)
"Thread-0":
	at DeadThread.run(DeadThread.java:21)
	- waiting to lock <0x00000000ec1df078> (a java.lang.Object)
	- locked <0x00000000ec1df068> (a java.lang.Object)
	at java.lang.Thread.run(Thread.java:745)

Found 1 deadlock.


deadlock说明出现死锁问题。

 

Thread-1 已经获得了锁<0x00000000ec1df078>,同时等待锁<0x00000000ec1df078>

Thread-0已经获得了锁<0x00000000ec1df078>,同时等待锁<0x00000000ec1df078>

一次发生了死锁问题。

 

Found one Java-level deadlock:
=============================
"Thread-1":
  waiting to lock monitor 0x00007fefcc003828 (object 0x00000000ec1df068, a java.lang.Object),
  which is held by "Thread-0"
"Thread-0":
  waiting to lock monitor 0x00007fefcc006218 (object 0x00000000ec1df078, a java.lang.Object),
  which is held by "Thread-1"

 

 

 

 

 

那么到底时什么地方出现了死锁问题呢?

我们再来分析下

 

Java stack information for the threads listed above:
===================================================
"Thread-1":
	at DeadThread.run(DeadThread.java:37)
	- waiting to lock <0x00000000ec1df068> (a java.lang.Object)
	- locked <0x00000000ec1df078> (a java.lang.Object)
	at java.lang.Thread.run(Thread.java:745)
"Thread-0":
	at DeadThread.run(DeadThread.java:21)
	- waiting to lock <0x00000000ec1df078> (a java.lang.Object)
	- locked <0x00000000ec1df068> (a java.lang.Object)
	at java.lang.Thread.run(Thread.java:745)

Found 1 deadlock.

其中有一行是at DeadThread.run(DeadThread.java:37)

 

说明Thread-1实在DeadThread类的37行处发生死锁

其中at DeadThread.run(DeadThread.java:21)

说明Thread-0实在DeadThread类的21行处发生死锁
接下来我们定位到具体代码:

 

public class DeadThread implements Runnable{
	public String username;
	public Object lock1 = new Object();
	public Object lock2 = new Object();
	
	@Override
	public void run() {
		// TODO Auto-generated method stub
		if(username.equals("a")){
			synchronized (lock1) {
				try {
					System.out.println("username = "+username);
					System.out.println(Thread.currentThread().getName());
					Thread.sleep(3000);
				} catch (Exception e) {
					// TODO: handle exception
					e.printStackTrace();
				}
				synchronized (lock2) {
					System.out.println("按lock1->lock2的顺序执行代码");
				}
			}
		}
		if(username.equals("b")){
			synchronized (lock2) {
				try{
						System.out.println("username = "+username);
						System.out.println(Thread.currentThread().getName());
						Thread.sleep(3000);
					
				}catch (Exception e) {
					// TODO: handle exception
					e.printStackTrace();
				}
				synchronized (lock1) {
					System.out.println("按lock2->lock1顺序执行代码");
				}
			}
			
		}
	}
	
	public void setFlag(String username){
		this.username=username;
	}
}

 

 

从而定位到死锁发生的原因,及具体位置:

Thread-0获得了锁lock1,接下来期望获得锁lock2,(20)

但是此时Thread-1获得了锁lock2,接下来期望获得锁lock2,(37)

因而发生了死锁。
 

 

 

<think> 我们参考用户提供的引用用户的需求:用户想查找在Linux系统中用于检查Java运行情况的相关命令。 根据引用[1]中提到的方法,我们可以使用命令行来排查Java应用程序的CPU内存问题,其中包括一些基本的性能监视命令。 引用[2]中提到了检查Java版本的方法,这也是检查Java运行情况的一部分。 引用[3]中提到了列出Java进程、终止进程以及查看网络连接状态的命令,这些也与Java运行情况相关。 接下来,我们将整理这些引用中提到的命令,并结合常见的Linux下检查Java运行情况的命令进行回答。 1. 检查Java版本:这是验证Java是否安装以及安装版本的基本命令。 - `java -version` - `javac -version`(如果安装了JDK) 2. 查看Java进程:使用`jps`命令Java Virtual Machine Process Status Tool)可以列出正在运行的Java进程,并显示主类的完整包名或JAR文件路径。 - `jps` 或 `jps -l` 3. 监控Java应用的CPU内存使用情况:可以使用`top`命令查看进程的资源占用,但为了更详细地查看Java进程,可以使用`jstat`命令Java Virtual Machine statistics monitoring tool)。 - `top`:查看系统资源使用情况,可以找到Java进程的PID资源消耗。 - `jstat -gcutil <pid> <interval> <count>`:查看垃圾回收情况,例如:`jstat -gcutil 12345 1000 10` 表示每1秒输出一次,共10次。 - `jstat -gc <pid>`:显示垃圾回收堆的行为统计。 - `jstat -class <pid>`:显示类加载信息。 4. 查看Java进程的详细内存映射:使用`jmap`(Java memory map)命令可以生成Java进程的内存快照,用于分析内存使用情况。 - `jmap -heap <pid>`:显示Java堆的详细信息。 - `jmap -histo:live <pid>`:显示堆中对象的统计信息(包括对象数量大小)。 - `jmap -dump:format=b,file=heapdump.hprof <pid>`:生成堆转储文件,用于后续分析。 5. 线程分析:使用`jstack`(Java stack trace)命令可以获取Java进程的线程堆栈信息,用于分析线程状态死锁等问题。 - `jstack <pid>`:输出线程堆栈信息。 - `jstack -l <pid>`:除了堆栈信息外,还显示关于锁的附加信息。 6. 网络连接状态:使用`netstat`命令可以查看Java进程的网络连接端口占用情况。 - `netstat -tulpn | grep java` 或 `netstat -tulpn | grep <pid>`:查看Java进程监听的端口网络连接。 7. 终止Java进程:如果发现某个Java进程出现问题,可以使用`kill`命令终止。 - `kill <pid>`:正常终止进程。 - `kill -9 <pid>`:强制终止进程。 8. 图形化工具:除了命令行,还可以使用图形化工具如VisualVM(需要单独启动)进行更深入的分析。 注意:以上命令中,`<pid>`是Java进程的ID,可以通过`jps`或`ps`命令获取。 另外,用户可能需要安装JDK来使用`jps`、`jstat`、`jmap`、`jstack`等工具,因为这些工具位于JDK的bin目录下。 下面我们按照回答结构给出详细说明,并在适当位置添加引用标识。 </think> ### Linux系统检查Java运行情况的相关命令Linux系统中,可通过以下命令监控Java应用的运行状态(包含性能、进程、内存网络等方面): #### ✅ 1. **基础信息检查** - **Java版本验证** ```bash java -version # 显示JDK版本信息 javac -version # 显示编译器版本 [^2] ``` #### ✅ 2. **进程监控** - **列出Java进程** ```bash jps -l # 显示Java进程PID及主类/JAR路径(JDK工具)[^3] ps -ef | grep java # 通用进程查看 ``` - **资源占用分析** ```bash top -p $(pgrep -d',' java) # 动态监控CPU/内存 jstat -gcutil <PID> 1000 5 # 每1秒输出1次GC数据,共5次 [^1] ``` #### ✅ 3. **内存诊断** - **堆内存分析** ```bash jmap -heap <PID> # 查看堆配置 jmap -histo:live <PID> # 统计存活对象 [^1] jmap -dump:format=b,file=heapdump.hprof <PID> # 生成堆转储文件 ``` #### ✅ 4. **线程与栈追踪** - **线程状态检查** ```bash jstack <PID> > thread_dump.txt # 导出线程快照(诊断死锁)[^1] jstack -l <PID> # 附加锁信息 ``` #### ✅ 5. **网络与端口** - **端口监听检测** ```bash netstat -tulpn | grep java # 查看Java监听的端口 [^3] ss -plant | grep <PID> # 更高效的替代方案 ``` #### ✅ 6. **进程管理** - **终止Java进程** ```bash kill <PID> # 正常终止 kill -9 <PID> # 强制终止 [^3] ``` #### ✅ 工具链说明 | 命令 | 作用 | 所属工具包 | |---------|---------------------|------------| | `jps` | Java进程查看 | JDK自带 | | `jstat` | JVM统计监控 | JDK自带 | | `jmap` | 内存映射分析 | JDK自带 | | `jstack`| 线程堆栈分析 | JDK自带 | | `VisualVM` | 图形化性能分析工具 | 需独立安装 [^1] | > **提示**: > - JDK命令需安装完整JDK(非仅JRE) > - 生产环境建议结合`nohup`或`systemd`守护进程 > - 复杂问题可用`arthas`或`VisualVM`在线诊断 [^1] --- ###
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值