分享

史上最全最详细的JVM优化方案---建议收藏

 昵称34195792 2022-05-13
1.1. 概述

1.2. 背景

系统运行有时会出现一些大大小小的JVM问题,比如cpu load过高、请求延迟、tps降低等,甚至出现内存泄漏(每次垃圾收集使用的时间越来越长,垃圾收集频率越来越高,每次垃圾收集清理掉的垃圾数据越来越少)、内存溢出导致系统崩溃,因此需要对JVM进行调优,使得程序在正常运行的前提下,获得更高的用户体验和运行效率。
通过对项目进行jvm信息监控,输出监控数据,通过JVM分析、调优,提升系统性能。
评估GC的性能指标:
吞吐量:程序代码运行时间占总时间的比例(总运行时间 = 程序的运行时间 + 内存回收的时间)
暂停时间:执行垃圾收集时,程序的工作线程被暂停的时间(stw 时间)
内存大小:堆内存大小
程序的目标不同,调优时所考虑的方向也不同,在调优之前,必须要结合实际场景,有明确的的优化目标,找到性能瓶颈,对瓶颈有针对性的优化,最后进行测试,通过各种监控工具确认调优后的结果是否符合目标。

1.3. 目标

1.3.1. JVM调优

JVM调优。

2. JVM性能跟踪

2.1. JVM性能跟踪总体方案

通过采集JVM数据,对JVM各项指标进行详细分析,进行JVM性能跟踪,为JVM调优提供依据。

图片

2.1.1. 应用运行时间查看

1、 获取应用pid
命令:ps –ef|grep java
通过终端登录服务器,输入命令,获取应用pid
2、 查看应用运行时间
命令:ps -p pid -o etime >> elapsed.log &
查看应用具体的堆信息,pid为上一步获取的应用pid
3、 应用运行时间关注点
1) 系统启动到当前节点运行的时间,用于配合后续GC分析

2.1.2. 堆信息查看

1、 获取应用pid
命令:ps –ef|grep java
通过终端登录服务器,输入命令,获取应用pid
2、 查看应用具体堆信息
命令:jmap -heap pid >> jmapheap.log
查看应用具体的堆信息,pid为上一步获取的应用pid
3、 性能跟踪关注点
2) 年轻代ED和S0、S1的占比情况
3) 年轻代和老年代堆内存占比情况
4) S0、S1的实际大小

2.1.3. 回收信息查看

1、 获取应用pid
命令:ps –ef|grep java
通过终端登录服务器,输入命令,获取应用pid
2、 查看应用具体堆信息
命令:jstat -gc pid 100 18000 >> jstatgc.log &
查看应用具体的回收信息,时间为5个小时,频率为每100毫秒,pid为上一步获取的应用pid
3、 GC信息跟踪关注点
1) YGC的频率
2) YGC的总耗时、单次耗时
3) FGC的频率
4) FGC的总耗时、单次耗时
5) GC总耗时
4、 jstat各项参数说明
1) S0C: 年轻代中第一个survivor(幸存区)的容量(字节)
2) S1C: 年轻代中第二个survivor(幸存区)的容量(字节)
3) S0U: 年轻代中第一个survivor(幸存区)目前已使用空间(字节)
4) S1U: 年轻代中第二个survivor(幸存区)目前已使用空间(字节)
5) EC: 年轻代中Eden(伊甸园)的容量(字节)
6) EU: 年轻代中Eden(伊甸园)目前已使用空间(字节)
7) OC: Old代的容量(字节)
8) OU: Old代目前已使用空间(字节)
9) MC: 方法区大小(字节)
10) MU: 方法区使用大小(字节)
11) CCSC: 压缩类空间大小(字节)
12) CCSU: 压缩类空间使用大小(字节)
13) YGC: 从应用程序启动到采样时年轻代中gc次数
14) YGCT: 从应用程序启动到采样时年轻代中gc所用时间(s)
15) FGC: 从应用程序启动到采样时old代(全gc)gc次数
16) FGCT: 从应用程序启动到采样时old代(全gc)gc所用时间(s)
17) GCT: 从应用程序启动到采样时gc用的总时间(s)

2.1.4. dump文件收集

1、 获取应用pid
命令:ps –ef|grep java
通过终端登录服务器,输入命令,获取应用pid
2、 获取dump文件
命令:jmap -dump:format=b,
file=dump.dump pid &
获取dump文件,利用分析工具进行分析,MAT,jvisualvm等。
需要注意dump会有服务暂停或卡顿,生产环境dump必须进行影响评估。

