一、Dump文件是什么
你们确定知道咱们java应用的对象的建立是由咱们管,可是回收大多数是由jvm经过必定的算法来自动实现的,如:最少使用、不可达、新生代的复制清除等,也就是jvm会按照你现有对象占用的新生代或老年代的内存比例决定是否进行垃圾回收,每次垃圾回收都是须要STW的,可是当对象非正常产生的时候,jvm是回收不过来的,会形成不应有的对象直接将内存占满甚至超过jvm设置大小,形成系统运行缓慢或者OOM。java
当出现运行缓慢或者OOM的时候,咱们就须要掌握jvm的内存状态来查找咱们系统变慢或者卡顿的缘由。Java官方提供了生成jvm内存快照文件(dump文件)的工具jmap ,使用jmap便可生成。web
同时,咱们还能够经过dump文件分析系统运行时的状况。针对特定卡慢的方法进行优化。算法
一、Dump文件的生成
2.1、Linux生成dump文件
2.1.1、Linux上使用命令生成内存dump文件
一、执行 ps -ef | grep [应用名称] --获取 [pid]
2、执行 jmap -dump:format=b,file=filename [pid] 生成内存的dump文件,生成时间可能较久数据库
2.1.2、Linux上使用命令生成线程dump文件
Jstack [pid] filename 就能够生成线程dump文件。jvm
2.1.3、内存dump文件和线程dump的区别
内存dump文件着重当前应用的jvm的内存被哪些对象占用,线程dump文件着重显示当前应用的各线程的运行状况,容易定位死锁等问题。如图。线程dump:工具
观测线程dump文件的时候要特别注意:java.lang.Thread.State:Blocked,这种状态可能出现了线程死锁,而后形成系统卡顿。测试
所谓的线程死锁:线程T1正在占用R1资源,须要获取R2资源才能执行完成,而后释放R1资源的锁。线程T2正在占用R2资源,须要获取R1资源才能执行完成,而后释放R2资源的锁。这就形成两个线程相互等待对方释放锁资源,线程没法向前执行。解决方式:加1、锁顺序(线程按照必定的顺序加锁)
2、加锁时限(线程尝试获取锁的时候加上必定的时限,超过期限则放弃对该锁的请求,并释放本身占有的锁)
3、死锁检测优化
内存dumpspa
稍后,咱们对内存dump文件进项详细介绍。线程
2.2、在出现OOM时自动保存dump文件
二、经过jvm参数--XX:+HeapDumpOnOutOfMemoryError可让JVM在出现内存溢出时候自动Dump出当前的内存转储快照。
3、Dump使用场景及问题分析思路
上线过程当中可能会遇到各类各样的问题,大多数的问题咱们经过分析日志就能够得出结论,找到缘由。
可是会出现一种问题咱们很难经过日志找到缘由:
系统刚上线各方面都很正常,可是因为某种操做触发或者运行一段时间以后出现接口卡顿,接口响应缓慢超时甚至假死等现象。
这种状况的出现大多伴随着系统硬件资源的使用率上升,如CPU和内存使用率忽然急剧飙升,直接翻倍甚至占满硬件资源。
若是出现系统刚上线应用、接口表现正常,运行一段时间以后出现卡顿缓慢现象,而日志又没有表现出明显错误,或直接出现OOM,咱们须要使用这种排查思路:
首先查看系统硬件资源使用状况,使用top命令可清晰查看,如图:
这是咱们系统正常状况下 947 进程的使用状况,cpu使用率只有12.6 内存只有4.4,当系统出现问题的时候,咱们再看系统的使用状况,如图:
26608与上图947为同一应用,发现cpu使用率直接飙升到100 % 内存使用状况翻倍,注意9.7是占用虚拟机的比例,可是咱们单应用的jvm内存是不能够跟虚拟机的直接比较的,因此短期内翻倍问题已经很大了。
这时候咱们已经能够初步断定jvm的内存管理出现了问题,因为jvm的内存被不正常的对象大量抢占致使系统运行缓慢。
同时,咱们数据中心的每台机器都是有zabbix监控(全部的数据中心都会有硬件资源监控系统,zabbix最为流行),咱们同时能够提取zabbix的记录来作验证,如图咱们举例一台:
咱们能够很清晰的看到在10点到10点12之间内存和CPU(有公司信息就不放了)的状况发生了急剧的增加,可是这和进入咱们系统的流量不是正常的比例,由此咱们能够判定咱们的代码的jvm的内存管理出现了问题,即大几率出现了内存溢出。
关于内存溢出:你们确定知道咱们java应用的对象的建立是由咱们管,可是回收大多数是由jvm经过必定的算法来实现的,如:最少使用、不可达、新生代的复制清除等等,也就是jvm会按照你现有对象占用的新生代或老年代的内存比例决定是否进行垃圾回收,每次垃圾回收都是须要STW的,可是当对象非正常产生的时候,jvm是回收不过来的,会形成不应有的对象直接占满、超过jvm设置大小,形成系统运行缓慢或者OOM。
若是出现了上述状况,咱们必须、必定要保存dump文件!
由于dump是惟一能够反映java进程的内存状况的文件,也只有拿到当时的dump文件咱们才能够分析出来形成咱们本次上线的运行缓慢的缘由,操做方式如图(测试环境):
1、执行 ps -ef | grep [应用名称] --获取 [pid]
2、执行 jmap -dump:format=b,file=website.dump [pid] 生成dump文件,生成时间可能较久
先拿到该应用的pid,而后借助于jdk的jmap工具获取dump文件。拿到dump文件以后就能够对应用的内存状况进行分析。
Dump文件须要借助特殊的工具进行分析,如今比较流行的是IBM Memory Analyzer和Eclipse Memory Analysis(MAT),咱们用MAT来作演示。
这是咱们系统运行正常时的截图,如图:
这是咱们系统运行非正常的截图,如图:
在系统运行卡顿时,咱们的char,String 的对象数量以及占用的内存空间发生了20倍的增加,同时咱们本身的一个对象产生了202万个,一个对象的正常建立是绝对不可能出现这么多的示例,因此能够肯定使用该对象的地方的建立出现了问题,咱们能够依此去代码中查找问题。
同时Oracle的Driver对象也出现了不正常的增加,这将极大的占据数据库资源,致使其余方法的数据库链接出现问题。因此咱们能够从代码中寻找即便用了该对象,有链接了数据库的地方。
同时除了这种运行变慢的,遇到OOM时,咱们也能够经过对dump文件的分析查找到不合理占据内存的对象,从而定位到问题代码。
另外,若是系统变慢,咱们日志和内存dump文件都没看到问题以后,咱们就须要观察Thread Dump文件,看是否有线程死锁的问题。
正常的应用千篇一概,有趣的问题万里挑一。