java 调优 命令_Java常用命令及性能调优工具

1、Linux命令

1.1 top命令

40612cab1453

top命令

top命令的输出可以分为上下两部分:系统统计信息和进程统计信息。

系统统计信息:

第一行:任务队列信息。等同于uptime命令。

20:30:40 up 71 days, 21:36, 1 user, load average: 0.15, 0.16, 0.13

系统当前时间、系统运行时间、当前登录用户数。load average表示系统的平均负载(1分钟内、5分钟内、15分钟内)。

第二行:进程统计信息。分别为总的进程数、运行中的进程数、睡眠进程数、停止的进程数以及僵尸进程数。

Tasks: 75 total, 1 running, 74 sleeping, 0 stopped, 0 zombie

第三行:CPU统计信息。

Cpu(s): 0.4%us, 0.2%sy, 0.0%ni, 99.4%id, 0.1%wa, 0.0%hi, 0.0%si, 0.0%st

us:用户态CPU占用率、sy:内核态CPU占用率、ni:用户进程空间改变过优先级的进程CPU占用率、id:空闲CPU占用率、wa:等待输入输出的CPU时间百分比、hi:硬件中断请求、si:软件中断请求、st:CPU服务于软中断所耗费的时间总额。

第四行:内存统计信息。

Mem: 1922244k total, 1200496k used, 721748k free, 181508k buffers

依次表示物理内存总量、已使用内存量、空闲内存量、内核缓冲使用量。

第五行:交换区统计信息。

Swap: 0k total, 0k used, 0k free, 435204k cached

依次表示交换区总量、已使用交互区总量、空闲交换区总量、缓冲的交换区总量。

进程统计信息:

PID:进程id

USER:进程所有者的用户id

PR:优先级

NI:nice值。负值表示高优先级、正值表示低优先级

VIRT:进程使用的虚拟内存总量。VIRT=SWAP+RES

RES:进程使用的、未被换出的物理内存大小

SHR:共享内存大小(KB)

S:进程状态。R-运行、S-睡眠、D-不可中断的睡眠、T-跟踪/停止、Z-僵尸

%CPU:上次更新到现在的CPU时间占用百分比

%MEM:进程使用的物理内存百分比

%TIME+:进程使用的CPU时间总计

COMMAND:命令名

top常用子命令:

h:帮助

k:终止一个进程

c:切换显示完整的命令行

M:按照内存大小排序

P:按照CPU占用百分比排序

1.2 sar命令

sar命令也是Linux系统中重要的性能检测工具之一,可周期性的对内存和CPU的使用情况进行采样。如下:

sar 1 5

表示每隔1秒采样1次,共采样5次。

Linux 2.6.32-573.22.1.el6.x86_64 (-) 03/14/2017 _x86_64_ (1 CPU)

02:40:35 PM CPU %user %nice %system %iowait %steal %idle

02:40:36 PM all 0.99 0.00 0.99 0.00 0.00 98.02

02:40:37 PM all 0.00 0.00 0.00 0.00 0.00 100.00

02:40:38 PM all 1.00 0.00 0.00 0.00 0.00 99.00

02:40:39 PM all 0.00 0.00 0.00 0.00 0.00 100.00

02:40:40 PM all 0.00 0.00 0.00 0.00 0.00 100.00

Average: all 0.40 0.00 0.20 0.00 0.00 99.40

option选项:

-A:所有报告。

-u:CPU利用率。默认选项。

-d:磁盘使用情况。

-b:I/O使用情况。

-q:查看队列长度。

-r:内存使用情况。

-n:查看网络信息统计。【ALL】

-o:将采样结果输出到文件

1.3 vmstat命令

vmstat命令同样也是Linux系统中重要的性能检测工具之一,不仅可周期性的对内存、CPU进行采样,还可以对swap使用进行采样。

vmstat 1 5

表示每隔1秒采样一次,共采样5次。

procs -----------memory---------- ---swap-- -----io---- --system-- -----cpu-----

