版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/GoGleTech/article/details/84111933
先上图,下面是一个线程Dump:
1、线程Dump的各种概念:
线程的状态:
- NEW:未启动,不会出现在Dump中
- RUNNABLE:在虚拟机中执行的
- BLOCKED:受阻塞并等待在监视器锁
- WAITTING:无限期等待另一个线程执行特定的操作
- TIMED_WAITTING:有时限的等候另一个线程执行特定的操作
- TERMINATED:已退出
什么是监视器:
面向对象锁控制访问这个锁的线程的一个线程。
调用修饰:
- locked <地址> 目标:注意临界区对象锁可重入,线程状态为RUNNABLE
- waitting to lock <地址> 目标:还没有获得锁,进入区等待,线程状态为BLOCKED
- waitting on <地址> 目标:获得锁了,等待区等待,线程状态为WAITTING,TIMED_WAITTING
- parking to wait for <地址> 目标:线程原语,随current包出现,与synchronized体系不同
线程动作
- runnable:线程状态为RUNNABLE
- in Object.wait():等待区等待,线程状态为WAITTING或TIMED_WAITTING
- waitting for monitor entry:进入区等待,线程状态为BLOCKED
- waitting on condition:等待区等待,被park
- sleeping:休眠的线程,调用了Thread.sleep()
2、分析线程Dump的入手点
1、进入区等待:BLOCKED、waitting to lock、waitting for monitor entry,这些词表名代码层面已经存在冲突。
2、持续进行的IO:一般来说被捕捉到的runnable的IO调用都是有问题的,如runnable中有JDBC链接的代码
3、非线程调度的等待区等待:in Object.wait()(情况1可能会导致这个情况,造成大量线程堆积)
3、“死锁”问题的解决办法
1、在最可能死锁的时间点制作Dump
2、找出引起大量线程阻塞的线程
扫描二维码关注公众号,回复:
5448665 查看本文章
3、找出该线程阻塞的原因
4、阅读代码,遍历其他阻塞或等待的线程,以及它之前的调用是否会造成这个线程的等待
4、注意
排除GC干扰,Full GC时所有线程都会被阻塞住,
- 查看线程Dump时,首先查看内存使用情况
- 使用命令“-verbose:gc”,观察是否有Full GC字样
5、什么情况下需要分析堆Dump
内存不足、GC异常、怀疑代码内存泄漏,这时需要制作堆Dump,找出生命周期的错误关联对象以及相关代码。
6、内存模型
年轻代(Young Generation,包括Eden space、From space、To space)
年老代(Old Generation)
永久代(PermGen space)
两种GC:
- YoungGen GC:Minor GC
- Full GC:Major GC
7、内存泄漏和内存溢出
- 内存泄漏:好比画画时把整个本都画满了,没地方画了。
一个对象持有一个引用永远不释放,导致声明周期过长,这样持有的对象对了,内存就不够用了,这样就会频繁GC - 内存溢出:画画时把一整页都画满了,都画到桌子上了。
8、常见错误
- out of MemoryError:GC overhead limit exceed
回收时间占系统运行时间的98%以上,极有可能是内存泄漏导致的。