一、常用参数
oralce官方参数参考:https://docs.oracle.com/javase/8/docs/technotes/tools/unix/java.html
1.1 HotSpot参数分类
标准: - 开头,所有的HotSpot都支持
非标准:-X 开头,特定版本HotSpot支持特定命令
不稳定:-XX 开头,下个版本可能取消
1.2 调优小程序
package com.cloud.bssp.jvm;
import java.util.LinkedList;
import java.util.List;
/**
* 调优小程序
*
* @date: 2020/12/16
* @author weirx
* @version 3.0
*/
public class Tuning {
public static void main(String[] args) {
System.out.println("Tuning...!");
List list = new LinkedList();
for (; ; ) {
byte[] bytes = new byte[1024 * 1024];
list.add(bytes);
}
}
}
本文以idea作为工具,可以在启动main方法时指定参数:
idea配置1.3 常用简单参数
-XX:+PrintFlagsWithComments:显示所有-XX参数,只有debug版本能用,这里不做演示了。
-XX:+PrintCommandLineFlags:查看当前jvm使用的优化参数。
-XX:InitialHeapSize=258062528 -XX:MaxHeapSize=4129000448 -XX:+PrintCommandLineFlags -XX:+UseCompressedClassPointers -XX:+UseCompressedOops -XX:-UseLargePagesIndividualAllocation -XX:+UseParallelGC
Connected to the target VM, address: '127.0.0.1:49379', transport: 'socket'
Tuning...!
Exception in thread "main" java.lang.OutOfMemoryError: Java heap space
at com.cloud.bssp.jvm.Tuning.main(Tuning.java:18)
Disconnected from the target VM, address: '127.0.0.1:49379', transport: 'socket'
-Xms:堆最小内存。
-Xmx:堆最大内存。
-Xmn:年轻代内存。
-Xss:线程内存大小,即栈的大小。
-XX:+PrintGC:打印程序GC过程的日志。
Tuning...!
[GC (Allocation Failure) 63340K->56175K(243712K), 0.0132497 secs]
[GC (Allocation Failure) 119881K->119182K(307712K), 0.0152269 secs]
[Full GC (Ergonomics) 119182K->118980K(396800K), 0.0249995 secs]
[GC (Allocation Failure) 246922K->244134K(396800K), 0.0244529 secs]
[Full GC (Ergonomics) 244134K->243911K(599552K), 0.0210220 secs]
[GC (Allocation Failure) 371326K->371145K(690688K), 0.0208859 secs]
[Full GC (Ergonomics) 371145K->370892K(857600K), 0.0073060 secs]
[GC (Allocation Failure) 590215K->590287K(878080K), 0.0354514 secs]
[Full GC (Ergonomics) 590287K->590036K(1188352K), 0.0103098 secs]
[GC (Allocation Failure) 829215K->828888K(1322496K), 0.0332829 secs]
[Full GC (Ergonomics) 828888K->828637K(1623552K), 0.0094309 secs]
[GC (Allocation Failure) 1201520K->1201635K(1623552K), 0.0551381 secs]
[Full GC (Ergonomics) 1201635K->1201387K(2108416K), 0.0126250 secs]
[GC (Allocation Failure) 1574277K->1574385K(2386944K), 0.0584038 secs]
[Full GC (Ergonomics) 1574385K->1574138K(2832896K), 0.0163265 secs]
[GC (Allocation Failure) 2226011K->2206475K(2860544K), 0.0954041 secs]
[Full GC (Ergonomics) 2206475K->2206302K(3351040K), 0.2683199 secs]
[Full GC (Ergonomics) 2857931K->2857590K(3351040K), 0.0929544 secs]
[Full GC (Ergonomics) 3340309K->3339912K(3351040K), 0.0795484 secs]
[Full GC (Allocation Failure) 3339912K->3339860K(3351040K), 0.3918795 secs]
Exception in thread "main" java.lang.OutOfMemoryError: Java heap space
at com.cloud.bssp.jvm.Tuning.main(Tuning.java:18)
Process finished with exit code 1
-XX:+PrintGCDetails:打印程序GC过程的详细日志,同时打印Heap(堆)的内存信息。
Tuning...!
[GC (Allocation Failure) [PSYoungGen: 63340K->9973K(74240K)] 63340K->56062K(243712K), 0.0098700 secs] [Times: user=0.00 sys=0.00, real=0.01 secs]
[GC (Allocation Failure) [PSYoungGen: 73679K->9596K(138240K)] 119768K->119182K(307712K), 0.0140132 secs] [Times: user=0.00 sys=0.00, real=0.01 secs]
[Full GC (Ergonomics) [PSYoungGen: 9596K->0K(138240K)] [ParOldGen: 109585K->118980K(260096K)] 119182K->118980K(398336K), [Metaspace: 3553K->3553K(1056768K)], 0.0289546 secs] [Times: user=0.08 sys=0.00, real=0.03 secs]
[GC (Allocation Failure) [PSYoungGen: 127941K->9408K(138240K)] 246922K->244102K(398336K), 0.0278171 secs] [Times: user=0.05 sys=0.09, real=0.03 secs]
[Full GC (Ergonomics) [PSYoungGen: 9408K->0K(138240K)] [ParOldGen: 234694K->243911K(464896K)] 244102K->243911K(603136K), [Metaspace: 3553K->3553K(1056768K)], 0.0249985 secs] [Times: user=0.08 sys=0.00, real=0.03 secs]
[GC (Allocation Failure) [PSYoungGen: 127415K->9472K(227328K)] 371326K->371145K(692224K), 0.0261426 secs] [Times: user=0.03 sys=0.06, real=0.03 secs]
[Full GC (Ergonomics) [PSYoungGen: 9472K->0K(227328K)] [ParOldGen: 361673K->370892K(632320K)] 371145K->370892K(859648K), [Metaspace: 3553K->3553K(1056768K)], 0.0071956 secs] [Times: user=0.00 sys=0.00, real=0.01 secs]
[GC (Allocation Failure) [PSYoungGen: 217235K->9472K(246272K)] 588127K->588239K(878592K), 0.0319854 secs] [Times: user=0.13 sys=0.11, real=0.03 secs]
[Full GC (Ergonomics) [PSYoungGen: 9472K->0K(246272K)] [ParOldGen: 578767K->587988K(940032K)] 588239K->587988K(1186304K), [Metaspace: 3553K->3553K(1056768K)], 0.0093061 secs] [Times: user=0.00 sys=0.02, real=0.01 secs]
[GC (Allocation Failure) [PSYoungGen: 235012K->9472K(379904K)] 823001K->822744K(1319936K), 0.0339853 secs] [Times: user=0.09 sys=0.14, real=0.03 secs]
[Full GC (Ergonomics) [PSYoungGen: 9472K->0K(379904K)] [ParOldGen: 813272K->822493K(1235968K)] 822744K->822493K(1615872K), [Metaspace: 3553K->3553K(1056768K)], 0.0088443 secs] [Times: user=0.09 sys=0.03, real=0.01 secs]
[GC (Allocation Failure) [PSYoungGen: 369664K->9472K(379904K)] 1192157K->1189347K(1615872K), 0.0535293 secs] [Times: user=0.09 sys=0.24, real=0.05 secs]
[Full GC (Ergonomics) [PSYoungGen: 9472K->0K(379904K)] [ParOldGen: 1179874K->1189099K(1712128K)] 1189347K->1189099K(2092032K), [Metaspace: 3553K->3553K(1056768K)], 0.0125591 secs] [Times: user=0.01 sys=0.00, real=0.01 secs]
[GC (Allocation Failure) [PSYoungGen: 369664K->9472K(656896K)] 1558763K->1555953K(2369024K), 0.0568648 secs] [Times: user=0.14 sys=0.28, real=0.06 secs]
[Full GC (Ergonomics) [PSYoungGen: 9472K->0K(656896K)] [ParOldGen: 1546480K->1555705K(2150912K)] 1555953K->1555705K(2807808K), [Metaspace: 3553K->3553K(1056768K)], 0.0134233 secs] [Times: user=0.02 sys=0.00, real=0.01 secs]
[GC (Allocation Failure) [PSYoungGen: 646434K->9760K(656896K)] 2202140K->2182955K(2830848K), 0.0870960 secs] [Times: user=0.19 sys=0.42, real=0.09 secs]
[Full GC (Ergonomics) [PSYoungGen: 9760K->9563K(656896K)] [ParOldGen: 2173194K->2173185K(2688512K)] 2182955K->2182749K(3345408K), [Metaspace: 4049K->4049K(1056768K)], 0.2665942 secs] [Times: user=1.53 sys=0.03, real=0.27 secs]
[Full GC (Ergonomics) [PSYoungGen: 656159K->140636K(656896K)] [ParOldGen: 2173185K->2688280K(2688512K)] 2829345K->2828917K(3345408K), [Metaspace: 4049K->4049K(1056768K)], 0.1014966 secs] [Times: user=0.30 sys=0.33, real=0.10 secs]
[Full GC (Ergonomics) [PSYoungGen: 645749K->645488K(656896K)] [ParOldGen: 2688280K->2688280K(2688512K)] 3334030K->3333768K(3345408K), [Metaspace: 4049K->4049K(1056768K)], 0.0848774 secs] [Times: user=0.42 sys=0.02, real=0.09 secs]
[Full GC (Ergonomics) [PSYoungGen: 646656K->646512K(656896K)] [ParOldGen: 2688280K->2688280K(2688512K)] 3334936K->3334792K(3345408K), [Metaspace: 4049K->4049K(1056768K)], 0.0113479 secs] [Times: user=0.00 sys=0.00, real=0.01 secs]
[Full GC (Allocation Failure) [PSYoungGen: 646512K->646477K(656896K)] [ParOldGen: 2688280K->2688262K(2688512K)] 3334792K->3334740K(3345408K), [Metaspace: 4049K->4049K(1056768K)], 0.4267966 secs] [Times: user=2.25 sys=0.06, real=0.43 secs]
Heap
PSYoungGen total 656896K, used 646656K [0x000000076df80000, 0x00000007a9300000, 0x00000007c0000000)
eden space 646656K, 100% used [0x000000076df80000,0x0000000795700000,0x0000000795700000)
from space 10240K, 0% used [0x0000000795700000,0x0000000795700000,0x0000000796100000)
to space 10240K, 0% used [0x00000007a8900000,0x00000007a8900000,0x00000007a9300000)
ParOldGen total 2688512K, used 2688266K [0x00000006c9e00000, 0x000000076df80000, 0x000000076df80000)
object space 2688512K, 99% used [0x00000006c9e00000,0x000000076df42b68,0x000000076df80000)
Metaspace used 4079K, capacity 4568K, committed 4864K, reserved 1056768K
class space used 445K, capacity 460K, committed 512K, reserved 1048576K
Exception in thread "main" java.lang.OutOfMemoryError: Java heap space
at com.cloud.bssp.jvm.Tuning.main(Tuning.java:18)
-XX:+UseConcMarkSweepGC:使用CMS垃圾回收器,当设置该参数时会默认使用ParNew年轻代回收器。
-XX:InitialHeapSize=258062528 -XX:MaxHeapSize=4129000448 -XX:MaxNewSize=697933824 -XX:MaxTenuringThreshold=6 -XX:OldPLABSize=16 -XX:+PrintCommandLineFlags -XX:+UseCompressedClassPointers -XX:+UseCompressedOops -XX:+UseConcMarkSweepGC -XX:-UseLargePagesIndividualAllocation -XX:+UseParNewGC
Tuning...!
Exception in thread "main" java.lang.OutOfMemoryError: Java heap space
at com.cloud.bssp.jvm.Tuning.main(Tuning.java:18)
-XX:+PrintFlagsInitial:默认参数值。
-XX:+PrintFlagsFinal:最终参数值。
-XX:+PrintFlagsFinal | grep xxx:找到对应的参数
-XX:+PrintFlagsFinal -version |grep GC
二、调优
2.1 基本概念
1、区分概念:内存泄漏memory leak,内存溢出out of memory。
2、吞吐量:用户代码时间 /(用户代码执行时间 + 垃圾回收时间)。
3、 响应时间:STW越短,响应时间越好。
目前两种常用方案:
吞吐量:PS + PO
响应时间:G1
2.2 如何调优?
调优,到底应该吞吐量优先?还是响应时间优先?还是在满足一定响应时间的情况下,能达到多大的吞吐量?
到底什么是调优?可以从下面三个层面进行分析:
1、根据需求进行JVM规划和预调优
2、优化JVM运行环境(慢,卡顿)
3、解决JVM运行过程中出现的各种问题(OOM)
2.2.1 根据需求进行JVM规划和预调优
重点:调优应该从结合业务场景开始,确定不同业务场景是看中响应时间还是吞吐量。
监控方式:压测。
调优的步骤:
1)熟悉业务场景,选择合适的垃圾回收器
响应时间,需要给用户做出响应:CMS G1 ZGC
吞吐量 = 用户时间 /( 用户时间 + GC时间:PS + PO
2)计算内存需求
3)选定cpu(越多越好)
4)设定年代大小
5)设定日志参数
-Xloggc:/opt/xxx/logs/xxx-xxx-gc-%t.log -XX:+UseGCLogFileRotation -XX:NumberOfGCLogFiles=5 -XX:GCLogFileSize=20M -XX:+PrintGCDetails -XX:+PrintGCDateStamps -XX:+PrintGCCause
6)观察日志
2.2.2 优化JVM运行环境与解决JVM线上问题
将优化与线上问题的解决放在同一章节去讲解,主要介绍一些常用命令和工具:
从以下四个问题去优化:
1)系统卡顿
原因:内存小,导致频繁的发生Full GC,造成系统卡顿。
解决方案:增加系统内存,但是发现仍然卡顿,频率降低,且卡顿时间更长了。
更换后仍然卡顿的原因:内存增加,导致full gc的时间更长。
解决方案:将PS + PO 更换成 G1或PN + CMS。
2)CPU100%
1、top命令,找到占用CPU高的进程(举例一个进程:PID-1)。
2、top -Hp PID-1 查看进程下的线程占用cpu情况(举例该命令查到的线程PID-2)。
3、将线程PID转换为16进制:printf "%x\n" PID-2(堆栈中,线程id是以16进制存储的)
3、jstack打印线程的堆栈:jstack PID-1 | grep PID-2
3)内存飙高
4)JVM监控
上述3、4两个问题我们通过以下java自带的命令来分析:
jmap、jstack
2.2.3 通过arthas工具排查
详细内容见:http://arthas.gitee.io/
2.3 各收集器日志分析
jdk1.8,jvm究竟使用什么垃圾收集器还取决于当前服务器的cpu核心数:
在多核情况下,使用的是PS + PO
在单核情况下,使用Serial + Serial Old
CMS日志分析
[GC (CMS Initial Mark) [1 CMS-initial-mark: 8511K(13696K)] 9866K(19840K), 0.0040321 secs] [Times: user=0.01 sys=0.00, real=0.00 secs]
//8511 (13696) : 老年代使用(最大)
//9866 (19840) : 整个堆使用(最大)
[CMS-concurrent-mark-start]
[CMS-concurrent-mark: 0.018/0.018 secs] [Times: user=0.01 sys=0.00, real=0.02 secs]
//这里的时间意义不大,因为是并发执行
[CMS-concurrent-preclean-start]
[CMS-concurrent-preclean: 0.000/0.000 secs] [Times: user=0.00 sys=0.00, real=0.00 secs]
//标记Card为Dirty,也称为Card Marking
[GC (CMS Final Remark) [YG occupancy: 1597 K (6144 K)][Rescan (parallel) , 0.0008396 secs][weak refs processing, 0.0000138 secs][class unloading, 0.0005404 secs][scrub symbol table, 0.0006169 secs][scrub string table, 0.0004903 secs][1 CMS-remark: 8511K(13696K)] 10108K(19840K), 0.0039567 secs] [Times: user=0.00 sys=0.00, real=0.00 secs]
//STW阶段,YG occupancy:年轻代占用及容量
//[Rescan (parallel):STW下的存活对象标记
//weak refs processing: 弱引用处理
//class unloading: 卸载用不到的class
//scrub symbol(string) table:
//cleaning up symbol and string tables which hold class-level metadata and
//internalized string respectively
//CMS-remark: 8511K(13696K): 阶段过后的老年代占用及容量
//10108K(19840K): 阶段过后的堆占用及容量
[CMS-concurrent-sweep-start]
[CMS-concurrent-sweep: 0.005/0.005 secs] [Times: user=0.00 sys=0.00, real=0.01 secs]
//标记已经完成,进行并发清理
[CMS-concurrent-reset-start]
[CMS-concurrent-reset: 0.000/0.000 secs] [Times: user=0.00 sys=0.00, real=0.00 secs]
//重置内部结构,为下次GC做准备
G1日志分析
[GC pause (G1 Evacuation Pause) (young) (initial-mark), 0.0015790 secs]
//young -> 年轻代 Evacuation-> 复制存活对象
//initial-mark 混合回收的阶段,这里是YGC混合老年代回收
[Parallel Time: 1.5 ms, GC Workers: 1] //一个GC线程
[GC Worker Start (ms): 92635.7]
[Ext Root Scanning (ms): 1.1]
[Update RS (ms): 0.0]
[Processed Buffers: 1]
[Scan RS (ms): 0.0]
[Code Root Scanning (ms): 0.0]
[Object Copy (ms): 0.1]
[Termination (ms): 0.0]
[Termination Attempts: 1]
[GC Worker Other (ms): 0.0]
[GC Worker Total (ms): 1.2]
[GC Worker End (ms): 92636.9]
[Code Root Fixup: 0.0 ms]
[Code Root Purge: 0.0 ms]
[Clear CT: 0.0 ms]
[Other: 0.1 ms]
[Choose CSet: 0.0 ms]
[Ref Proc: 0.0 ms]
[Ref Enq: 0.0 ms]
[Redirty Cards: 0.0 ms]
[Humongous Register: 0.0 ms]
[Humongous Reclaim: 0.0 ms]
[Free CSet: 0.0 ms]
[Eden: 0.0B(1024.0K)->0.0B(1024.0K) Survivors: 0.0B->0.0B Heap: 18.8M(20.0M)->18.8M(20.0M)]
[Times: user=0.00 sys=0.00, real=0.00 secs]
//以下是混合回收其他阶段
[GC concurrent-root-region-scan-start]
[GC concurrent-root-region-scan-end, 0.0000078 secs]
[GC concurrent-mark-start]
//无法evacuation,进行FGC
[Full GC (Allocation Failure) 18M->18M(20M), 0.0719656 secs]
[Eden: 0.0B(1024.0K)->0.0B(1024.0K) Survivors: 0.0B->0.0B Heap: 18.8M(20.0M)->18.8M(20.0M)], [Metaspace: 38
76K->3876K(1056768K)] [Times: user=0.07 sys=0.00, real=0.07 secs]
三、常见问题分析
1. -XX:MaxTenuringThreshold控制的是什么?
该参数主要是控制新生代需要经历多少次GC晋升到老年代中的最大阈值。
2. 生产环境中,倾向于将最大堆内存和最小堆内存设置为?
相同,避免在每次GC之后去动态调整堆的大小。
3. JDK1.8默认的垃圾回收器是:
PS+PO
4. 什么是响应时间优先?
快速给用户响应,本质是降低STW。
推荐垃圾回收器:CMS + ParNew,G1,ZGC
5. 什么是吞吐量优先?
不要求快速给用户响应,能处理更多的任务,但是STW时间增长。
推荐垃圾回收器:PS + PO。
6. ParNew和PS的区别是什么?
ParNew主要为了配合CMS所使用的多线程年轻代垃圾回收器。
PS关注点为吞吐量,而CMS关注点在于更快的响应时间。
7. ParNew和ParallelOld的区别是什么?
ParNew主要为了配合CMS所使用的多线程年轻代垃圾回收器。
ParallelOld是多线程的老年代回收器。
其算法也不相同。
8. 长时间计算的场景应该选择:A:停顿时间 B: 吞吐量
B
9. 大规模电商网站应该选择:A:停顿时间 B: 吞吐量
A
10. HotSpot的垃圾收集器最常用有哪些?
Serial + serial Old
PS + PO
ParNew + CMS
G1
ZGC
11. 常见的HotSpot垃圾收集器组合有哪些?
Serial + serial Old
PS + PO
ParNew + CMS
G1
ZGC
12. JDK1.7 1.8 1.9的默认垃圾回收器是什么?如何查看?
jdk1.7 默认垃圾收集器Parallel Scavenge(新生代)+Parallel Old(老年代)
jdk1.8 默认垃圾收集器Parallel Scavenge(新生代)+Parallel Old(老年代)
jdk1.9 默认垃圾收集器G1
-XX:+PrintCommandLineFlagsjvm参数可查看默认设置收集器类型
-XX:+PrintGCDetails亦可通过打印的GC日志的新生代、老年代名称判断
13. 所谓调优,到底是在调什么?
吞吐量和响应时间
结合业务,环境优化,线上问题的解决
14. 如果采用PS + ParrallelOld组合,怎么做才能让系统基本不产生FGC
增加内存,但是PS + PO的组合并不是内存越大越好,有其限度,按经验来讲最大到几个G。
增加年轻代的大小,
增加年轻代的比例,
增加gc年龄
这三个增加可以使垃圾尽量在年轻代被回收。
代码层面减少内存泄漏、死锁。
15. 如果采用ParNew + CMS组合,怎样做才能够让系统基本不产生FGC
增加内存,要比PS + PO大的多,按经验来讲最大到几十个G。
增加年轻代的大小,
增加年轻代的比例,
增加gc年龄
这三个增加可以使垃圾尽量在年轻代被回收。
代码层面减少内存泄漏、死锁。
16. G1是否分代?G1垃圾回收器会产生FGC吗?
G1是逻辑分代,物理不分代,混合回收,也会产生FullGC。
17. 如果G1产生FGC,你应该做什么?
减少代码中的大对象,增加region区域
扩内存
提高CPU性能(回收的快,业务逻辑产生对象的速度固定,垃圾回收越快,内存空间越大)
降低MixedGC触发的阈值,让MixedGC提早发生(默认是45%)
18. 问:生产环境中能够随随便便的dump吗?
不能,会导致卡顿
19. 问:常见的OOM问题有哪些?
堆,栈,元空间
网友评论