您的位置:首页 > 运维架构

第八章 JVM性能监控与故障处理工具(2)

2016-02-08 14:58 453 查看
注意:该篇博客主要记录自《深入理解java虚拟机(第二版)》

说明:关于命令行的JVM性能监控与故障处理工具见《第七章 JVM性能监控与故障处理工具(1)

1、图像化的故障处理工具

Jconsole

visualVM

2、Jconsole

进入"E:\Java\jdk1.6\bin",双击"jconsole.exe",弹出如下框:

package thread;

/**
* 测试线程
*/
class XXthread implements Runnable{
int a,b;

public XXthread(int a, int b) {
this.a = a;
this.b = b;
}

public void run() {
synchronized (Integer.valueOf(a)) {
synchronized (Integer.valueOf(b)) {
System.out.println(a + b);
}
}
}
}

public class TestDeadLockThread {
public static void main(String[] args) {
for(int i=0;i<100;i++){
new Thread(new XXthread(1, 2)).start();
new Thread(new XXthread(2, 1)).start();
}
}
}


View Code
执行main()方法,之后去查看"线程"标签,点击"检测死锁",如下:





发现线程Thread-95和Thread-106死锁(彼此拥有对方想要的锁)

分析:

1)Integer缓存机制

Integer.valueOf(int xxx),该方法为了减少对象的创建,节省内存,会将xxx转化成的Integer对象缓存起来,之后只要是相同的xxx,那么这个方法都会直接从缓存中取出对象来。假设代码中的Integer.valueOf(1)生成的对象是java.lang.Integer@987197,而Integer.valueOf(2)生成的对象是java.lang.Integer@15e293a,那么之后无论调用多少次Integer.valueOf(1),也无论是哪一个线程去调用该方法,返回的都只是同一个对象java.lang.Integer@987197。也就是说上边的这段代码中的Integer.valueOf(i)只会生成两个不同的对象,就是java.lang.Integer@987197和java.lang.Integer@15e293a,而这两个对象也就是我们的锁对象。

2)死锁发生的时机

假设线程"Thread-95"执行到其第一个synchronized块中时(假设刚刚获取了锁对象java.lang.Integer@987197),这时候CPU时间片切换给了线程"Thread-106",而"Thread-106"执行其第一个synchronized块(获取了锁对象java.lang.Integer@15e293a),之后"Thread-106"要执行第二个synchronized块儿来获取锁对象java.lang.Integer@987197,这时候就获取不到了,因为这个锁对象正被"Thread-95"所持有,于是"Thread-106"就阻塞在java.lang.Integer@987197这个锁对象上,这时,假设CPU时间片又切换给了"Thread-95",该线程要执行第二个synchronized块来获取java.lang.Integer@15e293a,就获取不到了,因为该锁对象已被"Thread-106"所持有

3)结果

"Thread-95"持有锁对象java.lang.Integer@987197,阻塞在锁对象java.lang.Integer@15e293a;

"Thread-106"持有锁对象java.lang.Integer@15e293a,阻塞在锁对象java.lang.Integer@987197

3、visualVM

是一块更加全面的GUI监视工具,包含很多插件(需要自己下载),具体的见《深入理解Java虚拟机(第二版)》
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: