第八章 JVM性能监控与故障处理工具(2)
2016-02-08 14:58
453 查看
注意:该篇博客主要记录自《深入理解java虚拟机(第二版)》
说明:关于命令行的JVM性能监控与故障处理工具见《第七章 JVM性能监控与故障处理工具(1)》
1、图像化的故障处理工具
Jconsole
visualVM
2、Jconsole
进入"E:\Java\jdk1.6\bin",双击"jconsole.exe",弹出如下框:
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虚拟机(第二版)》
说明:关于命令行的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虚拟机(第二版)》
相关文章推荐
- -boundingRectWithSize:options:attributes:context:用法
- shell
- Linux入门回顾
- Linux中使用Boxes安装windows7
- Linux下的Nginx安装
- 1.以普通表格型单表为模板定制模块:短信分类维护
- 嵌入式Linux系统的电子书阅读器项目2——Display System
- 关于主线程中自动建立的Looper的思考:主线程中Looper中的轮询死循环为何没有阻塞主线程
- 进入tomcat的app manager界面需要配置的tomcat-users.xml
- tomcat 服务开机自启动
- linux内核的idr学习(二)
- 造轮子:论Top与ROW_NUMBER读取第一页的效率问题
- 使用Linux操作系统命令检查服务器主板上每个内存插槽的内存大小
- 【翻译自mos文章】在使用Linux大页内存的配置中,使用drop_cache时导致的ORA-600 [KGHLKREM1]问题
- 文本绘制附加选项NSStringDrawingOptions的解释
- Linux关机/重启命令
- linux例行性命令
- JAVA企业级应用TOMCAT实战 【转】
- linux Centos6.5使用yum安装mysql
- 《1024伐木累》-小白篇之开发网站,三天!(中篇-3)-总章节十二