r b swpd free buff cache si so bi bo in cs us sy id wa st

0 0 0 401032 183320 732700 0 0 3 2 3 6 0 0 99 0 0

0 0 0 401016 183320 732700 0 0 0 0 234 512 0 1 99 0 0

0 0 0 401016 183320 732700 0 0 0 0 220 495 0 0 100 0 0

0 0 0 401016 183320 732700 0 0 0 32 240 518 1 0 99 0 0

0 0 0 401016 183320 732700 0 0 0 0 244 511 0 0 100 0 0

procs

r:等待运行的进程数

b:处在非中断睡眠状态的进程数

memory

swpd:虚拟内存使用情况(KB)

free:空闲内存大小(KB)

buff:表示块设备(block device)所占用的缓存页,包括:直接读写块设备、以及文件系统元数据(metadata),比如SuperBlock所使用的缓存页(KB)

cache:表示普通文件数据所占用的缓存页

swap

si:从磁盘交换到内存的交换页数量(KB/秒)

so:从内存交换到磁盘的交换页数量(KB/秒)

io

bi:发送到块设备的块数(块/秒)

bo:从块设备接收到的块数(块/秒)

system

in:每秒中断数

cs:每秒上下文切换次数

cpu

us:用户态CPU占用率

sy:内核态CPU占用率

id:空闲CPU占用率

-wa:等待输入输出的CPU时间百分比

st:CPU服务于软中断所耗费的时间总额

1.4 iostat命令

iostat可以提供详尽的I/O信息。

iostat 1 2

表示每隔1秒采样1次,共采样2次。

Linux 2.6.32-573.22.1.el6.x86_64 (-) 03/14/2017 _x86_64_ (1 CPU)

avg-cpu: %user %nice %system %iowait %steal %idle

0.42 0.00 0.17 0.05 0.00 99.36

Device: tps Blk_read/s Blk_wrtn/s Blk_read Blk_wrtn

vda 0.49 5.86 4.35 39755548 29531688

vdb 0.00 0.00 0.00 1392 0

avg-cpu: %user %nice %system %iowait %steal %idle

1.00 0.00 0.00 0.00 0.00 99.00

Device: tps Blk_read/s Blk_wrtn/s Blk_read Blk_wrtn

vda 0.00 0.00 0.00 0 0

vdb 0.00 0.00 0.00 0 0

tps:该设备每秒的传输次数

Blk_read/s:每秒从设备读取的数据量

Blk_wrtn/s:每秒向设备写入的数据量

Blk_read:读取的总数据量

Blk_wrtn:写入的总数据量

1.5 pidstat命令

pidstat也是一个功能强大的性能检测工具。不仅可以检测进程的性能,还可以检测线程的性能。

1.5.1 CPU使用率监控

下面的程序中,开启了3个线程,其中一个大量占用CPU,其他2个线程处于空闲状态。

public class CPUMain {

public static class BusyCPUTask implements Runnable {

@Override

public void run() {

while (true) {

double i = Math.random() * Math.random();

}

}

}

public static class LazyCPUTask implements Runnable {

@Override

public void run() {

try {

while (true) {

TimeUnit.SECONDS.sleep(1);

}

} catch (Exception e) {

// do nothing

}

}

}

public static void main(String[] args) {

new Thread(new BusyCPUTask()).start();

new Thread(new LazyCPUTask()).start();

new Thread(new LazyCPUTask()).start();

}

}

1、使用jps -l找到该Java程序的PID:

[root@- ~]# jps -l

19077 sun.tools.jps.Jps

19064 command.CPUMain

17338 org.elasticsearch.bootstrap.Elasticsearch

17851 org.jruby.Main

2、使用pidstat命令输出该程序的CPU使用情况:

[root@- ~]# pidstat -p 19064 -u 1 3

Linux 2.6.32-573.22.1.el6.x86_64 (-) 03/14/2017 _x86_64_ (1 CPU)

05:49:01 PM PID %usr %system %guest %CPU CPU Command

