【生产案例面试题】JVM调优

写作目的

最近上线了一个需求,遇到了一个JVM报警的问题,很荣幸能遇到,在此分享一下整个调优的过程。

背景

我们是中台服务,我们的甲方就是上游不同的业务。中台原则上是业务和能力分离,但是不可避免的是分不开,所以我们通过SPI的机制让上游的业务实现SPI接口从而执行他们自己的逻辑。本次需求我们上线了一个大需求,要同时发布很多业务方实现的SPI包。我们是灰度发布,发布一台机器后发现频繁的FGC导致监控报警。

补充一下我们的机器规格是4核4G内存和80G磁盘。GC垃圾收集器是CMS和ParNew。

接下来开始进行推理和论证。

推断堆空间有问题

频繁的FGC初步想法就是OOM,比如静态集合无限添加对象。但是去机器上找了一下OOM的Dump文件这个是没找到的,所以说只能手动dump。

jmap -dump:format=b,file=/tmp/myapp_dump.bin pid1234

使用MAT去分析,去找自己的类最多的,发现并没有找到那种一枝独秀特别多的。下面是反例,公司不方便截图
在这里插入图片描述
因为是灰度,所以我们有正常的机器。对比有问题机器和没问题机器新生代和老年带的变化趋势、速成和使用大小,整体是相似的,这块就不符合常理了。类似下面的图
在这里插入图片描述
结论:新生代老年代和正常机器一样,初步推断堆空间正常。

推断元空间有问题

如果不是堆空间引起的FGC,那就是元空间要满了。接着通过arthas的dashboard命令对比,这里发现这个值新老机器差距很大
在这里插入图片描述
那就需要调大元空间

-XX:MetaspaceSize=1500m
-XX:MaxMetaspaceSize=1500mm
修改为
-XX:MetaspaceSize=2048m
-XX:MaxMetaspaceSize=2048m

此时机器再发布后就不会出现FGC了。

结论:元空间小,导致频繁FGC

元空间到底为什么变大

通过JVM的命令,可以看出来加载了哪些类

 jcmd 28818 GC.class_histogram

在这里插入图片描述
那我看上图有什么意义呢?
对比新老机器,可以获得两份加载的类
通过awk命令能洗出来有哪些类,然后通过diff命令就可以看出来不同的类。
在这里插入图片描述

通过分析两个加载的类不同,发现两个问题。

  1. 本次加载的类有本次需求新上的,符合预期。
  2. 里面有很多MethodAccessor,看我的另一篇文章

总结

  • 如果面试回答,你可以说你引入了很多pom,这种场景其实是很常见的。
  • 本文对回答的关键词都做了加深,包括每一步的命令是什么,且能能量化的都用数字表示(比如机器大小)
  • 调大元空间意味着别的会缩小,所以最终方法是充钱,扩大机器的配置。

课外补充

补充一下有意义的jvm启动参数

-XX:ParallelGCThreads=4 (并行收集,几核机器设置几核)
-Xms6g   (调优,设置新生代初始大小)
-Xmx6g   (调优,设置新生代最大值)
-Xmn2g   (调优,设置堆空间大小)
-XX:MetaspaceSize=2048m
-XX:MaxMetaspaceSize=2048m
-XX:MaxDirectMemorySize=1g
-XX:SurvivorRatio=8   (新老年代默认8:1:1)
-XX:+UseConcMarkSweepGC  (使用CMS垃圾收集器)
-XX:CMSMaxAbortablePrecleanTime=5000 (并发标记阶段之后、重新标记阶段之前,就让你执行这么长时间)
-XX:+CMSClassUnloadingEnabled (允许类卸载,比如线上使用内存诊断工具Arthas,用完后会有残留)
-XX:CMSInitiatingOccupancyFraction=80 (老年带到达80%,触发老年代收集)
-XX:+UseCMSInitiatingOccupancyOnly(配合上面参数使用)
-XX:+ExplicitGCInvokesConcurrent (针对System.gc()触发老年带的GC,否则就是fullGC)
-Xloggc:/home/admin/logs/gc.log  (GC日志目录)
-XX:+PrintGCDetails  (GC日志详细细节)
-XX:+PrintGCDateStamps(每个垃圾收集事件发生的确切日期和时间戳)
-XX:+HeapDumpOnOutOfMemoryError  (OOM)
-XX:HeapDumpPath=/home/admin/logs/java.hprof (OOM)

参考

有过JVM调优经验吗【面试题】






阿里淘天Java开发工程师,CSDN博客专家,阿里云博客专家,专注于后端技术的分享。如果你迷茫,不妨来瞅瞅码农的轨迹。

一起学习,共同进步👇👇👇

在这里插入图片描述

相关推荐

  1. JVM篇--JVM高频面试

    2024-04-15 07:12:03       56 阅读
  2. Nginx 面试

    2024-04-15 07:12:03       29 阅读
  3. jvm 参数

    2024-04-15 07:12:03       46 阅读
  4. <span style='color:red;'>JVM</span><span style='color:red;'>调</span><span style='color:red;'>优</span>

    JVM

    2024-04-15 07:12:03      53 阅读
  5. <span style='color:red;'>JVM</span><span style='color:red;'>调</span><span style='color:red;'>优</span>

    JVM

    2024-04-15 07:12:03      50 阅读
  6. <span style='color:red;'>JVM</span><span style='color:red;'>调</span><span style='color:red;'>优</span>

    JVM

    2024-04-15 07:12:03      59 阅读
  7. <span style='color:red;'>JVM</span><span style='color:red;'>调</span><span style='color:red;'>优</span>

    JVM

    2024-04-15 07:12:03      58 阅读

最近更新

  1. docker php8.1+nginx base 镜像 dockerfile 配置

    2024-04-15 07:12:03       94 阅读
  2. Could not load dynamic library ‘cudart64_100.dll‘

    2024-04-15 07:12:03       100 阅读
  3. 在Django里面运行非项目文件

    2024-04-15 07:12:03       82 阅读
  4. Python语言-面向对象

    2024-04-15 07:12:03       91 阅读

热门阅读

  1. Docker搭建Kanzi

    2024-04-15 07:12:03       32 阅读
  2. 【Leetcode|#88.合并两个有序数组】

    2024-04-15 07:12:03       38 阅读
  3. 【Linux】匿名管道实现简单进程池

    2024-04-15 07:12:03       37 阅读
  4. 【设计模式】SOLID设计原则

    2024-04-15 07:12:03       32 阅读
  5. docker swarm 详细安装配置步骤

    2024-04-15 07:12:03       34 阅读
  6. redis zremove删除不掉【bug】

    2024-04-15 07:12:03       28 阅读
  7. 浏览器缓存(强缓存、协商缓存)

    2024-04-15 07:12:03       35 阅读
  8. Android中的Zygote进程介绍

    2024-04-15 07:12:03       25 阅读
  9. 纯Python实现Qt的信号与槽机制

    2024-04-15 07:12:03       31 阅读
  10. 简述框架和函数库的区别

    2024-04-15 07:12:03       38 阅读
  11. typora支持的流程图的语法

    2024-04-15 07:12:03       41 阅读