JVM 线上故障排查基本操做--内容问题排查


内存问题排查

说完了 CPU 的问题排查,再说说内存的排查,一般,内存的问题就是 GC 的问题,由于 Java 的内存由 GC 管理。有2种状况,一种是内存溢出了,一种是内存没有溢出,但 GC 不健康。数据结构

内存溢出的状况能够经过加上 -XX:+HeapDumpOnOutOfMemoryError 参数,该参数做用是:在程序内存溢出时输出 dump 文件。oracle

有了 dump 文件,就能够经过 dump 分析工具进行分析了,好比经常使用的MAT,Jprofile,jvisualvm 等工具均可以分析,这些工具都可以看出究竟是哪里溢出,哪里建立了大量的对象等等信息。jvm

第二种状况就比较复杂了。GC 的健康问题。工具

一般一个健康的 GC 是什么状态呢?根据楼主的经验,YGC 5秒一次左右,每次不超过50毫秒,FGC 最好没有,CMS GC 一天一次左右。优化

而 GC 的优化有2个维度,一是频率,二是时长。spa

咱们看YGC,首先看频率,若是 YGC 超过5秒一次,甚至更长,说明系统内存过大,应该缩小容量,若是频率很高,说明 Eden 区太小,能够将 Eden 区增大,但整个新生代的容量应该在堆的 30% - 40%之间,eden,from 和 to 的比例应该在 8:1:1左右,这个比例可根据对象晋升的大小进行调整。操作系统

若是 YGC 时间过长呢?YGC 有2个过程,一个是扫描,一个是复制,一般扫描速度很快,复制速度相比而言要慢一些,若是每次都有大量对象要复制,就会将 STW 时间延长,还有一个状况就是 StringTable ,这个数据结构中存储着 String.intern 方法返回的常连池的引用,YGC 每次都会扫描这个数据结构(HashTable),若是这个数据结构很大,且没有通过 FGC,那么也会拉长 STW 时长,还有一种状况就是操做系统的虚拟内存,当 GC 时正巧操做系统正在交换内存,也会拉长 STW 时长。日志

再来看看FGC,实际上,FGC 咱们只能优化频率,没法优化时长,由于这个时长没法控制。如何优化频率呢?对象

首先,FGC 的缘由有几个,1 是 Old 区内存不够,2 是元数据区内存不够,3 是 System.gc(), 4 是 jmap 或者 jcmd,5 是CMS Promotion failed 或者 concurrent mode failure,6 JVM 基于悲观策略认为此次 YGC 后 Old 区没法容纳晋升的对象,所以取消 YGC,提早 FGC。内存

一般优化的点是 Old 区内存不够致使 FGC。若是 FGC 后还有大量对象,说明 Old 区太小,应该扩大 Old 区,若是 FGC 后效果很好,说明 Old 区存在了大量短命的对象,优化的点应该是让这些对象在新生代就被 YGC 掉,一般的作法是增大新生代,若是有大而短命的对象,经过参数设置对象的大小,不要让这些对象进入 Old 区,还须要检查晋升年龄是否太小。若是 YGC 后,有大量对象由于没法进入 Survivor 区从而提早晋升,这时应该增大 Survivor 区,但不宜太大。

上面说的都是优化的思路,咱们也须要一些工具知道 GC 的情况。

JDK 提供了不少的工具,好比 jmap ,jcmd 等,oracle 官方推荐使用 jcmd 代替 jmap,由于 jcmd 确实能代替 jmap 不少功能。jmap 能够打印对象的分布信息,能够 dump 文件,注意,jmap 和 jcmd dump 文件的时候会触发 FGC ,使用的时候注意场景。

还有一个比较经常使用的工具是 jstat,该工具能够查看GC 的详细信息,好比eden ,from,to,old 等区域的内存使用状况。

还有一个工具是 jinfo,该工具能够查看当前 jvm 使用了哪些参数,而且也能够在不停机的状况下修改参数。

包括咱们上面说的一些分析 dump 文件的可视化工具,MAT,Jprofile,jvisualvm 等,这些工具能够分析 jmap dump 下来的文件,看看哪一个对象使用的内存较多,一般是可以查出问题的。

还有很重要的一点就是,线上环境必定要带上 GC 日志!!!

相关文章
相关标签/搜索