05:49:02 PM 19064 99.00 0.00 0.00 99.00 0 java

05:49:03 PM 19064 100.00 0.00 0.00 100.00 0 java

05:49:04 PM 19064 99.00 0.00 0.00 99.00 0 java

Average: 19064 99.33 0.00 0.00 99.33 - java

-p 指定进程的ID,-u 对CPU使用率进行监控;每隔1秒采样1次,共采样3次。

3、使用-t参数找出最占CPU的线程

[root@- ~]# pidstat -p 19064 -u -t 1 1

Linux 2.6.32-573.22.1.el6.x86_64 (-) 03/14/2017 _x86_64_ (1 CPU)

05:56:00 PM TGID TID %usr %system %guest %CPU CPU Command

05:56:01 PM 19064 - 99.00 0.00 0.00 99.00 0 java

05:56:01 PM - 19064 0.00 0.00 0.00 0.00 0 |__java

05:56:01 PM - 19065 0.00 0.00 0.00 0.00 0 |__java

05:56:01 PM - 19066 0.00 0.00 0.00 0.00 0 |__java

05:56:01 PM - 19067 0.00 0.00 0.00 0.00 0 |__java

05:56:01 PM - 19068 0.00 0.00 0.00 0.00 0 |__java

05:56:01 PM - 19069 0.00 0.00 0.00 0.00 0 |__java

05:56:01 PM - 19070 0.00 0.00 0.00 0.00 0 |__java

05:56:01 PM - 19071 0.00 0.00 0.00 0.00 0 |__java

05:56:01 PM - 19072 0.00 0.00 0.00 0.00 0 |__java

05:56:01 PM - 19073 0.00 0.00 0.00 0.00 0 |__java

05:56:01 PM - 19074 100.00 0.00 0.00 100.00 0 |__java

05:56:01 PM - 19075 0.00 0.00 0.00 0.00 0 |__java

05:56:01 PM - 19076 0.00 0.00 0.00 0.00 0 |__java

... ...

可以看到, 19074 这个线程占用了大量CPU。

备注:上述2和3两个过程可以使用top -p 19064 -H命令查出哪个线程占用大量CPU,如下:

[root@- ~]# top -p 19064 -H

top - 17:57:41 up 78 days, 19:03, 3 users, load average: 1.00, 0.86, 0.55

Tasks: 13 total, 1 running, 12 sleeping, 0 stopped, 0 zombie

Cpu(s): 99.7%us, 0.3%sy, 0.0%ni, 0.0%id, 0.0%wa, 0.0%hi, 0.0%si, 0.0%st

Mem: 1922244k total, 1584308k used, 337936k free, 185344k buffers

Swap: 0k total, 0k used, 0k free, 776028k cached

PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND

19064 root 20 0 2414m 23m 11m S 0.0 1.3 0:00.00 java

19065 root 20 0 2414m 23m 11m S 0.0 1.3 0:00.07 java

19066 root 20 0 2414m 23m 11m S 0.0 1.3 0:00.00 java

19067 root 20 0 2414m 23m 11m S 0.0 1.3 0:00.00 java

19068 root 20 0 2414m 23m 11m S 0.0 1.3 0:00.00 java

19069 root 20 0 2414m 23m 11m S 0.0 1.3 0:00.00 java

19070 root 20 0 2414m 23m 11m S 0.0 1.3 0:00.00 java

19071 root 20 0 2414m 23m 11m S 0.0 1.3 0:00.00 java

19072 root 20 0 2414m 23m 11m S 0.0 1.3 0:00.00 java

19073 root 20 0 2414m 23m 11m S 0.0 1.3 0:00.12 java

19074 root 20 0 2414m 23m 11m R 99.6 1.3 9:09.31 java

19075 root 20 0 2414m 23m 11m S 0.0 1.3 0:00.01 java

19076 root 20 0 2414m 23m 11m S 0.0 1.3 0:00.00 java

得到的结果同样是**19074 **这个线程。

4、jstack定位线程栈

