线上故障如何快速排查?来看这套技巧大全( 二 )


过滤Tomcat节点的日志 , 发现有OOM的异常,但是重启后 , 有时候Tomcat挂掉后 , 又不会打印如下OOM的异常:
TopicNewController.getTopicSoftList() error="Java heap space From class java.lang.OutOfMemoryError"Appstore_apitomcat2.2.3 获取内存快照在一次OOM发生后立刻抓取内存快照,需要执行命令的用户与JAVA进程启动用户是同一个 , 否则会有异常:
/data/program/jdk/bin/jmap -dump:live,format=b,file=/home/www/jmaplogs/jmap-8001-2.bin 18760ps -ef|grep store.cn.xml|grep -v grep|awk '{print $2}'|xargs /data/program/jdk-1.8.0_11/bin/jmap -dump:live,format=b,file=api.bin内存dump文件比较大 , 有1.4G , 先压缩 , 然后拉取到本地用7ZIP解压 。
linux压缩dump为.tgz 。
在windows下用7zip需要经过2步解压:
.bin.tgz---.bin.tar--.bin2.2.4 分析内存快照文件使用Memory Analyzer解析dump文件 , 发现有很明显的内存泄漏提示 。

线上故障如何快速排查?来看这套技巧大全

文章插图
 
点击查看详情 , 发现定位到了代码的具体某行 , 一目了然:
线上故障如何快速排查?来看这套技巧大全

文章插图
 
查看shallow heap与retained heap能发现生成了大量的Object(810325个对象) , 后面分析代码发现是上报softItem对象超过300多万个对象 , 在循环的时候 , 所有的数据全部保存在某个方法中无法释放 , 导致内存堆积到1.5G , 从而超过了JVM分配的最大数 , 从而出现OOM 。
线上故障如何快速排查?来看这套技巧大全

文章插图
 
java.lang.Object[810325] @ 0xb0e971e0
线上故障如何快速排查?来看这套技巧大全

文章插图
 
2.2.5 相关知识2.2.5.1 JVM内存
线上故障如何快速排查?来看这套技巧大全

文章插图
 
2.2.5.2 内存分配的流程
线上故障如何快速排查?来看这套技巧大全

文章插图
 
如果通过逃逸分析 , 则会先在TLAB分配 , 如果不满足条件才在Eden上分配 。
2.2.4.3 GC
线上故障如何快速排查?来看这套技巧大全

文章插图
 
(1)GC触发的场景
线上故障如何快速排查?来看这套技巧大全

文章插图
 
2)GC Roots
GC Roots有4种对象:
  • 虚拟机栈(栈栈中的本地变量表)中的引用的对象 , 就是平时所指的java对象 , 存放在堆中 。
  • 方法区中的类静态属性引用的对象 , 一般指被static修饰引用的对象 , 加载类的时候就加载到内存中 。
  • 方法区中的常量引用的对象 。
  • 本地方法栈中JNI(native方法)引用的对象 。
(3)GC算法
线上故障如何快速排查?来看这套技巧大全

文章插图
 
  • 串行只使用单条GC线程进行处理 , 而并行则使用多条 。
  • 多核情况下 , 并行一般更有执行效率 , 但是单核情况下 , 并行未必比串行更有效率 。

线上故障如何快速排查?来看这套技巧大全

文章插图
 
  • STW会暂停所有应用线程的执行 , 等待GC线程完成后再继续执行应用线程 , 从而会导致短时间内应用无响应 。
  • Concurrent会导致GC线程和应用线程并发执行 , 因此应用线程和GC线程互相抢用CPU , 从而会导致出现浮动垃圾 , 同时GC时间不可控 。
(4)新生代使用的GC算法
线上故障如何快速排查?来看这套技巧大全

文章插图
 
  • 新生代算法都是基于Coping的 , 速度快 。
  • Parallel Scavenge:吞吐量优先 。
  • 吞吐量=运行用户代码时间 /(运行用户代码时间 + 垃圾收集时间)
(5)老年代使用的GC算法
线上故障如何快速排查?来看这套技巧大全

文章插图
 

线上故障如何快速排查?来看这套技巧大全

文章插图
 
Parallel Compacting
线上故障如何快速排查?来看这套技巧大全

文章插图
 
Concurrent Mark-Sweep(CMS)


推荐阅读