JVM调优工具以及调优实战
# 调优工具以及调优实战
# JVM参数调优
java -XX:+UseContainerSupport -XX:MaxRAMPercentage=60.0 -XX:InitialRAMPercentage=60.0 -XX:MinRAMPercentage=60.0 -XX:NewRatio=2 -Xss512k -XX:MetaspaceSize=256M -XX:MaxMetaspaceSize=512M -Djava.awt.headless=true -d64 -server -Djava.awt.headless=true -Djava.net.preferIPv4Stack=true -Djavax.servlet.request.encoding=UTF-8 -Dfile.encoding=UTF-8 -XX:+AlwaysPreTouch -XX:+UseConcMarkSweepGC -XX:CMSInitiatingOccupancyFraction=75 -XX:+UseCMSInitiatingOccupancyOnly -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=/demo-api/logs/demo-api/ -jar demo-api-1.0.1-RELEASE.jar --server.port=8080 --management.server.port=8070 --apollo.meta=http://configserver:8080
1
-XX:+UseContainerSupport
: 启用容器支持,允许JVM自动检测容器环境并调整内存使用以适应容器的限制。-XX:MaxRAMPercentage=60.0
: 设置JVM可用内存的最大百分比为60%,限制JVM在物理内存中可以使用的最大比例。-XX:InitialRAMPercentage=60.0
: 设置JVM初始内存的百分比为60%,用于指定JVM在启动时分配的内存比例。-XX:MinRAMPercentage=60.0
: 设置JVM最小内存的百分比为60%,指定JVM在运行时所需的最小内存比例。-XX:NewRatio=2
: 表示新生代和老年代的比例为 1:2,也就是新生代占整个堆内存的1/3,而老年代占2/3。-Xss512k
: 设置线程栈的大小为512KB,影响每个线程的栈大小。-XX:MetaspaceSize=256M
: 设置Metaspace的初始大小为256MB。-XX:MaxMetaspaceSize=512M
: 设置Metaspace的最大大小为512MB。-Djava.awt.headless=true
: 设置Java运行时为无头模式,用于在没有图形界面的环境中运行。-d64
: 指示JVM在64位模式下运行。-server
: 指示JVM以服务器模式运行,通常用于生产环境,以获得更好的性能。-Djava.net.preferIPv4Stack=true
: 设置JVM偏好使用IPv4协议栈。-Djavax.servlet.request.encoding=UTF-8
: 设置Servlet请求的编码为UTF-8。-Dfile.encoding=UTF-8
: 设置文件编码为UTF-8。-XX:+AlwaysPreTouch
: 指示JVM在启动时分配并预触摸所有堆内存,以确保内存已分配。-XX:+UseConcMarkSweepGC
: 启用并发标记清除垃圾收集器(Concurrent Mark-Sweep GC)。-XX:CMSInitiatingOccupancyFraction=75
: 设置CMS垃圾收集器的触发阈值为75%。-XX:+UseCMSInitiatingOccupancyOnly
: 使用CMS的触发阈值来触发垃圾收集,而不使用其他条件。-XX:+HeapDumpOnOutOfMemoryError
: 在发生内存溢出错误时生成堆转储文件。-XX:HeapDumpPath=/demo-api/logs/demo-api/
: 指定堆转储文件的保存路径为/demo-api/logs/demo-api/
。-jar demo-api-1.0.1-RELEASE.jar
: 启动一个包含demo-api-1.0.1-RELEASE.jar
的Java应用程序。--server.port=8080
: 指定应用程序的HTTP端口为8080。--management.server.port=8070
: 指定管理端口为8070。--apollo.meta=http://configserver:8080
: 指定Apollo配置中心的元数据地址为http://configserver:8080
。
参数调优
-XX:MetaspaceSize=200M -XX:MaxMetaspaceSize=400M -XX:+UseContainerSupport -XX:MaxRAMPercentage=50.0 -XX:InitialRAMPercentage=50.0 -XX:MinRAMPercentage=50.0 -Xss512k -XX:+UseConcMarkSweepGC -XX:CMSInitiatingOccupancyFraction=75 -XX:+UseCMSInitiatingOccupancyOnly -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=/tmp/
1
# JVM参数解析:
-XX:MetaspaceSize=200M
: 设置Metaspace的初始大小为200MB。Metaspace是Java 8及更高版本中用于存储类元数据的区域。-XX:MaxMetaspaceSize=400M
: 设置Metaspace的最大大小为400MB。这是Metaspace允许增长到的最大大小。-XX:+UseContainerSupport
: 启用容器支持。这个选项允许JVM自动检测容器环境并调整内存使用,以便更好地适应容器的限制。-XX:MaxRAMPercentage=50.0
: 设置JVM可用内存的最大百分比为50%。这个选项用于限制JVM在整个物理内存中可以使用的最大比例。-XX:InitialRAMPercentage=50.0
: 设置JVM初始内存的百分比为50%。这个选项用于指定JVM在启动时分配的内存比例。-XX:MinRAMPercentage=50.0
: 设置JVM最小内存的百分比为50%。这个选项用于指定JVM在运行时所需的最小内存比例。-Xss512k
: 设置线程栈的大小为512KB。这影响每个线程的栈大小。-XX:+UseConcMarkSweepGC
: 启用并发标记清除垃圾收集器(Concurrent Mark-Sweep GC)。这是一种用于管理Java堆内存中的垃圾的垃圾收集器。-XX:CMSInitiatingOccupancyFraction=75
: 设置CMS(Concurrent Mark-Sweep)垃圾收集器的触发阈值为75%。当堆内存占用达到这个阈值时,CMS开始执行垃圾收集。-XX:+UseCMSInitiatingOccupancyOnly
: 使用CMS的触发阈值来触发垃圾收集,而不使用其他条件。-XX:+HeapDumpOnOutOfMemoryError
: 在发生内存溢出错误时生成堆转储(heap dump)文件。堆转储文件包含了内存中的对象快照,用于分析问题。-XX:+CMSParallelRemarkEnabled
:并行执行CMS的remark阶段。-XX:+ScavengeBeforeFullGC
:在执行Full GC之前先执行Minor GC。-XX:+CMSScavengeBeforeRemark
:在CMS的remark阶段之前先执行Minor GC。-XX:ParallelCMSThreads=4
:并行执行CMS的线程数设置为4。-XX:HeapDumpPath=/tmp/
: 指定堆转储文件的保存路径为/tmp/
。堆转储文件将保存在该目录下。
# JVM参数分析:
- Metaspace: 为Metaspace设置的初始大小为200M,最大大小为400M。这通常是足够的,除非有很多动态生成的类或使用了大量的第三方库。
- RAM使用: 设置了
UseContainerSupport
,这意味着JVM会考虑容器的限制。为JVM堆设置的RAM百分比是50%,这意味着JVM会使用容器可用RAM的50%作为其最大堆大小。- 线程堆栈大小: 设置的线程堆栈大小为512k,这对大多数应用程序来说是足够的。
- GC: 您选择了
UseConcMarkSweepGC
,这是一个并发标记-清除垃圾收集器,适用于响应时间要求严格的应用程序。- Heap Dump: 在OutOfMemoryError时,选择了生成堆转储,并将其保存在
/tmp/
目录下。
# 输出GC日志
# 必备
-XX:+PrintGCDetails
-XX:+PrintGCDateStamps
-XX:+PrintTenuringDistribution
-XX:+PrintHeapAtGC
-XX:+PrintReferenceGC
-XX:+PrintGCApplicationStoppedTime
# 可选
-XX:+PrintSafepointStatistics
-XX:PrintSafepointStatisticsCount=1
# GC日志输出的文件路径
-Xloggc:/path/to/gc-%t.log
# 开启日志文件分割
-XX:+UseGCLogFileRotation
# 最多分割几个文件,超过之后从头文件开始写
-XX:NumberOfGCLogFiles=14
# 每个文件上限大小,超过就触发分割
-XX:GCLogFileSize=100M
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
# Arthas
# dashboard
# Arthas指标分析:
- 操作系统: 您的操作系统是Linux,版本为5.4.253-167.359.amzn2.x86_64,JVM版本为1.8.0_265。
- 线程: 大部分线程的CPU使用率都很低,没有明显的CPU瓶颈。
- 内存:
- 堆内存使用了732M,总共1013M,这意味着您的应用程序使用了大约72%的堆内存。
- Eden区使用了135M,总共320M。
- Old区使用了591M,总共683M。
- 非堆内存使用了238M,总共254M。
- Metaspace使用了154M,总共167M。
- GC:
- 年轻代GC(ps_scavenge)运行时间为10647ms。
- 老年代GC(ps_marksweep)运行了23次,总时间为10488ms。
# 调优建议:
- 内存调整: 考虑到堆内存使用了大约72%,可以考虑增加
MaxRAMPercentage
的值,例如设置为60%或70%,以提供更多的堆内存给应用程序。 - GC策略: 当前使用的是CMS垃圾收集器,如果发现应用程序的响应时间受到GC的影响,可以考虑切换到G1垃圾收集器,它在Java 8中也是可用的,并且通常提供更好的响应时间。
- Metaspace: 考虑到Metaspace使用了接近其上限的内存,您可以考虑增加
MaxMetaspaceSize
的值,例如设置为500M。 - 监控: 继续使用Arthas或其他监控工具来监控应用程序的性能,特别是GC活动和内存使用情况。
- 代码优化: 考虑对应用程序代码进行性能分析,找出可能的瓶颈或不必要的资源使用,并进行优化。
# jvm调优命令工具
# jps查看进程ID
# jmap
JVM Memory Map命令用于生成heap dump文件,还可以查询finalize执行队列、Java堆和永久代的详细信息,如当前使用率、当前使用的是哪种收集器等
jmap
pid 参数如下:
-heap:打印jvm heap的情况
-histo:打印jvm heap的直方图。其输出信息包括类名,对象数量,对象占用大小。
-histo:live :只打印存活对象的情况
-permstat:打印permanent generation heap情况
jmap -histo pid
- 查看内存信息,实例个数以及占用内存大小
jmap -heap pid
- 堆信息
jmap ‐dump:format=b,file=eureka.hprof 14660
- 堆内存dump
# jstack
用于查看线程状态
jstack pid
- jstack加进程id查找死锁
jstack找出占用cpu最高的线程堆栈信息
- 使用命令top -p <pid> ,显示你的java进程的内存情况,pid是你的java进程号,比如19663
- 按H,获取每个线程的内存情况
- 找到内存和cpu占用最高的线程tid,比如19664
- 转为十六进制得到 0x4cd0,此为线程id的十六进制表示
- 执行 jstack 19663|grep -A 10 4cd0,得到线程堆栈信息中 4cd0 这个线程所在行的后面10行,从堆栈中可以发现导致cpu飙高的调 用方法
- 查看对应的堆栈信息找出可能存在问题的代码
# jinfo
用来查看正在运行的java应用程序的扩展参数(JVM中-X标示的参数),甚至支持在运行时修改部分参数。
jinfo -flags pid
- 查看jvm的参数
jinfo -sysprops pid
- 查看jvm的参数
# jstat
jstat命令可以查看堆内存各部分的使用量,以及加载类的数量。 命令的格式如下: jstat [-命令选项] [vmid] [间隔时间(毫秒)] [查询次数]
jstat -gc pid
- 可以评估程序内存使用及GC压力整体情况
- S0C:第一个幸存区的大小,单位KB
- S1C:第二个幸存区的大小
- S0U:第一个幸存区的使用大小
- S1U:第二个幸存区的使用大小
- EC:伊甸园区的大小
- EU:伊甸园区的使用大小
- OC:老年代大小
- OU:老年代使用大小
- MC:方法区大小(元空间)
- MU:方法区使用大小
- CCSC:压缩类空间大小
- CCSU:压缩类空间使用大小
- YGC:年轻代垃圾回收次数
- YGCT:年轻代垃圾回收消耗时间,单位s
- FGC:老年代垃圾回收次数
- FGCT:老年代垃圾回收消耗时间,单位s
- GCT:垃圾回收消耗总时间,单位s
jstat -gccapacity pid
- 堆内存统计
- NGCMN:新生代最小容量
- NGCMX:新生代最大容量
- NGC:当前新生代容量
- S0C:第一个幸存区大小
- S1C:第二个幸存区的大小
- EC:伊甸园区的大小
- OGCMN:老年代最小容量
- OGCMX:老年代最大容量
- OGC:当前老年代大小
- OC:当前老年代大小
- MCMN:最小元数据容量
- MCMX:最大元数据容量
- MC:当前元数据空间大小
- CCSMN:最小压缩类空间大小
- CCSMX:最大压缩类空间大小
- CCSC:当前压缩类空间大小
- YGC:年轻代gc次数
- FGC:老年代GC次数
jstat -gcnew pid
- 新生代垃圾回收统计
- S0C:第一个幸存区的大小
- S1C:第二个幸存区的大小
- S0U:第一个幸存区的使用大小
- S1U:第二个幸存区的使用大小
- TT:对象在新生代存活的次数
- MTT:对象在新生代存活的最大次数
- DSS:期望的幸存区大小
- EC:伊甸园区的大小
- EU:伊甸园区的使用大小
- YGC:年轻代垃圾回收次数
- YGCT:年轻代垃圾回收消耗时间
jstat -gcnewcapacity pid
- 新生代内存统计
- NGCMN:新生代最小容量
- NGCMX:新生代最大容量
- NGC:当前新生代容量
- S0CMX:最大幸存1区大小
- S0C:当前幸存1区大小
- S1CMX:最大幸存2区大小
- S1C:当前幸存2区大小
- ECMX:最大伊甸园区大小
- EC:当前伊甸园区大小
- YGC:年轻代垃圾回收次数
- FGC:老年代回收次数
jstat -gcold pid
- 老年代垃圾回收统计
- MC:方法区大小
- MU:方法区使用大小
- CCSC:压缩类空间大小
- CCSU:压缩类空间使用大小
- OC:老年代大小
- OU:老年代使用大小
- YGC:年轻代垃圾回收次数
- FGC:老年代垃圾回收次数
- FGCT:老年代垃圾回收消耗时间
- GCT:垃圾回收消耗总时间
jstat -gcoldcapacity pid
- 老年代内存统计
- OGCMN:老年代最小容量
- OGCMX:老年代最大容量
- OGC:当前老年代大小
- OC:老年代大小
- YGC:年轻代垃圾回收次数
- FGC:老年代垃圾回收次数
- FGCT:老年代垃圾回收消耗时间
- GCT:垃圾回收消耗总时间
jstat -gcmetacapacity pid
- 元数据空间统计
- MCMN:最小元数据容量
- MCMX:最大元数据容量
- MC:当前元数据空间大小
- CCSMN:最小压缩类空间大小
- CCSMX:最大压缩类空间大小
- CCSC:当前压缩类空间大小
- YGC:年轻代垃圾回收次数
- FGC:老年代垃圾回收次数
- FGCT:老年代垃圾回收消耗时间
- GCT:垃圾回收消耗总时间
- S0:幸存1区当前使用比例
- S1:幸存2区当前使用比例
- E:伊甸园区使用比例
- O:老年代使用比例
- M:元数据区使用比例
- CCS:压缩使用比例
- YGC:年轻代垃圾回收次数
- FGC:老年代垃圾回收次数
- FGCT:老年代垃圾回收消耗时间
- GCT:垃圾回收消耗总时间
# 相关文章
上次更新: 2024/04/01, 19:14:44