jstack 19064 > jstack.log

5、查看19074线程情况

通过使用命令printf %x 19074得到19074的16进制:4a82

查看4a82线程:

"Thread-0" #8 prio=5 os_prio=0 tid=0x00007fae380fa800 nid=0x4a82 runnable [0x00007fae3c551000]

java.lang.Thread.State: RUNNABLE

at command.CPUMain$BusyCPUTask.run(CPUMain.java:14)

at java.lang.Thread.run(Thread.java:745)

结论:可以定位到线程在执行CPUMain.java:14占用了大量CPU。

1.5.2 I/O监控

下面的程序中,开启了3个线程,其中一个大量占用I/O,其他2个线程处于空闲状态。

public class IOMain {

public static class BusyIOTask implements Runnable {

@Override

public void run() {

try {

FileOutputStream fos;

FileInputStream fis;

while (true) {

fos = new FileOutputStream(new File("temp"));

for (int i = 0; i < 1000; i++) {

fos.write(i); // 写操作

}

fos.close();

fis = new FileInputStream(new File("temp"));

while (fis.read() != -1); // 读操作

fis.close();

}

} catch (Exception e) {

e.printStackTrace();

}

}

}

public static class LazyIOTask implements Runnable {

@Override

public void run() {

try {

while (true) {

TimeUnit.SECONDS.sleep(1);

}

} catch (Exception e) {

// do nothing

}

}

}

public static void main(String[] args) {

new Thread(new IOMain.BusyIOTask()).start();

new Thread(new IOMain.LazyIOTask()).start();

new Thread(new IOMain.LazyIOTask()).start();

}

}

1、使用jps -l找到该Java程序的PID:

[root@- ~]# jps -l

17338 org.elasticsearch.bootstrap.Elasticsearch

17851 org.jruby.Main

19323 sun.tools.jps.Jps

19310 command.IOMain

2、使用pidstat命令输出该程序的各个线程的I/O使用情况:

[root@- ~]# pidstat -p 19310 -d -t 1 3

Linux 2.6.32-573.22.1.el6.x86_64 (-) 03/14/2017 _x86_64_ (1 CPU)

06:30:13 PM TGID TID kB_rd/s kB_wr/s kB_ccwr/s Command

06:30:14 PM 19310 - 0.00 3482.83 1741.41 java

06:30:14 PM - 19310 0.00 0.00 0.00 |__java

06:30:14 PM - 19311 0.00 0.00 0.00 |__java

06:30:14 PM - 19312 0.00 0.00 0.00 |__java

06:30:14 PM - 19313 0.00 0.00 0.00 |__java

06:30:14 PM - 19314 0.00 0.00 0.00 |__java

06:30:14 PM - 19315 0.00 0.00 0.00 |__java

06:30:14 PM - 19316 0.00 0.00 0.00 |__java

06:30:14 PM - 19317 0.00 0.00 0.00 |__java

06:30:14 PM - 19318 0.00 0.00 0.00 |__java

06:30:14 PM - 19319 0.00 0.00 0.00 |__java

06:30:14 PM - 19320 0.00 3478.79 1741.41 |__java

06:30:14 PM - 19321 0.00 0.00 0.00 |__java

06:30:14 PM - 19322 0.00 0.00 0.00 |__java

... ...

3、定位线程栈

同样地使用jstack命令,导出该程序的线程栈,查找nid=19320(0x4b78)的线程,即可定位问题。

1.5.3 内存监控

使用pidstat命令,还可以监视指定进程的内存的使用情况。

[root@- test]# pidstat -p 17338 -r 1 3

Linux 2.6.32-573.22.1.el6.x86_64 (-) 03/14/2017 _x86_64_ (1 CPU)

06:36:36 PM PID minflt/s majflt/s VSZ RSS %MEM Command

06:36:37 PM 17338 0.00 0.00 2677708 280504 14.59 java

06:36:38 PM 17338 0.00 0.00 2677708 280504 14.59 java