2.1.5. 存活对象分析

1、 获取应用pid
命令:ps –ef|grep java
通过终端登录服务器,输入命令,获取应用pid
2、 获取dump文件,dump会有服务暂停或卡顿,生产环境dump必须进行影响评估。
命令:jmap -dump:format=b,
file=/u02/applications/jvm-track/track.dump pid
dump文件获取,pid为上一步获取的应用pid
3、 拿到dump文件,可借助分析工具进行分析。以MAT工具为例:

图片

查看存活对象主要分布。

2.1.6. Dominator树分析

1、 获取应用pid
命令:ps –ef|grep java
通过终端登录服务器,输入命令,获取应用pid
2、 获取dump文件,dump会有服务暂停或卡顿,生产环境dump必须进行影响评估。
命令:jmap -dump:format=b,
file=/u02/applications/jvm-track/track.dump pid
dump文件获取,pid为上一步获取的应用pid
3、 拿到dump文件,可借助分析工具进行分析。以MAT工具为例:

图片

查看Dominator tree进行对象分析浅堆、深堆。

2.1.7. 内存泄露检测

1、 获取应用pid
命令:ps –ef|grep java
通过终端登录服务器,输入命令,获取应用pid
2、 获取dump文件,dump会有服务暂停或卡顿,生产环境dump必须进行影响评估。
命令:jmap -dump:format=b,
file=/u02/applications/jvm-track/track.dump pid
dump文件获取,pid为上一步获取的应用pid
3、 拿到dump文件,可借助分析工具进行分析。以MAT工具为例:

图片

MAT提供了自动检测内存泄漏,以及统计堆快照内对象分布情况的工具。如图展示了内存泄漏检测工具的使用方法。选择菜单中的LeakSuspects命令,MAT会自动生成一份报告。这份报告罗列了系统内可能存在内存泄漏的问题点。

2.1.8. 大对象查看

1、 获取应用pid
命令:ps –ef|grep java
通过终端登录服务器,输入命令,获取应用pid
2、 获取dump文件,dump会有服务暂停或卡顿,生产环境dump必须进行影响评估。
命令:jmap -dump:format=b,
file=/u02/applications/jvm-track/track.dump pid
dump文件获取,pid为上一步获取的应用pid
3、 拿到dump文件,可借助分析工具进行分析。以MAT工具为例:

图片

查看系统中占用内存最大的几个对象,如果应用程序发生内存泄漏,那么泄漏的对象通常会在堆快照中占据很大的比重。查看和分析堆快照中最大的对象具有较高的价值。

在MAT中,可以自动查找并显示消耗内存最多的几个对象。如上图所示,通过选择TopConsumers命令,可以获取大对象报告。

2.1.9. 线程分析

1、 获取应用pid
命令:ps –ef|grep java
通过终端登录服务器,输入命令,获取应用pid
2、 获取dump文件,dump会有服务暂停或卡顿,生产环境dump必须进行影响评估。
命令:jmap -dump:format=b,
file=/u02/applications/jvm-track/track.dump pid
dump文件获取,pid为上一步获取的应用pid
3、 拿到dump文件,可借助分析工具进行分析。以MAT工具为例:

图片

在堆快照中,还包括当前的线程信息,通过MAT可以查看这些信息。如上图通过ThreadDetails、ThreadOverview和ThreadStacks这3个命令,可以根据当前堆快照中的所有线程及线程引用的对象,查看线程详情进行分析。

2.1.10. 集合使用情况分析

1、 获取应用pid
命令:ps –ef|grep java
通过终端登录服务器,输入命令,获取应用pid
2、 获取dump文件,dump会有服务暂停或卡顿,生产环境dump必须进行影响评估。
命令:jmap -dump:format=b,
file=/u02/applications/jvm-track/track.dump pid
dump文件获取,pid为上一步获取的应用pid
3、 拿到dump文件,可借助分析工具进行分析。以MAT工具为例:

图片

可以查看数组、集合的填充率;可以观察集合内的数据;也可以分析哈希表的冲突率。

通过对集合使用情况进行分析,可以更好地了解系统的内存使用情况,查找浪费的内存空间。
选择CollectionFillRatio命令,可以展示给定集合的填充率。如图所示为该功能的输出结果,其中显示了填充率为0、20%以下、80%以下和100%以下的集合个数。
通过选择HashEntries命令,可以查看Hash表的内容。还可以进一步分析它们的引用情况和其他具体信息。

