jvm案例和排查套路

1. 排查FGC问题的实践指南:https://mp.weixin.qq.com/s/I1fp89Ib2Na1-vjmjSpsjQ

 1. 清楚从程序角度,有哪些原因导致FGC? 

  • 大对象:系统一次性加载了过多数据到内存中(比如SQL查询未做分页),导致大对象进入了老年代。

  • 内存泄漏:频繁创建了大量对象,但是无法被回收(比如IO对象使用完后未调用close方法释放资源),先引发FGC,最后导致OOM.

  • 程序频繁生成一些长生命周期的对象,当这些对象的存活年龄超过分代年龄时便会进入老年代,最后引发FGC. (即本文中的案例)

  • 程序BUG导致动态生成了很多新类,使得 Metaspace 不断被占用,先引发FGC,最后导致OOM.

  • 代码中显式调用了gc方法,包括自己的代码甚至框架中的代码。

  • JVM参数设置问题:包括总内存大小、新生代和老年代的大小、Eden区和S区的大小、元空间大小、垃圾回收算法等等。

2. 清楚排查问题时能使用哪些工具

  • 公司的监控系统:大部分公司都会有,可全方位监控JVM的各项指标。

  • JDK的自带工具,包括jmap、jstat等常用命令:

    # 查看堆内存各区域的使用率以及GC情况

    jstat -gcutil -h20 pid 1000

    # 查看堆内存中的存活对象,并按空间排序

    jmap -histo pid | head -n20

    # dump堆内存文件

    jmap -dump:format=b,file=heap pid

  • 可视化的堆内存分析工具:JVisualVM、MAT等

3. 排查指南

  • 查看监控,以了解出现问题的时间点以及当前FGC的频率(可对比正常情况看频率是否正常)

  • 了解该时间点之前有没有程序上线、基础组件升级等情况。

  • 了解JVM的参数设置,包括:堆空间各个区域的大小设置,新生代和老年代分别采用了哪些垃圾收集器,然后分析JVM参数设置是否合理。

  • 再对步骤1中列出的可能原因做排除法,其中元空间被打满、内存泄漏、代码显式调用gc方法比较容易排查。

  • 针对大对象或者长生命周期对象导致的FGC,可通过 jmap -histo 命令并结合dump堆内存文件作进一步分析,需要先定位到可疑对象。

  • 通过可疑对象定位到具体代码再次分析,这时候要结合GC原理和JVM参数设置,弄清楚可疑对象是否满足了进入到老年代的条件才能下结论。

 

YGC: 

经典排查案例:https://mp.weixin.qq.com/s/O0l-d928hr994OpSNw3oow

1.收到超时告警,调用服务超时。查看服务监控耗时变长,从平时的几十毫秒完成变为百几毫秒。

2.摘掉一个节点,通过命令dump了堆内存文件保留现场

     jmap -dump:format=b,file=heap pid

3.查看jvm参数配置

    ps aux | grep "applicationName=adsearch"

   jmap -heap pid 查到:新生代的Eden区为1.6G,S0和S1区均为0.2G

4.因为都没有任何改动,所以和代码有关。

5.通过工具分析dump的堆文件,看结构堆中是否有大对象,然后一直不回收。

  (1)看外部接口:使用static的map做新旧数据转换,但是内存也就100m,后面都会到老年代。

 (2)在分析dump文件。长周期对象积累过多,或者锁竞争严重导致线程阻塞,局部变量生命周期变长。

  其他团队引用apollo包装了下供团队使用,但是读取配置时候getconfig方法一直add一个的list(虽然是静态的,但是调用方法时候去添加值,所以就在年轻代里面)。然后没有去重。

很多团队都用这个apollo引用配置,然后积累的数据越来越多。

6.回归引用旧版本,用单台测试,发现正常。确定这个原因(外部团队使用super-pom业务无感知的发布最新版本)

猜你喜欢

转载自blog.csdn.net/qq_39809613/article/details/107353733