06:36:39 PM 17338 0.00 0.00 2677708 280504 14.59 java

Average: 17338 0.00 0.00 2677708 280504 14.59 java

minflt/s:该进程每秒minor faults(不需要从磁盘中调出内存页)的总数

majflt/s:该进程每秒major faults(需要从磁盘中调出内存页)的总数

VSZ:该进程使用的虚拟内存大小(KB)

RSS:该进程使用的物理内存大小(KB)

%MEM:内存占用率

2、JDK命令

2.1 jps命令

jps命令类似于Linux的ps,只不过ps是查看Linux系统的进程,jps只是列出当前用户启动的Java进程。

jps

[root@- ~]# jps

17338 Elasticsearch

17851 Main

21166 Jps

jps -q:只输出进程id

jps -m:输出传递给Java Main函数的参数

jps -l:输出Main函数的完整路径

jps -v:输出传递给JVM的参数

2.2 jstat命令

jstat命令用于观察Java程序的运行时工具。

Usage: jstat -help|-options

jstat - [-t] [-h] [ []]

option可选项:

-class:显示ClassLoader的相关信息

[root@- ~]# jstat -class -t 17338

Timestamp Loaded Bytes Unloaded Bytes Time

4302040.9 8482 15664.4 12 12.0 7.94

Loaded表示载入类的数量、Bytes表示载入类的大小、Unloaded表示卸载类的数量、Bytes表示卸载类的大小、Time表示在加载及卸载类上所花的时间。

-compiler:显示JIT编译的相关信息

[root@- ~]# jstat -compiler -t 17338

Timestamp Compiled Failed Invalid Time FailedType FailedMethod

4312097.9 12812 0 0 73.32 0

Complied表示编译任务执行的次数、Failed表示编译失败的次数、Invalid表示不可用的次数、Time表示编译的总耗时、FailedType表示最后一次编译失败的类型、FailedMethod表示最后一次编译失败的类名和方法名。

-gc:显示与GC相关的堆信息

[root@- ~]# jstat -gc -t 17338

Timestamp S0C S1C S0U S1U EC EU OC OU MC MU CCSC CCSU YGC YGCT FGC FGCT GCT

4312491.0 8512.0 8512.0 76.1 0.0 68160.0 15675.5 439104.0 18409.8 47780.0 47055.7 5600.0 5363.6 644 4.077 4 0.176 4.253

S0C:S0(From)的大小(KB)

S1C:S1(To)的大小(KB)

S0U:S0(From)已使用的大小(KB)

S1U:S1(To)已使用的大小(KB)

EC:Eden区的大小(KB)

EU:Eden已使用的大小(KB)

OC:老年代大小(KB)

OU:老年代已使用的大小(KB)

MC:方法区大小(KB)

MU:方法区已使用大小(KB)

CCSC:压缩类空间大小(KB)

CCSU:压缩类空间已使用大小(KB)

PC:永久区大小(KB)

PU:永久区已使用大小(KB)

YGC:新生代GC次数

YGCT:新生代GC耗时

FGC:Full GC次数

FGCT:Full GC耗时

GCT:GC总耗时

-gccapacity:显示各个代的容量及使用情况

[root@- ~]# jstat -gccapacity -t 17338

Timestamp NGCMN NGCMX NGC S0C S1C EC OGCMN OGCMX OGC OC MCMN MCMX MC CCSMN CCSMX CCSC YGC FGC

4313185.9 85184.0 85184.0 85184.0 8512.0 8512.0 68160.0 439104.0 439104.0 439104.0 439104.0 0.0 1091584.0 47780.0 0.0 1048576.0 5600.0 644 4

与-gc相比,不仅输出了各个代当前的大小,还输出了各个代的最小、最大值。

NGCMN:新生代最小值(KB)

NGCMX:新生代最大值(KB)

NGC:当前新生代大小(KB)

OGCMN:老年代最小值(KB)

OGCMX:老年代最大值(KB)

PGCMN:永久区最小值(KB)