2.1.11. JVM跟踪参考脚本

JVM信息采集脚本,可根据具体需要观察内容,进行脚本调整:

图片

3. 优化详细方案

3.1. 优化总体方案

根据性能跟踪、分析,进行JVM调优。优化方案需要根据压测结果对比最终进行调整。

3.1.1. 选择合适垃圾收集器

可参考:堆内存4G以下可以用parallel,4-8G可以用ParNew + CMS。
JDK8默认采用parallel。

3.1.2. 堆内初始值设置

jvm参数的初始值和最大值设置一样,避免扩容时消耗性能。
-Xms4096m –Xmx4096m

3.1.3. 元空间设置

元空间的大小参数必须要设置,默认是21M,但是它会自动扩容,元空间满了也会触发fullGC,所以一开始就设置好,避免扩容和触发FullGC。
-XX:MetaspaceSize=256M -XX:MaxMetaspaceSize=256M

3.1.4. 年轻代、老年代占比

默认年轻代:老年代是1:2,可以调整为1:1。
尽可能让对象都在新生代里分配和回收,尽可能别让太多对象频繁进入老年代,避免频繁对老年代进行垃圾回收,同时给系统充足的内存大小,避免新生代频繁进行垃圾回收。
扩大年轻代的空间,避免触发对象动态年龄判定机制,尽量避免对象进入老年代,触发FullGC,也可以减少minorGC的频率。
如果用parallel,则需要显式的指定比例,parallel默认会动态调整。
-XX:-UseAdaptiveSizePolicy -XX:NewRatio=2

3.1.5. Eden、S0、S1占比

eden区和s0、s1默认是8:1:1,可以调整为6:1:1
尽量让每次Young GC后的存活对象小于Survivor区域的50%,都留在年轻代中,避免对象动态年龄判定的触发。尽量别让对象进入老年代,减少FullGC频率,避免频繁fullGC对性能影响。(FullGC时间长,会STW)。
如果用parallel,则需要显式的指定比例,parallel默认会动态调整。
-XX:-UseAdaptiveSizePolicy -XX:SurvivorRatio=6

3.1.6. 晋升老年代的最大年龄阈

-XX:MaxTenuringThreshold=15

3.1.7. 开启GC日志

-XX:+PrintGCDetails
-XX:+PrintGCDateStamps
-XX:+PrintHeapAtGC
-XX:+PrintTenuringDistribution

3.1.8. 调优参数

需要对下列参数进行调优:
-Xms2048m -Xmx2048m
-XX:-UseAdaptiveSizePolicy -XX:NewRatio=1 -XX:SurvivorRatio=6
-XX:MetaspaceSize=256M -XX:MaxMetaspaceSize=256M
-XX:+PrintGCDetails -XX:
+PrintGCDateStamps
-XX:+PrintHeapAtGC
-XX:+PrintTenuringDistribution
-XX:+PrintGCDetails
-XX:+PrintGCDateStamps
-XX:+PrintHeapAtGC
-XX:+PrintTenuringDistribution

3.1.9. 参考参数

4核8G,JDK1.8参数参考,具体要以实际项目及调优结果进行设置:
-Xms4096m
-Xmx4096m
-Xmn3072m
-XX:MetaspaceSize=256m
-XX:MaxMetaspaceSize=256m
-XX:+UseParNewGC
-XX:+UseConcMarkSweepGC
-XX:CMSInitiatingOccupancyFraction=92
-XX:+UseCMSCompactAtFullCollection
-XX:CMSFullGCsBeforeCompaction=0
-XX:+CMSParallelInitialMarkEnabled  
-XX:+CMSScavengeBeforeRemark
-XX:+DisableExplicitGC            
-XX:+PrintGCDateStamps
-XX:+PrintGCDetails
-Xloggc:gc.log
-XX:+HeapDumpOnOutOfMemoryError
-XX:HeapDumpPath=/usr/local/dumdir

4. 验证方案

4.1. 优化验证

通过优化前后堆信息、GC时间、频率进行验证。

4.1.1. 调优验证

通过监控堆内存情况,GC详细信息进行验证,验证时间为1个小时。收集堆内存及GC信息。参照2.1JVM性能跟踪总体方案进行验证。

    本站是提供个人知识管理的网络存储空间,所有内容均由用户发布,不代表本站观点。请注意甄别内容中的联系方式、诱导购买等信息,谨防诈骗。如发现有害或侵权内容,请点击一键举报。
    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约

    类似文章 更多