目录
1 JDK常用JVM优化相关命令
bin | 描述 | 功能 |
jps | 打印 Hotspot VM 进程 | VMID、 JVM 参数、 main()函 数参数、主类名/Jar 路径 |
jstat | 查看 Hotspot VM 运行 时信息 | 类加载、内存、 GC[可分代 查看]、 JIT 编译 命令格式: jstat -gc 10340 250 20 |
jinfo | 查看和修改虚拟机各 项配置 | -flag name=value |
jmap | heapdump: 生成 VM堆 转储快照、查询 finalize 执 行队列、 Java 堆和永久代详 细信息 | jmap -dump:live,format=b,file=heap.bin [VMID] |
jhat | 分析 dump 文件 | |
jstack | 查看 VM 当前时刻的线 程快照: 当前 VM 内每一条线程正在执行的方法堆栈集合 | Thread.getAllStackTraces()提 供了类似的功能 |
javap | 查看经 javac 之后产生 的 JVM 字节码代码 | 自动解析.class 文件, 避免 了去理解 class 文件格式以及手 动解析 class 文件内容 |
jcmd | 一个多功能工具, 可以 用来导出堆, 查看 Java 进 程、导出线程信息、 执行 GC、查看性能相关数据等 | 几乎集合了 jps、 jstat、 jinfo、 jmap、 jstack 所有功能 |
jconsole | 基于 JMX 的可视化监 视、管理工具 | 可以查看内存、线程、类、 CPU 信息, 以及对 JMX MBean 进 行管理 |
jvisualvm | JDK 中最强大运行监视 和故障处理工具 | 可以监控内存泄露、跟踪垃 圾回收、执行时内存分析、 CPU 分析、线程分析… |
jmc | 源自JRockit JVM的一套监控和管理工具 | JMC可以监视和管理 Java 应用程序,不会导致相关工具类的大幅度性能开销,它使用为 Java 虚拟机 (JVM) 的普通自适应动态优化收集的数据 |
1.1 jps
jps - l 显示线程 id 和执行线程的主类名
jps -v 显示线程 id 和执行线程的主类名和 JVM 配置信息
jps 有如下主要的选项:
选项 | 作用 |
-q | 只输出 LVMID,省略主类的名称 |
-m | 输出虚拟机启动时候传递给 main 方法的参数 |
-l | 输出类的全名 |
-v | 输出虚拟机进程启动时 JVM 参数 |
1.2 jstat
语法结构: jstat -help|-options
jstat -option> [-t] [-hlines>] vmid> [interval> [count>]]
参数介绍:
- -h n 每隔几行输出标题
- vmid VM的进程号,即当前运行的java进程号
- -t 在第一列显示自JVM启动以来的时间戳
- -J 修改java进程的参数。类似jinfo -flag =。例如-J-Xms48m 设置初始堆为48M。详见这里。这个参数挺有用的,可以在运行中调整参数以方便测试、监测。
- -option option为要检测的参数。参数列表可通过jstat –options 获取。下面将分别介绍每个参数及输出字段的含义。
class | 统计class loader行为信息 |
complier | 统计编译行为信息 |
gc | 统计jdk gc时heap信息 |
gccapacity | 统计堆内存不同代的heap容量信息 |
gccause | 统计gc的情况(同-gcutil)和引起gc的事件 |
gcnew | 统计gc时新生代的信息(相比gcutil更详细) |
gcnewcapacity | 统计gc时新生代heap容量 |
gcold | 统计gc时,老年区的情况 |
gcoldcapacity | 统计gc时,老年区heap容量 |
gcpermcapacity | 统计gc时,permanent区heap容量 |
gcutil | 统计gc时,heap情况 |
printcompilation | 统计编译行为信息 |
-class option:Class Loader Statistics
Column | Description |
Loaded | Number of classes loaded. |
Bytes | Number of Kbytes loaded. |
Unloaded | Number of classes unloaded. |
Bytes | Number of Kbytes unloaded. |
Time | Time spent performing class load and unload operations. |
-compiler:HotSpot Just-In-Time Compiler Statistics
Column | Description |
Compiled | Number of compilation tasks performed. |
Failed | Number of compilation tasks that failed. |
Invalid | Number of compilation tasks that were invalidated. |
Time | Time spent performing compilation tasks. |
FailedType | Compile type of the last failed compilation. |
FailedMethod | Class name and method for the last failed compilation. |
-gc Option:Garbage-collected heap statistics
Column | Description |
S0C | Current survivor space 0 capacity (KB). |
S1C | Current survivor space 1 capacity (KB). |
S0U | Survivor space 0 utilization (KB). |
S1U | Survivor space 1 utilization (KB). |
EC | Current eden space capacity (KB). |
EU | Eden space utilization (KB). |
OC | Current old space capacity (KB). |
OU | Old space utilization (KB). |
PC | Current permanent space capacity (KB). |
PU | Permanent space utilization (KB). |
YGC | Number of young generation GC Events. |
YGCT | Young generation garbage collection time. |
FGC | Number of full GC events. |
FGCT | Full garbage collection time. |
GCT | Total garbage collection time. |
-gccapacity Option:Memory Pool Generation and Space Capacities
Column | Description |
NGCMN | Minimum new generation capacity (KB). |
NGCMX | Maximum new generation capacity (KB). |
NGC | Current new generation capacity (KB). |
S0C | Current survivor space 0 capacity (KB). |
S1C | Current survivor space 1 capacity (KB). |
EC | Current eden space capacity (KB). |
OGCMN | Minimum old generation capacity (KB). |
OGCMX | Maximum old generation capacity (KB). |
OGC | Current old generation capacity (KB). |
OC | Current old space capacity (KB). |
PGCMN | Minimum permanent generation capacity (KB). |
PGCMX | Maximum Permanent generation capacity (KB). |
PGC | Current Permanent generation capacity (KB). |
PC | Current Permanent space capacity (KB). |
YGC | Number of Young generation GC Events. |
FGC | Number of Full GC Events. |
-gccause Option:Garbage Collection Statistics, Including GC Events
Column | Description |
LGCC | Cause of last Garbage Collection. |
GCC | Cause of current Garbage Collection. |
前面的字段与gcutil相同.
-gcnew Option:New Generation Statistics
Column | Description |
S0C | Current survivor space 0 capacity (KB). |
S1C | Current survivor space 1 capacity (KB). |
S0U | Survivor space 0 utilization (KB). |
S1U | Survivor space 1 utilization (KB). |
TT | Tenuring threshold. |
MTT | Maximum tenuring threshold. |
DSS | Desired survivor size (KB). |
EC | Current eden space capacity (KB). |
EU | Eden space utilization (KB). |
YGC | Number of young generation GC events. |
YGCT | Young generation garbage collection time. |
-gcnewcapacity Option:New Generation Space Size Statistics
Column | Description |
NGCMN | Minimum new generation capacity (KB). |
NGCMX | Maximum new generation capacity (KB). |
NGC | Current new generation capacity (KB). |
S0CMX | Maximum survivor space 0 capacity (KB). |
S0C | Current survivor space 0 capacity (KB). |
S1CMX | Maximum survivor space 1 capacity (KB). |
S1C | Current survivor space 1 capacity (KB). |
ECMX | Maximum eden space capacity (KB). |
EC | Current eden space capacity (KB). |
YGC | Number of young generation GC events. |
FGC | Number of Full GC Events. |
-gcold Option:Old and Permanent Generation Statistics
Column | Description |
PC | Current permanent space capacity (KB). |
PU | Permanent space utilization (KB). |
OC | Current old space capacity (KB). |
OU | old space utilization (KB). |
YGC | Number of young generation GC events. |
FGC | Number of full GC events. |
FGCT | Full garbage collection time. |
GCT | Total garbage collection time. |
-gcoldcapacity Option:Old Generation Statistics
Column | Description |
OGCMN | Minimum old generation capacity (KB). |
OGCMX | Maximum old generation capacity (KB). |
OGC | Current old generation capacity (KB). |
OC | Current old space capacity (KB). |
YGC | Number of young generation GC events. |
FGC | Number of full GC events. |
FGCT | Full garbage collection time. |
GCT | Total garbage collection time. |
-gcpermcapacity Option: Permanent Generation Statistics
-gcutil Option:Summary of Garbage Collection Statistics
Column | Description |
S0 | Survivor space 0 utilization as a percentage of the space's current capacity. |
S1 | Survivor space 1 utilization as a percentage of the space's current capacity. |
E | Eden space utilization as a percentage of the space's current capacity. |
O | Old space utilization as a percentage of the space's current capacity. |
P | Permanent space utilization as a percentage of the space's current capacity. |
YGC | Number of young generation GC events. |
YGCT | Young generation garbage collection time. |
FGC | Number of full GC events. |
FGCT | Full garbage collection time. |
GCT | Total garbage collection time. |
1.2.1 jstat -gc
jstat -参数 线程id 执行时间(单位毫秒) 执行次数,
例如:jstat -gc 4488 30 10(每30毫秒执行10次)
S0C:第一个幸存区的大小 S0U:第一个幸存区的使用大小
S1C:第二个幸存区的大小 S1U:第二个幸存区的使用大小
EC:伊甸园区的大小 EU:伊甸园区的使用大小
OC:老年代大小 OU:老年代使用大小
MC:方法区大小 MU:方法区使用大小
CCSC:压缩类空间大小 CCSU:压缩类空间使用大小
YGC:年轻代垃圾回收次数 YGCT:年轻代垃圾回收消耗时间
FGC:老年代垃圾回收次数 FGCT:老年代垃圾回收消耗时间
GCT:垃圾回收消耗总时间
1.2.2 jstat -gcutil
使用gcutil命令
S0: 新生代中Survivor space 0区已使用空间的百分比
S1: 新生代中Survivor space 1区已使用空间的百分比
E: 新生代已使用空间的百分比
O: 老年代已使用空间的百分比
M: 元空间已使用空间的百分比
YGC: 从应用程序启动到当前,发生Yang GC 的次数
YGCT: 从应用程序启动到当前,Yang GC所用的时间【单位秒】
FGC: 从应用程序启动到当前,发生Full GC的次数
FGCT: 从应用程序启动到当前,Full GC所用的时间
GCT: 从应用程序启动到当前,用于垃圾回收的总时间【单位秒】
1.3 jmap堆快照文件分析
观察运行中的jvm物理内存的占用情况
堆快照文件分析可通过命令jmap-dump:format=b,file=[filename] [pid]来记录下堆的内存快照,然后利用第三方工具(如mat)来分析整个Heap的对象关联情况。
例如:jmap -dump:format=b,file=outfile 3024 可以将3024进程的内存heap输出出来到outfile文件里,再配合MAT(内存分析工具(Memory Analysis Tool)或与jhat (Java Heap Analysis Tool)一起使用,能够以图像的形式直观的展示当前内存是否有问题
如果内存耗尽那么可能导致JVM直接垮掉,可以通过参数:-XX:+HeapDumpOnOutOfMemoryError来配置当内存耗尽时记录下内存快照,可以通过-XX:HeapDumpPath来指定文件的路径,这个文件的命名格式如java_[pid].hpn>f
1.4 jinfo
- 可以从一个给定的java进程或core文件或远程debug服务器上获取java配置信息。包括java系统属性及JVM参数(command line flags)。注意在jvm启动参数中没有配置的参数也可使用jinfo –flag xxx pid输出默认值(很有用,但貌似一些简写的参数查不出来)。
- 可以修改运行时的java 进程的opts
- 使用方式可使用jinfo –h 查询
1.5 jstack
观察jvm中当前所有线程的运行情况和线程当前状态
如果java程序崩溃生成core文件,jstack工具可以用来获得core文件的java stack和native stack的信息,从而可以轻松地知道java程序是如何崩溃和在程序何处发生问题。另外,jstack工具还可以附属到正在运行的java程序中,看到当时运行的java程序的java stack和native stack的信息, 如果现在运行的java程序呈现hung的状态,jstack是非常有用的
举例:jstack pid
2 JDK常用JVM优化可视化工具
java可视化工具:
jconsole:java的监控与管理控制台
jvisualvm:java的虚拟平台的可视化工具
fg:使用jconsole工具
jmc:
监视和管理 Java 应用程序
2.1 jconsole
[root@localhost jdk1.
6
.0_21]# jconsole #会启动一个图形界面
2.2 jvisualvm
2.2.1 简介
jvisualvm #也是一个可视化工具,可以分析dump文件
一个 JDK 内置的图形化 VM 监视管理工具
2.2.2 装插件
给jdk自带的jvisualvm安装Visual GC插件,遇到We're sorry the java.net site has closed(我们很抱歉java.net网站已经关闭) ,找到新的更新地址 visualvm新访问地址:https://visualvm.github.io/index.html
进入 Plugins ,再进入Plugins Centers 找到对应自己JDK版本的更新地址
进入jvisualvm的插件管理 "工具" - "插件" 在"设置"中修改url地址为刚才我们在github上找到的对应我们JDK版本的地址
修改成功后,可用插件即可刷新出来
重启即可看到VisualGC
2.3 jmc
jmc概览图
2.4 GCeasy
分析 GC 日志,就必须让 GC 日志输出到一个文件中,然后使用 GC 日志分析工具(gceasy.io/) 进行分析,GCeasy分析时采集日志使用:
- -XX:+PrintGCDetails 开启 GC 日志创建更详细的 GC 日志 ,默认情况下,GC 日志是关闭的
- -XX:+PrintGCTimeStamps,-XX:+PrintGCDateStamps :开启 GC 时间提示
开启时间便于我们更精确地判断几次 GC 操作之间的时两个参数的区别
时间戳是相对于 0 (依据 JVM 启动的时间)的值,而日期戳(date stamp)是实际的日期字符串
由于日期戳需要进行格式化,所以它的效率可能会受轻微的影响,不过这种操作并不频繁,它造成的影响也很难被我们感知。 - -XX:+PrintHeapAtGC 打印堆的 GC 日志
- -Xloggc:./logs/gc.log 指定 GC 日志路径
这里分析完之后,可以下载分析报告
JVM 内存占用情况:
Generation【区域】 | Allocated【最大值】 | Peak【占用峰值】 |
---|---|---|
Young Generation【年轻代】 | 74.5 mb | 74.47 mb |
Old Generation【老年轻代】 | 171 mb | 95.62 mb |
Meta Space【元空间】 | 1.05 gb | 55.38 mb |
Young + Old + Meta space【整体】 | 1.3 gb | 212.64 mb |
2) 关键性能指标:
1 、吞吐量:百分比越高表明 GC 开销越低。这个指标反映了 JVM 的吞吐量。
Throughput:97.043%
2 、GC 延迟:Latency
-
Avg Pause GC Time:7.80 ms 平均 GC 暂停时间
-
Max Pause GC Time:190 ms 最大 GC 暂停时间
3) GC 可视化交互聚合结果
由上图可以看到,发生了 3 次 full gc
存在问题:一开始就发生了 3 次 full gc , 很明显不太正常;
4) GC 统计
GC Statistics:GC 统计
由上图可以得到,发生 gc 的总次数,young gc,full gc 的统计,gc 暂停时间统计。
5) GC 原因:
原因 | 次数 | 平均时间 | 最大时间 | 总耗时 |
---|---|---|---|---|
Metadata GC Threshold | 6 | 43.3 ms | 190 ms | 260 ms |
Allocation Failure | 53 | 3.77 ms | 10.0 ms | 200 ms |
这里对这些原因解析一下:
-
Metadata GC Threshold:元空间超阈值
-
Allocation Failure :年轻代空间不足
2.5 JProfiler
JProfiler是由ej-technologies GmbH公司开发的一款性能瓶颈分析工具(该公司还开发部署工具)。
其特点:
- 使用方便
- 界面操作友好
- 对被分析的应用影响小
- CPU,Thread,Memory分析功能尤其强大
- 支持对jdbc,noSql, jsp, servlet, socket等进行分析
- 支持多种模式(离线,在线)的分析
在start center中选择open a single snapshot,选择就可以分析堆内存了(不是HPROF后缀名的打不开)
在idea中安装jprofiler插件,下载后运行按钮旁边出现两个jprofiler的按钮,左面的是执行程序并唤起jprofiler监控,右面的是唤起jprofiler监控运行中的jvm
3 JVM 常见参数
配置方式: java [options] MainClass [arguments]
options - JVM 启动参数。 配置多个参数的时候,参数之间使用空格分隔。
参数命名: 常见为 -参数名
参数赋值: 常见为 -参数名=参数值 / -参数名:参数值
3.1 JVM参数类型
3.1.1 标准参数
标准参数(-):所有的jvm实现都必须实现这些参数的功能,而且向后兼容,基本上不会随着JVM版本的变化而变化,比如和运行模式相关的:-server,-client;与verbose相关:-verbose:class,-verbose:gc ;
或者设置系统变量的-D参数:-D<name>=<value>:设置系统参数
我们可以通过 -help 命令来检索出所有标准参数
-help 也是一个标准参数,再比如使用比较多的 -version也是
3.1.2 X参数
非标准参数(-X):默认具名实现这些参数的功能,但是并不保证所有jvm实现都满足,且不保证向后兼容,表示在将来的JVM版本中可能会发生改变,但是这类以 -X开始的参数变化的比较小。
我们可以通过 Java -X 命令来检索所有-X 参数
3.1.3 XX参数
非stable(稳定的)参数(-XX):此类参数各个jvm实现会有所不同,将来可能会随时取消,需要谨慎使用
这是我们日常开发中接触到最多的参数类型。这也是非标准化参数,相对来说不稳定,随着JVM版本的变化可能会发生变化,主要用于JVM调优和debug。该参数的书写形式又分为两大类:
- Boolean类型 格式:-XX:[+-]name 表示启用或者禁用name属性。
-XX:+<option>开启此参数指定的功能
-XX:-<option>关闭功能
例子:-XX:+UseG1GC(表示启用G1垃圾收集器) - Key-Value类型 格式:-XX:name=value 表示name的属性值为value。
-XX:<option>=<value>给option指定的选项赋值
例子:-XX:MaxGCPauseMillis=500(表示设置GC的最大停顿时间是500ms)-XX:+PrintFlagsFinal显示所有参数
3.1.4 -- 参数
在Spring Boot应用中使用java -jar
命令启动时,可以通过--
方式传递参数,但是--放在jar包后,-D 放在jar包前
当使用--
传递参数时,这些参数通常被视为Spring Boot的命令行参数或配置属性。
例如:java -jar myapp.jar --server.port=8081 --my.custom.property=value
可以通过@Value或Environment或System.getProperty获取参数
1. 使用--
传递参数
当你使用--
传递参数时,这些参数通常被视为Spring Boot的命令行参数或配置属性。
3.2 各个参数汇总设置
3.2.1 内存参数
JVM参数的含义
参数名称 | 含义 | 默认值 | 详细解释 |
-Xms | 初始堆大小 | 物理内存的1/64( | 默认(MinHeapFreeRatio参数可以调整)空余堆内存小于40%时,JVM就会增大堆直到-Xmx的最大限制. |
-Xmx | 最大堆大小 | 物理内存的1/4( | 默认(MaxHeapFreeRatio参数可以调整)空余堆内存大于70%时,JVM会减少堆直到 -Xms的最小限制 |
-Xmn | 年轻代大小(1.4or lator) | 注意:此处的大小是(eden+ 2 survivor space).与jmap -heap中显示的New gen是不同的。 整个堆大小=年轻代大小 + 年老代大小 + 持久代大小. 增大年轻代后,将会减小年老代大小.此值对系统性能影响较大,Sun官方推荐配置为整个堆的3/8 | |
-XX:NewSize | 设置年轻代大小(for 1.3/1.4) | ||
-XX:MaxNewSize | 年轻代最大值(for 1.3/1.4) | ||
-XX:PermSize | 设置持久代(perm gen)初始值 | 物理内存的1/64 | |
-XX:MaxPermSize | 设置持久代最大值 | 物理内存的1/4 | |
-Xss | 每个线程的堆栈大小 | JDK5.0以后每个线程堆栈大小为1M,以前每个线程堆栈大小为256K.更具应用的线程所需内存大小进行 调整.在相同物理内存下,减小这个值能生成更多的线程.但是操作系统对一个进程内的线程数还是有限制的,不能无限生成,经验值在3000~5000左右 一般小的应用, 如果栈不是很深, 应该是128k够用的 大的应用建议使用256k。这个选项对性能影响比较大,需要严格的测试。(校长) 和threadstacksize选项解释很类似,官方文档似乎没有解释,在论坛中有这样一句话:"” -Xss is translated in a VM flag named ThreadStackSize” 一般设置这个值就可以了。 | |
-XX:ThreadStackSize | Thread Stack Size | (0 means use default stack size) [Sparc: 512; Solaris x86: 320 (was 256 prior in 5.0 and earlier); Sparc 64 bit: 1024; Linux amd64: 1024 (was 0 in 5.0 and earlier); all others 0.] | |
-XX:NewRatio | 年轻代(包括Eden和两个Survivor区)与年老代的比值(除去持久代) | -XX:NewRatio=4表示年轻代与年老代所占比值为1:4,年轻代占整个堆栈的1/5 Xms=Xmx并且设置了Xmn的情况下,该参数不需要进行设置。 | |
-XX:SurvivorRatio | Eden区与Survivor区的大小比值 | 设置为8,则两个Survivor区与一个Eden区的比值为2:8,一个Survivor区占整个年轻代的1/10 | |
-XX:LargePageSizeInBytes | 内存页的大小不可设置过大, 会影响Perm的大小 | =128m | |
-XX:+UseFastAccessorMethods | 原始类型的快速优化 | ||
-XX:+DisableExplicitGC | 关闭System.gc() | 这个参数需要严格的测试 | |
-XX:MaxTenuringThreshold | 垃圾最大年龄 | 如果设置为0的话,则年轻代对象不经过Survivor区,直接进入年老代. 对于年老代比较多的应用,可以提高效率.如果将此值设置为一个较大值,则年轻代对象会在Survivor区进行多次复制,这样可以增加对象再年轻代的存活 时间,增加在年轻代即被回收的概率 该参数只有在串行GC时才有效. | |
-XX:+AggressiveOpts | 加快编译 | ||
-XX:+UseBiasedLocking | 锁机制的性能改善 | ||
-Xnoclassgc | 禁用垃圾回收 | ||
-XX:SoftRefLRUPolicyMSPerMB | 每兆堆空闲空间中SoftReference的存活时间 | 1s | softly reachable objects will remain alive for some amount of time after the last time they were referenced. The default value is one second of lifetime per free megabyte in the heap |
-XX:PretenureSizeThreshold | 对象超过多大是直接在旧生代分配 | 0 | 单位字节 新生代采用Parallel Scavenge GC时无效 另一种直接在旧生代分配的情况是大的数组对象,且数组中无外部引用对象. |
-XX:TLABWasteTargetPercent | TLAB占eden区的百分比 | 1% | |
-XX:+CollectGen0First | FullGC时是否先YGC | false |
JVM 中最大堆大小有三方面限制:相关操作系统的数据模型(32-bt 还是 64-bit)限制;系统的可用虚拟内存限制;系统的可用物理内存限制。
32 位系统 下,一般限制在 1.5G~2G;64 为操作系统对内存无限制。
Tomcat 配置方式: 编写 catalina.bat|catalina.sh,增加 JAVA_OPTS 参数设置。 windows和 linux 配置方式不同。
indows - set "JAVA_OPTS=%JAVA_OPTS% 自定义参数"; linux -JAVA_OPTS="$JAVA_OPTS 自定义参数"
常见设置:
-Xmx3550m -Xms3550m -Xmn2g -Xss128k 适合开发过程的测试应用。要求物理内存大于4G。
-Xmx3550m -Xms3550m -Xss128k -XX:NewRatio=4 -XX:SurvivorRatio=4
-XX:MaxPermSize=160m -XX:MaxTenuringThreshold=0 适合高并发本地测试使用。 且大数据对象相对较多(如 IO 流)
环境: 16G 物理内存,高并发服务,重量级对象中等(线程池,连接池等),常用对象比例为 40%(运行过程中产生的对象 40%是生命周期较长的)
-Xmx10G -Xms10G -Xss1M -XX:NewRatio=3 -XX:SurvivorRatio=4 -XX:MaxPermSize=2048m
-XX:MaxTenuringThreshold=5
3.2.2 收集器相关参数
参数名称 | 含义 | 默认值 | 详细解释 |
-XX:+UseParallelGC | 设置并行收集器 | 选择垃圾收集器为并行收集器。此配置仅对年轻代有效,即上述配置下,年轻代使用并发收集,而年老代仍旧使用串行收集.(此项待验证) | |
-XX:+UseSerialGC | 设置串行收集器,年轻带收集器, 次收集器 | ||
-XX:+UseG1GC | 设置 G1 收集器 | ||
-XX:+UseParNewGC | 设置年轻代为并行收集 | 可与CMS收集同时使用 JDK5.0以上,JVM会根据系统配置自行设置,所以无需再设置此值 | |
-XX:ParallelGCThreads | 并行收集器的线程数 | 设置并行收集器收集时最大线程数使用的 CPU 数 此值最好配置与处理器数目相等 同样适用于CMS | |
-XX:+UseParallelOldGC | 年老代垃圾收集方式为并行收集 | 这个是JAVA 6出现的参数选项 | |
-XX:MaxGCPauseMillis | 每次年轻代垃圾回收的最长时间(最大暂停时间) | 设置并行收集最大暂停时间,单位毫秒。可以减少 STW 时间 如果无法满足此时间,JVM会自动调整年轻代大小,以满足此值. | |
-XX:+UseAdaptiveSizePolicy | 自动选择年轻代区大小和相应的Survivor区比例 | 设置此选项后,并行收集器会自动选择年轻代区大小和相应的Survivor区比例,以达到目标系统规定的最低相应时间或者收集频率等,此值建议使用并行收集器时,一直打开 提高年轻代 GC 效率的配置,次收集器执行效率,并发收集器主要是保证系统的响应时间,减少垃圾收集时的停顿时间。适用于应用服务器、电信领域、互联网领域等 | |
-XX:GCTimeRatio | 设置垃圾回收时间占程序运行时间的百分比 | 公式为1/(1+n) | |
-XX:+ScavengeBeforeFullGC | Full GC前调用YGC | true | Do young generation GC prior to a full GC. (Introduced in 1.4.1.) |
-XX:+UseConcMarkSweepGC | 设置年老代并发收集器 | 使用CMS内存收集,测试中配置这个以后,-XX:NewRatio的配置失效了,原因不明。所以,此时年轻代大小最好用-Xmn设置 | |
-XX:+AggressiveHeap | 试图是使用大量的物理内存 长时间大内存使用的优化,能检查计算资源(内存, 处理器数量) 至少需要256MB内存 大量的CPU/内存, (在1.4.1在4CPU的机器上已经显示有提升) | ||
-XX:CMSFullGCsBeforeCompaction | 多少次后进行内存压缩 | 由于并发收集器不对内存空间进行压缩、整理,所以运行一段时间以后会产生"碎片",使得运行效率降低。此值设置运行多少次GC以后对内存空间进行压缩,整理 | |
-XX:+CMSParallelRemarkEnabled | 降低标记停顿 | ||
-XX+UseCMSCompactAtFullCollection | 在FULL GC的时候, 对年老代的压缩 | CMS是不会移动内存的, 因此, 这个非常容易产生碎片, 导致内存不够用, 因此, 内存的压缩这个时候就会被启用。 增加这个参数是个好习惯。 可能会影响性能,但是可以消除碎片 | |
-XX:+UseCMSInitiatingOccupancyOnly | 使用手动定义初始化定义开始CMS收集 | 禁止hostspot自行触发CMS GC | |
-XX:CMSInitiatingOccupancyFraction=70 | 使用cms作为垃圾回收 使用70%后开始CMS收集 | 92 | |
-XX:CMSInitiatingPermOccupancyFraction | 设置Perm Gen使用到达多少比率时触发 | 92 | |
-XX:+CMSIncrementalMode | 设置为增量模式 | 用于单CPU情况 | |
-XX:+CMSClassUnloadingEnabled |
关于收集器的选择 JVM 给了三种选择:串行收集器、并行收集器、并发收集器,但是串行收集器只适用于小数据量的情况,所以这里的选择主要针对并行收集器和并发收集器。默认情况下, JDK5.0 以前都是使用串行收集器,如果想使用其他收集器需要在启动时加入相应参数。 JDK5.0 以后, JVM 会根据当前系统配置进行判断。
常见配置:
并行收集器主要以到达一定的吞吐量为目标,适用于科学计算和后台处理等。
-Xmx3800m -Xms3800m -Xmn2g -Xss128k -XX:+UseParallelGC -XX:ParallelGCThreads=20使用 ParallelGC 作为并行收集器, GC 线程为 20(CPU 核心数>=20 时),内存问题根据硬件配置具体提供。 建议使用物理内存的 80%左右作为 JVM 内存容量。
-Xmx3550m -Xms3550m -Xmn2g -Xss128k -XX:+UseParallelGC -XX:ParallelGCThreads=20
-XX:+UseParallelOldGC 指定老年代收集器,在 JDK5.0之后的版本,ParallelGC对应的全收集器就是 ParallelOldGC。可以忽略
-Xmx3550m -Xms3550m -Xmn2g -Xss128k -XX:+UseParallelGC -XX:MaxGCPauseMillis=100指定 GC 时最大暂停时间。单位是毫秒。每次 GC 最长使用 100 毫秒。 可以尽可能提高工作线程的执行资源。
-Xmx3550m -Xms3550m -Xmn2g -Xss128k -XX:+UseParallelGC -XX:MaxGCPauseMillis=100
-Xmx3550m -Xms3550m -Xmn2g -Xss128k -XX:ParallelGCThreads=20
-XX:+UseConcMarkSweepGC -XX:+UseParNewGC
指定年轻代收集器为 ParNew,年老代收集器 ConcurrentMarkSweep,并发 GC 线程数为20(CPU 核心>=20),并发 GC 的线程数建议使用(CPU 核心数+3) /4 或 CPU 核心数【不推荐使用】。
-Xmx3550m -Xms3550m -Xmn2g -Xss128k -XX:+UseConcMarkSweepGC
-XX:CMSFullGCsBeforeCompaction=5 -XX:+UseCMSCompactAtFullCollection
CMSFullGCsBeforeCompaction=5 执行 5 次 GC 后,运行一次内存的整理。
UseCMSCompactAtFullCollection 执行老年代内存整理。 可以避免内存碎片,提高 GC 过程中的效率,减少停顿时间。
年轻代大小选择
响应时间优先的应用:尽可能设大,直到接近系统的最低响应时间限制(根据实际情况选择)。在此种情况下,年轻代收集发生的频率也是最小的。同时,减少到达年老代的对象。
吞吐量优先的应用:尽可能的设置大,可能到达 Gbit 的程度。因为对响应时间没有要求,垃圾收集可以并行进行,一般适合 8CPU 以上的应用。
年老代大小选择
响应时间优先的应用: 年老代使用并发收集器,所以其大小需要小心设置,一般要考虑并发会话率和会话持续时间等一些参数。如果堆设置小了,可以会造成内存碎片、高回收频率以及应用暂停而使用传统的标记清除方式;如果堆大了,则需要较长的收集时间。
最优化的方案,一般需要参考以下数据获得:
- 并发垃圾收集信息
- 持久代并发收集次数
- 传统 GC 信息
- 花在年轻代和年老代回收上的时间比例
- 减少年轻代和年老代花费的时间,一般会提高应用的效率
吞吐量优先的应用:一般吞吐量优先的应用都有一个很大的年轻代和一个较小的年老代。原因是,这样可以尽可能回收掉大部分短期对象,减少中期的对象,而年老代存放长期存活对象。
较小堆引起的碎片问题, 因为年老代的并发收集器使用标记、清除算法,所以不会对堆进行压缩。当收集器回收时,他会把相邻的空间进行合并,这样可以分配给较大的对象。但是,当堆空间较小时,运行一段时间以后,就会出现“碎片”,如果并发收集器找不到足够的空间,那么并发收集器将会停止,然后使用传统的标记、 整理方式进行回收。如果出现“碎片”,可能需要进行如下配置:
-XX:+UseCMSCompactAtFullCollection:使用并发收集器时,开启对年老代的压缩。
-XX:CMSFullGCsBeforeCompaction=0:上面配置开启的情况下,这里设置多少次 Full GC后,对年老代进行压缩
3.2.3 GC日志参数
参数名称 | 含义 | 详细解释 |
-verbose:gc | 可以辅助输出一些详细的GC信息 | |
-XX:+PrintGC | 输出形式: [GC 118250K->113543K(130112K), 0.0094143 secs] [Full GC 121376K->10414K(130112K), 0.0650971 secs] | |
-XX:+PrintGCDetails | 输出 GC 的详细信息 | 输出形式:[GC [DefNew: 8614K->781K(9088K), 0.0123035 secs] 118250K->113543K(130112K), 0.0124633 secs] [GC [DefNew: 8614K->8614K(9088K), 0.0000665 secs][Tenured: 112761K->10414K(121024K), 0.0433488 secs] 121376K->10414K(130112K), 0.0436268 secs] |
-XX:+PrintGCTimeStamps | ||
-XX:+PrintGC:PrintGCTimeStamps | 可与-XX:+PrintGC -XX:+PrintGCDetails混合使用 输出形式:11.851: [GC 98328K->93620K(130112K), 0.0082960 secs] | |
-XX:+PrintGCApplicationStoppedTime | 打印垃圾回收期间程序暂停的时间 | 输出形式:Total time for which application threads were stopped: 0.0468229 seconds, Stopping threads took: 0.0000218 seconds |
-XX:+PrintGCApplicationConcurrentTime | 打印每次垃圾回收前,程序未中断的执行时间.可与上面混合使用 | 输出形式:Application time: 0.5291524 seconds |
-XX:+PrintHeapAtGC | 打印GC前后的详细堆栈信息 | 在GC前后输出堆中各个区域的大小 |
-Xloggc:filename | 将GC信息输出到单独的文件中 | 按照这个参数,每个GC日志只要超过设定的M就会进行分割,最多分割几个文件后会被覆盖 |
-XX:+UseGCLogFileRotation | 开启日志文件分割 | |
-XX:NumberOfGCLogFiles=14 | 最多分割几个文件,超过之后从头开始写 | 不能设置为无限数字 |
-XX:GCLogFileSize=100M | 每个文件上限大小,超过就触发分割 | |
-XX:+PrintClassHistogram | garbage collects before printing the histogram. | |
-XX:+PrintTLAB | 查看TLAB空间的使用情况 | |
XX:+PrintTenuringDistribution | 查看每次minor GC后新的存活周期的阈值 | 了分析 GC 时的晋升情况和晋升导致的高暂停,查看对象年龄分布日志 new threshold 7即标识新的存活周期的阈值为7。 |
-XX:+PrintGCDateStamps | GC 发生的时间信息 | |
-XX:+PrintSafepointStatistics | 查看safepoint | |
-XX:PrintSafepointStatisticsCount=1 | ||
-XX:+PrintReferenceGC | 查看Reference | 强引用/弱引用/软引用/虚引用/finalize 方法万一有问题,可以打印出来看看 |
一般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
3.3 GC日志解读
3.3.1 每种GC的日志形式
GC方式 | 日志形式 | |
Serial Collector (串行) | [GC[DefNew: 11509K->1138K(14336K), 0.0110060 secs] 11509K->1138K(38912K), 0.0112610 secs] [Times: user=0.00 sys=0.01, real=0.01 secs] | |
[Full GC [Tenured: 9216K->4210K(10240K), 0.0066570 secs] 16584K->4210K(19456K), [Perm : 1692K->1692K(16384K)], 0.0067070 secs][Tiines: user=0.00 sys=0.00, real=0.01 secs] | ||
Parallel Collector (并行) | ParNewGC | [GC [ParNew: 11509K->1152K(14336K), 0.0129150 secs] 11509K->1152K(38912K), 0.0131890 secs] [Times: user=0.05 sys=0.02, real=0.02 secs] |
[GC [ASParNew: 7495K->120K(9216K), 0.0403410 secs] 7495K->7294K(19456K), 0.0406480 secs] [Times: user=0.06 sys=0.15, real=0.04 secs] | ||
ParallelGC | [GC [PSYoungGen: 11509K->1184K(14336K)] 11509K->1184K(38912K), 0.0113360 secs][Times: user=0.03 sys=0.01, real=0.01 secs] | |
[Full GC [PSYoungGen: 1208K->0K(8960K)] [PSOldGen: 6144K->7282K(10240K)] 7352K->7282K(19200K) [PSPermGen: 1686K->1686K(16384K)], 0.0165880 secs] [Times: user=0.01 sys=0.01, real=0.02 secs] | ||
ParallelOldGC | [Full GC [PSYoungGen: 1224K->0K(8%0K)] [ParOldGen: 6144K->7282K(10240K)] 7368K->7282K(19200K) [PSPennGen: 1686K->1685K( 16384K)], 0.0223510 secs] [Times: user=0.02 sys=0.06, real=0.03 secs] | |
CMS Collector (并发) | [GC [1 CMS-initial-mark: 13433K(20480K)] 14465K(29696K), 0.0001830 secs] [Times: user=0.00 sys=0.00, real=0.00 secs] [CMS-concurrent-mark: 0.004/0.004 secs] [Times: user=0.01 sys=0.00, real=0.01 secs] [CMS-concurrent-preclean: 0.000/0.000 secs] [Times: user=0.00 sys=0.00, real=0.00 secs] CMS: abort precleandue to time [CMS-concurrent-abortable-preclean: 0.007/5.042 secs] [Times: user=0.00 sys=0.00, real=5.04 secs] [CJC[YG occupancy: 3300 K (9216 K)][Rescan (parallel), 0.0002740 secs] [weak refs processing, 0.0000090 secs] [1 CMS-remark: 13433K(20480K)] 16734K(29696K), 0.0003710 secs] [Tiroes: user=0.00 sys=0.00, real=0.00 secs] [CMS-concurrent-sweep: 0.000/0.000 secs] [Times: user=0.00 sys=0.00, real=0.00 secs] [CMS-concurrent-reset: 0.000/0.000 secs] [Times: user=0.00 sys=0.00, real=0.00 secs] |
除CMS的日志与其他GC的日志差别较大外,它们都可以抽象成如下格式
[GC [<collector>:<starting occupancy 1>-> <ending occupancy 1> (total sizel), <pause time1> secs] <starting occupancy 2> -> <ending occupancy 2>(total size2) <pause time2> secs]
其中说明如下:
- <collector>GC表示收集器的名称
- <starting occupancy 1>表示Young区在GC前占用的内存
- <ending occupancy 1>表示Young区在GC后占用的内存
- <pause time1>表示Young区局部收集时JVM暂停处理的时间
- <starting occupancy 2>表不 JVM Heap 在 GC 前占用的内存
- <ending occupancy 2> 表示 JVM Heap 在 GC 后占用的内存
- <pause time2>表示在GC过程中JVM暂停处理的总时间
可以根据日志来判断是否有内存在泄漏,如果〈ending occupancy 1>-<starting occupancy 1>=<ending occupancy2>-<starting occupancy2>,则表明这次GC对象100%被回收,没有对象进入Old区或者Perm区。如果等号前面的值大于等号后面的值,那么差值就是这次回收对象进入Old区或者Perm区的大小。如果随着时间的延长,ending occupancy2的值一直在增长,而且FullGC很频繁,那么很可能就是内存泄漏了
3.3.2 Young GC 日志含义
2022-08-05T13:45:23.336+0800: 4.866: [GC (Metadata GC Threshold)
[PSYoungGen: 136353K->20975K(405504K)] 160049K->48437K(720384K),
0.0092260 secs] [Times: user=0.00 sys=0.02, real=0.02 secs]
这里的内容,我们一个一个解析:
2022-08-05T13:45:23.336+0800: 本次GC发生时间
4.866: 举例启动应用的时间
[GC【表示GC的类型,youngGC】 (Metadata GC Threshold) 元空间超阈值
[PSYoungGen: 136353K->20975K(405504K年轻代总空间)] 160049K->48437K(720384K)整堆), 0.0092260 secs本次垃圾回收耗时]
[Times: user=0.00本次GC消耗CPU的时间 sys=0.02系统暂停时间, real=0.02 secs实际应用暂停时间]
3.3.3 FullGC 日志含义
2022-08-05T20:24:47.815+0800: 6.955: [Full GC (Metadata GC Threshold)
[PSYoungGen: 701K->0K(72704K)] [ParOldGen: 38678K->35960K(175104K)] 39380K->35960K(247808K),
[Metaspace: 56706K->56706K(1099776K)], 0.1921975 secs] [Times: user=1.03 sys=0.00, real=0.19 secs]
这里的内容,我们也是一个一个解析:
2022-08-05T20:24:47.815+0800:
6.955: 刚启动服务就Full GC【整堆回收!!】
[Full GC (Metadata GC Threshold) Metaspace空间超限!
[PSYoungGen: 701K->0K(72704K)] 年轻代没有回收空间
[ParOldGen: 38678K->35960K(175104K)] 39380K->35960K(247808K), 老年代也没有到阈值,整堆更没有到阈值
[Metaspace: 56706K->56706K(1099776K)], 0.1921975 secs]
[Times: user=1.03本次GC消耗CPU的时间 sys=0.00系统暂停时间, real=0.19 secs实际应用暂停时间]
3.3.4 可视化日志分析
分析 GC 日志,就必须让 GC 日志输出到一个文件中,然后使用 GC 日志分析工具(gceasy.io/) 进行分析