PGCMX:永久区最大值(KB)

-gccause:显示垃圾收集相关信息(同gcutil),同时显示最后一次或当前正在发生的垃圾收集的诱发原因

[root@- ~]# jstat -gccause -t 17338

Timestamp S0 S1 E O M CCS YGC YGCT FGC FGCT GCT LGCC GCC

4313692.2 0.89 0.00 43.07 4.19 98.48 95.78 644 4.077 4 0.176 4.253 Allocation Failure No GC

LGCC:最近一次GC的的原因

GCC:当前GC的原因

-gcnew:显示新生代信息

[root@- ~]# jstat -gcnew -t 17338

Timestamp S0C S1C S0U S1U TT MTT DSS EC EU YGC YGCT

4314215.7 8512.0 8512.0 76.1 0.0 6 6 4256.0 68160.0 33355.0 644 4.077

TT:新生代对象晋升到老年代对象的年龄

MTT:新生代对象晋升到老年代对象的年龄最大值

DSS:所需的幸存区大小

-gcnewcapacity:显示新生代容量及使用情况

[root@- ~]# jstat -gcnewcapacity -t 17338

Timestamp NGCMN NGCMX NGC S0CMX S0C S1CMX S1C ECMX EC YGC FGC

4314357.1 85184.0 85184.0 85184.0 8512.0 8512.0 8512.0 8512.0 68160.0 68160.0 644 4

S0CMX:S0区的最大值

S1CMX:S1区的最大值

ECMX:Eden区的最大值

-gcold:显示老年代和永久代的信息

[root@- ~]# jstat -gcold -t 17338

Timestamp MC MU CCSC CCSU OC OU YGC FGC FGCT GCT

4314463.2 47780.0 47055.7 5600.0 5363.6 439104.0 18409.8 644 4 0.176 4.253

-gcoldcapacity:显示老年代容量

[root@- ~]# jstat -gcoldcapacity -t 17338

Timestamp OGCMN OGCMX OGC OC YGC FGC FGCT GCT

4314490.9 439104.0 439104.0 439104.0 439104.0 644 4 0.176 4.253

-gcutil:显示垃圾收集信息

[root@- ~]# jstat -gcutil -t 17338

Timestamp S0 S1 E O M CCS YGC YGCT FGC FGCT GCT

4314594.9 0.89 0.00 52.34 4.19 98.48 95.78 644 4.077 4 0.176 4.253

-printcompilation:输出HotSpot编译方法的统计

[root@- ~]# jstat -printcompilation -t 17338

Timestamp Compiled Size Type Method

4314622.9 12827 173 1 org/elasticsearch/cluster/routing/allocation/decider/AllocationDeciders canRebalance

其他选项:

-t:在输出信息前加入一个时间戳,显示程序的运行时间

-h:在周期性数据输出时,输出多少行数据后,跟着输出一个表头信息

interval:指定输出统计数据的周期(毫秒)

count:指定一共输出多少次数据

2.3 jinfo命令

jinfo可以查看正在运行的Java程序的JVM参数,并且支持运行时修改个别参数。

jinfo [option]

option可选项:

-flag to print the value of the named VM flag,打印指定JVM的参数值

-flag [+|-] to enable or disable the named VM flag,设置指定JVM参数的boolean值

-flag = to set the named VM flag to the given value,设置指定JVM参数值

-flags to print VM flags,打印JVM的参数值

-sysprops to print Java system properties,打印Java系统的属性信息

to print both of the above,打印flags和syspros

2.4 jmap命令

jmap命令能生成Java应用程序的堆快照和对象的统计信息。

jmap -histo 17338 > jmap.log

num #instances #bytes class name

----------------------------------------------

