Java JVM调优五大技能详解
作者:程序员小强
1.什么时候需要JVM调优
- 应用的响应慢、CPU占用高
- 应用吞吐量小,占用内存空间过大
这些表象一般伴随着频繁的垃圾回收,或者OOM。
2.JVM调优一般调什么
- 应用占用的内存(堆内存,元空间内存)
- 新生代老年代的大小,比例。
- 垃圾回收器的选择。
堆内存参数
| -Xms512m |
初始堆大小
默认值:若未设置,初始值将是老年代和年轻代分配制内存之和 |
---|
-Xmx1024m |
年轻代内存相关参数
| -Xmn512m |
新生代的初始值及最大值。
默认值:堆内存的1/4(已经分配的堆内存的1/4)。 |
---|
-XX:NewSize=512m |
-XX:MaxNewSize=512m |
-XX:NewRatio=8 |
比如:-XX:NewRatio=8
表示:老年代内存:年轻代内存=8:1 |
| -XX:SurvivorRatio=8 |
新生代和存活区的比例
-XX:SurvivorRatio=8
表示存活区:新生代=1:8 =》新生代占年轻代的8/10,每个存活区各占年轻代的1/10 |
元空间参数
| -XX:MetaspaceSize |
初始元空间大小
达到该值就会触发垃圾收集进行类型卸载 |
---|
-XX:MaxMetaspaceSize=256m |
3.JVM调优基本步骤
首先在启动程序的时候
3.1添加GC日志相关的参数
-XX:+PrintGC:输出GC日志 -XX:+PrintGCDetails:输出GC的详细日志 -XX:+PrintGCTimeStamps:输出GC的时间戳(以基准时间的形式) -XX:+PrintGCDateStamps:输出GC的时间戳(以日期的形式,如2018-08-29T19:22:48.741-0800) -XX:+PrintHeapAtGC:在进行GC的前后打印出堆的信息 -Xloggc:gc.log:日志文件的输出路径
3.2添加内存溢出与Full gc前快照输出参数
-XX:+HeapDumpOnOutOfMemoryError 发生内存溢出时生成heapdump文件 -XX:+HeapDumpBeforeFullGC 发生Full gc前生成heapdump文件 -XX:HeapDumpPath:指定heapdump输出路径
3.3通过日志确定问题
3.3.1堆内存不足
- 排查是否是设置的堆内存过小,还是内存溢出情况。
- 拿到当时的内存快照,用工具分析 jump用Mat工具分析。
3.3.2频繁Full gc
- 考虑是否是新上线的代码问题,有大对象占用,导致了频繁YGC,进而导致了晋升至年老代的对象增多,老年代达到内存阈值触发 Full gc ;
- 考虑是否是新生代设置太小 ;
总结:
若是代码问题可通过版本控制工具找到本期变更的代码,优化代码
若非代码问题,可适当增加堆内存大小、新生代老年代的大小与比例 , 适当增大新生代内存大小。
4.监控工具
4.1使用jstat 统计gc相关信息
jstat 是 jdk bin 下自带工具,最多的是用来统计gc相关信息,使用步骤如下。
获取进程号 ps -ef|grep 对应进程
例如我想统计jvm-demo.jar(进程号27164)的gc信息,并且每隔3秒统计一次,可以执行以下命令
jstat -gcutil 27164 3000
主要关注以下几个。
s0、s1
:表示两个survior区域的使用百分比e
:eden区域使用百分比o
:老年代使用百分比m
:metaspace(元数据空间)使用百分比ygc
:新生代gc次数ygct
:新生代gc累计总时间fgc
:full gc次数fgct
:full gc累计总时间gct
:gc累计总时间
若要进一步查看上一次GC信息
jstat -gccause 27146 3000
LGCC
:上一次gc的原因,Allocation Failure是新生代满了,进行gcgcc
:当前gc的原因,如果当前没有gc就no gc
4.2使用jmap命令查某时刻的JVM堆信息
使用步骤
- 获取进行 pid ps -ef|grep 对应进程
- 例如我想统计jvm-demo.jar(进程号27164)的信息,并且每隔3秒统计一次,可以执行以下命令
jmap -heap 2865
输出内容示例:
Attaching to process ID 27146, please wait... Debugger attached successfully. Server compiler detected. JVM version is 25.144-b01 using thread-local object allocation. Mark Sweep Compact GC #堆相关的配置信息 Heap Configuration: MinHeapFreeRatio = 40 MaxHeapFreeRatio = 70 MaxHeapSize = 104857600 (100.0MB) NewSize = 10485760 (10.0MB) MaxNewSize = 34930688 (33.3125MB) OldSize = 20971520 (20.0MB) NewRatio = 2 SurvivorRatio = 8 MetaspaceSize = 21807104 (20.796875MB) CompressedClassSpaceSize = 1073741824 (1024.0MB) MaxMetaspaceSize = 17592186044415 MB G1HeapRegionSize = 0 (0.0MB) #堆占用相关的配置信息 Heap Usage: New Generation (Eden + 1 Survivor Space): capacity = 12517376 (11.9375MB) used = 10708296 (10.212226867675781MB) free = 1809080 (1.7252731323242188MB) 85.54745020042539% used Eden Space: capacity = 11141120 (10.625MB) used = 10708272 (10.212203979492188MB) free = 432848 (0.4127960205078125MB) 96.11486098345588% used From Space: capacity = 1376256 (1.3125MB) used = 24 (2.288818359375E-5MB) free = 1376232 (1.3124771118164062MB) 0.0017438616071428572% used To Space: capacity = 1376256 (1.3125MB) used = 0 (0.0MB) free = 1376256 (1.3125MB) 0.0% used tenured generation: capacity = 27684864 (26.40234375MB) used = 27096504 (25.84123992919922MB) free = 588360 (0.5611038208007812MB) 97.87479541167332% used 15431 interned Strings occupying 2044328 bytes.
5.常用的调优工具有哪些?
JDK内置的命令行:jps
(查看jvm进程信息)、jstat
(监视jvm运行状态的,比如gc情况、jvm内存情况、类加载情况等)、jinfo
(查看jvm参数的,也可动态调整)、jmap
(生成dump文件的,在dump的时候会影响线上服务)、jhat
(分析dump的,但是一般都将dump导出放到mat上分析)、jstack
(查看线程的)。
JDK内置的可视化界面:JConsole
、VisualVM
,这两个在QA环境压测的时候很有用。
阿里巴巴开源的arthas:神器,线上调优很方便,安装和显示效果都很友好
总结
本篇文章就到这里了,希望能够给你带来帮助,也希望您能够多多关注脚本之家的更多内容!