1: 119627 16888576 [C

2: 74845 8336640 [B

3: 14991 3763272 [I

4: 66990 3215520 java.lang.management.MemoryUsage

5: 32973 2374056 java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask

6: 42965 2055352 [Ljava.lang.Object;

7: 81756 1962144 java.lang.String

8: 9035 994824 java.lang.Class

9: 6709 858752 sun.nio.fs.UnixFileAttributes

10: 24718 790976 sun.nio.fs.UnixPath

... ...

3729: 1 16 sun.util.resources.LocaleData$LocaleDataResourceBundleControl

Total 1077805 61629024

上述命令输出了内存中实例的数量和大小。

生成堆快照信息:

jmap -dump:format=b,file=heap.hprof 17338

2.5 jhat命令

jhat命令可以分析Java程序的堆快照。

[root@- ~]# jhat heap.hprof

Reading from heap.hprof...

Dump file created Wed Mar 15 15:42:02 CST 2017

Snapshot read, resolving...

Resolving 1183100 objects...

Chasing references, expect 236 dots............................................................................................................................................................................................................................................

Eliminating duplicate references............................................................................................................................................................................................................................................

Snapshot resolved.

Started HTTP server on port 7000

Server is ready.

可以通过浏览器访问7000端口查看堆快照信息。

2.6 jstack命令

用于输出Java应用程序的线程栈信息。

public class DeadLockMain {

private static String A = "A";

private static String B = "B";

public void deadLock() {

Thread t1 = new Thread(new Runnable() {

@Override

public void run() {

synchronized (A) {

try {

TimeUnit.SECONDS.sleep(2);

} catch (Exception e) {

e.printStackTrace();

}

synchronized (B) {

System.out.println("thread1");

}

}

}

});

Thread t2 = new Thread(new Runnable() {

@Override

public void run() {

synchronized (B) {

synchronized (A) {

System.out.println("thead2");

}

}

}

});

t1.start();

t2.start();

}

public static void main(String[] args) {

new DeadLockMain().deadLock();

}

}

上述代码是一个简单的会发生死锁的例子,两个线程分别持有A和B,并分别请求B和A,导致死锁产生。

使用jstack打印上述进程的线程栈信息,部分输出如下:

"Thread-1" #9 prio=5 os_prio=0 tid=0x00007f0ff410b000 nid=0x56d9 waiting for monitor entry [0x00007f0fe4bfa000]

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

at command.DeadLockMain$2.run(DeadLockMain.java:33)

- waiting to lock <0x00000000e2a77cc0> (a java.lang.String)

- locked <0x00000000e2a77cf0> (a java.lang.String)

at java.lang.Thread.run(Thread.java:745)

"Thread-0" #8 prio=5 os_prio=0 tid=0x00007f0ff40fb000 nid=0x56d8 waiting for monitor entry [0x00007f0fe4cfb000]

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

at command.DeadLockMain$1.run(DeadLockMain.java:23)

- waiting to lock <0x00000000e2a77cf0> (a java.lang.String)

- locked <0x00000000e2a77cc0> (a java.lang.String)

at java.lang.Thread.run(Thread.java:745)

Found one Java-level deadlock:

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

"Thread-1":

waiting to lock monitor 0x00007f0fd8004e28 (object 0x00000000e2a77cc0, a java.lang.String),

which is held by "Thread-0"

"Thread-0":

waiting to lock monitor 0x00007f0fd80062c8 (object 0x00000000e2a77cf0, a java.lang.String),

which is held by "Thread-1"

Java stack information for the threads listed above:

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

"Thread-1":

at command.DeadLockMain$2.run(DeadLockMain.java:33)

- waiting to lock <0x00000000e2a77cc0> (a java.lang.String)

- locked <0x00000000e2a77cf0> (a java.lang.String)

at java.lang.Thread.run(Thread.java:745)

"Thread-0":

at command.DeadLockMain$1.run(DeadLockMain.java:23)

- waiting to lock <0x00000000e2a77cf0> (a java.lang.String)

- locked <0x00000000e2a77cc0> (a java.lang.String)

at java.lang.Thread.run(Thread.java:745)

Found 1 deadlock.

从上述输出来看,很容易找到死锁,并且可以看到发生死锁的两个线程以及两个线程的持有和等待的对象。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值