引言:更多相关请看 JVM+GC解析系列
JVM参数类型
分为标配参数、X参数、XX参数。
标配参数
各大JDK版本比较稳定,很少有大的变化。
参数:java -version
效果:
java version "1.8.0_211"
Java(TM) SE Runtime Environment (build 1.8.0_211-b12)
Java HotSpot(TM) 64-Bit Server VM (build 25.211-b12, mixed mode)
参数:java -help
效果:
java version "1.8.0_211"
用法: java [-options] class [args...]
(执行类)
或 java [-options] -jar jarfile [args...]
(执行 jar 文件)
其中选项包括:
-d32 使用 32 位数据模型 (如果可用)
-d64 使用 64 位数据模型 (如果可用)
-server 选择 "server" VM
默认 VM 是 server.
-cp <目录和 zip/jar 文件的类搜索路径>
-classpath <目录和 zip/jar 文件的类搜索路径>
用 ; 分隔的目录, JAR 档案
和 ZIP 档案列表, 用于搜索类文件。
-D<名称>=<值>
设置系统属性
-verbose:[class|gc|jni]
启用详细输出
-version 输出产品版本并退出
-version:<值>
警告: 此功能已过时, 将在
未来发行版中删除。
需要指定的版本才能运行
-showversion 输出产品版本并继续
-jre-restrict-search | -no-jre-restrict-search
警告: 此功能已过时, 将在
未来发行版中删除。
在版本搜索中包括/排除用户专用 JRE
-? -help 输出此帮助消息
-X 输出非标准选项的帮助
-ea[:<packagename>...|:<classname>]
-enableassertions[:<packagename>...|:<classname>]
按指定的粒度启用断言
-da[:<packagename>...|:<classname>]
-disableassertions[:<packagename>...|:<classname>]
禁用具有指定粒度的断言
-esa | -enablesystemassertions
启用系统断言
-dsa | -disablesystemassertions
禁用系统断言
-agentlib:<libname>[=<选项>]
加载本机代理库 <libname>, 例如 -agentlib:hprof
另请参阅 -agentlib:jdwp=help 和 -agentlib:hprof=help
-agentpath:<pathname>[=<选项>]
按完整路径名加载本机代理库
-javaagent:<jarpath>[=<选项>]
加载 Java 编程语言代理, 请参阅 java.lang.instrument
-splash:<imagepath>
使用指定的图像显示启动屏幕
有关详细信息, 请参阅 http://www.oracle.com/technetwork/java/javase/documentation/index.html。
参数:java -showversion(java -version和java -help的综合功能)
效果:
java version "1.8.0_211"
Java(TM) SE Runtime Environment (build 1.8.0_211-b12)
Java HotSpot(TM) 64-Bit Server VM (build 25.211-b12, mixed mode)
用法: java [-options] class [args...]
(执行类)
或 java [-options] -jar jarfile [args...]
(执行 jar 文件)
其中选项包括:
-d32 使用 32 位数据模型 (如果可用)
-d64 使用 64 位数据模型 (如果可用)
-server 选择 "server" VM
默认 VM 是 server.
-cp <目录和 zip/jar 文件的类搜索路径>
-classpath <目录和 zip/jar 文件的类搜索路径>
用 ; 分隔的目录, JAR 档案
和 ZIP 档案列表, 用于搜索类文件。
-D<名称>=<值>
设置系统属性
-verbose:[class|gc|jni]
启用详细输出
-version 输出产品版本并退出
-version:<值>
警告: 此功能已过时, 将在
未来发行版中删除。
需要指定的版本才能运行
-showversion 输出产品版本并继续
-jre-restrict-search | -no-jre-restrict-search
警告: 此功能已过时, 将在
未来发行版中删除。
在版本搜索中包括/排除用户专用 JRE
-? -help 输出此帮助消息
-X 输出非标准选项的帮助
-ea[:<packagename>...|:<classname>]
-enableassertions[:<packagename>...|:<classname>]
按指定的粒度启用断言
-da[:<packagename>...|:<classname>]
-disableassertions[:<packagename>...|:<classname>]
禁用具有指定粒度的断言
-esa | -enablesystemassertions
启用系统断言
-dsa | -disablesystemassertions
禁用系统断言
-agentlib:<libname>[=<选项>]
加载本机代理库 <libname>, 例如 -agentlib:hprof
另请参阅 -agentlib:jdwp=help 和 -agentlib:hprof=help
-agentpath:<pathname>[=<选项>]
按完整路径名加载本机代理库
-javaagent:<jarpath>[=<选项>]
加载 Java 编程语言代理, 请参阅 java.lang.instrument
-splash:<imagepath>
使用指定的图像显示启动屏幕
有关详细信息, 请参阅 http://www.oracle.com/technetwork/java/javase/documentation/index.html。
X参数(了解)
分为下面三种:
-Xint:解释执行
-Xcomp:第一次使用就编译成本地代码
-Xmixed:混合模式(默认的)
查询X参数需执行参数:java -version
java version "1.8.0_211"
Java(TM) SE Runtime Environment (build 1.8.0_211-b12)
Java HotSpot(TM) 64-Bit Server VM (build 25.211-b12, mixed mode)
其中的“...VM (build 25.211-b12, mixed mode)”中的mixed mode就是我们的X参数。
相关执行效果如下(注意看命令执行后的mode模式变化):
C:\Windows\system32>java -version
java version "1.8.0_211"
Java(TM) SE Runtime Environment (build 1.8.0_211-b12)
Java HotSpot(TM) 64-Bit Server VM (build 25.211-b12, mixed mode)
C:\Windows\system32>java -Xint -version
java version "1.8.0_211"
Java(TM) SE Runtime Environment (build 1.8.0_211-b12)
Java HotSpot(TM) 64-Bit Server VM (build 25.211-b12, interpreted mode)
C:\Windows\system32>java -Xcomp -version
java version "1.8.0_211"
Java(TM) SE Runtime Environment (build 1.8.0_211-b12)
Java HotSpot(TM) 64-Bit Server VM (build 25.211-b12, compiled mode)
C:\Windows\system32>java -Xmixed -version
java version "1.8.0_211"
Java(TM) SE Runtime Environment (build 1.8.0_211-b12)
Java HotSpot(TM) 64-Bit Server VM (build 25.211-b12, mixed mode)
XX参数(重点)
分为Boolean类型、KV设值类型。
jinfo
查看当前运行程序的配置,公式:jinfo -flag 配置项 进程编号。
查看当前运行程序的所有配置,公式:jinfo -flags 进程编号。
查看当前所有java进程pid:jps
VM配置,以IDEA为例。


public class GcDemo{
public static void main(String[] args) throws Exception{
System.out.println("启动中");
Thread.sleep(Integer.MAX_VALUE);
}
}
再执行相关命令
C:\Windows\system32>jps
13376 Launcher
2368
10724 jar
5028 GcDemo
9492 RemoteMavenServer36
12120 Jps
13084 jar
C:\Windows\system32>jinfo -flag PrintGCDetails 5028
-XX:-PrintGCDetails
C:\Windows\system32>jinfo -flags 5028
Attaching to process ID 5028, please wait...
Debugger attached successfully.
Server compiler detected.
JVM version is 25.211-b12
Non-default VM flags: -XX:CICompilerCount=4 -XX:InitialHeapSize=268435456 -XX:MaxHeapSize=4273995776 -XX:MaxNewSize=1424490496 -XX:MinHeapDeltaBytes=524288 -XX:NewSize=89128960 -XX:OldSize=179306496 -XX:+UseCompressedClassPointers -XX:+UseCompressedOops -XX:+UseFastUnorderedTimeStamps -XX:-UseLargePagesIndividualAllocation -XX:+UseParallelGC
Command line: -javaagent:E:\software\IntelliJ IDEA 2019.1.3\lib\idea_rt.jar=5319:E:\software\IntelliJ IDEA 2019.1.3\bin -Dfile.encoding=UTF-8
Boolean类型
公式:-XX:+或者- 某个属性值,+表示开启、-表示关闭。
Case:
是否打印GC收集细节:-XX:+PrintGCDetails和-XX:-PrintGCDetails
是否使用串行垃圾收集器:-XX:-UseSerialGC和-XX:+UseSerialGC
例子:
编写下面代码
public class GcDemo{
public static void main(String[] args) throws Exception{
System.out.println("启动中");
Thread.sleep(Integer.MAX_VALUE);
}
}
配置参数并执行

C:\Windows\system32>jps -l
2368
7280 com.example.demo.test01.GcDemo
8320 org.jetbrains.jps.cmdline.Launcher
10724 finalshell.jar
9492 org.jetbrains.idea.maven.server.RemoteMavenServer36
11464 sun.tools.jps.Jps
13084 finalshell.jar
3420 org.jetbrains.kotlin.daemon.KotlinCompileDaemon
C:\Windows\system32>jinfo -flag PrintGCDetails 7280
-XX:+PrintGCDetails
KV设值类型
公式:-XX:属性key=属性值value
case:
-XX:MetaspaceSize=128m 设置元空间大小为128M
给上面GcDemo代码配置参数并执行后的效果:
134217728=1024x1024x128
C:\Windows\system32>jps -l
2368
10724 finalshell.jar
9492 org.jetbrains.idea.maven.server.RemoteMavenServer36
10984 org.jetbrains.jps.cmdline.Launcher
1448 com.example.demo.test01.GcDemo
13084 finalshell.jar
3420 org.jetbrains.kotlin.daemon.KotlinCompileDaemon
7036 sun.tools.jps.Jps
C:\Windows\system32>jinfo -flag MetaspaceSize 1448
-XX:MetaspaceSize=134217728
C:\Windows\system32>
-XX:MaxTenuringThreshold=15 设置堆的young区最大存活15次数(经历过15次存活才能进入年老区)
题外话
两个经典参数:-Xms和-Xmx。
-Xms:等价于 -XX:InitialHeapSize,初始化堆对大小。
-Xmx:等价于 -XX:MaxHeapSize,最大堆大小。
查看JVM默认值
-XX:+PrintFlagsInitial
查看初始默认值。
公式:java -XX:+PrintFlagsInitial -version或java -XX:+PrintFlagsInitial
[Global flags]
intx ActiveProcessorCount = -1 {product}
uintx AdaptiveSizeDecrementScaleFactor = 4 {product}
...
-XX:+PrintFlagsFinal
主要查看修改更新。
公式:java -XX:+PrintFlagsFinal和java -XX:+PrintFlagsFinal -version
注意:=未修改过,:=人为或JVM修改过
[Global flags]
intx ActiveProcessorCount = -1 {product}
uintx AdaptiveSizeDecrementScaleFactor = 4 {product}
...
uintx InitialBootClassLoaderMetaspaceSize = 4194304 {product}
uintx InitialCodeCacheSize = 2555904 {pd product}
uintx InitialHeapSize := 268435456 {product}
PrintFlagsFinal举例,运行Java更改VM参数命令的同时打印出参数
命令:java -XX:+PrintFlagsFinal -XX:MetaspaceSize=512m -version 注意::=(人为或JVM修改过) 536870912(1024x1024X512)
[Global flags]
intx ActiveProcessorCount = -1 {product}
uintx AdaptiveSizeDecrementScaleFactor = 4 {product}
uintx AdaptiveSizeMajorGCDecayTimeScale = 10 {product}
...
intx MaxVectorSize = 32 {C2 product}
uintx MetaspaceSize := 536870912 {pd product}
bool MethodFlushing = true {product}
uintx MinHeapDeltaBytes := 524288 {product}
...
-XX:+PrintCommandLineFlags
打印HotSpotVM 采用的自动优化参数
命令:java -XX:+PrintCommandLineFlags -version
执行效果:
-XX:InitialHeapSize=267043712 -XX:MaxHeapSize=4272699392 -XX:+PrintCommandLineFlags -XX:+UseCompressedClassPointers -XX:+UseCompressedOops -XX:-UseLargePagesIndividualAllocation -XX:+UseParallelGC
java version "1.8.0_211"
Java(TM) SE Runtime Environment (build 1.8.0_211-b12)
Java HotSpot(TM) 64-Bit Server VM (build 25.211-b12, mixed mode)
常用参数
平时工作JVM常用基本配置参数。
堆默认比例

-Xms 初始大小内存
默认为物理内存1/64,等价于-XX:InitialHeapSize。
-Xmx 最大分配内存
默认为物理内存1/4,等价于-XX:MaxHeapSize。
-Xss 设置单个线程的大小
一般默认为512K~1024K,等价于-XX:ThreadStackSize。
-Xmn 设置年轻代大小
-XX:MetaspaceSize设置元空间大小
案例:-Xms10m -Xmx10m -XX:MetaspaceSize=1024m -XX:+PrintFlagsFinal。
元空间的本质和永久代类似,都是对JVM规范中方法区的实现。不过元空间与永久代之间最大的区别在于:元空间并不在虚拟机中,面是使用本地内存因此,默认情況下,元空间的大小仅受本地内存限制。
-XX:+PrintGCDetails 输出详细GC收集日志信息
JVM参数设置最大最小内存为10m:
-Xms10m -Xmx10m -XX:+PrintGCDetails
代码中设置一个对象为50m:
public class GcDemo{
public static void main(String[] args) throws Exception{
System.out.println(Thread.currentThread().getName() + "启动中");
// 50M
byte[] bytes = new byte[50*1024*1024];
// Thread.sleep(Integer.MAX_VALUE);
}
}
运行结果:报异常OutOfMemoryError: Java heap space
[GC (Allocation Failure) [PSYoungGen: 2048K->504K(2560K)] 2048K->899K(9728K), 0.0013385 secs] [Times: user=0.00 sys=0.00, real=0.00 secs]
main启动中
[GC (Allocation Failure) [PSYoungGen: 799K->480K(2560K)] 1195K->1003K(9728K), 0.0009863 secs] [Times: user=0.00 sys=0.00, real=0.00 secs]
[GC (Allocation Failure) [PSYoungGen: 480K->440K(2560K)] 1003K->963K(9728K), 0.0007481 secs] [Times: user=0.00 sys=0.00, real=0.00 secs]
[Full GC (Allocation Failure) [PSYoungGen: 440K->0K(2560K)] [ParOldGen: 523K->863K(7168K)] 963K->863K(9728K), [Metaspace: 3117K->3117K(1056768K)], 0.0079109 secs] [Times: user=0.00 sys=0.00, real=0.01 secs]
[GC (Allocation Failure) [PSYoungGen: 0K->0K(2560K)] 863K->863K(9728K), 0.0003336 secs] [Times: user=0.00 sys=0.00, real=0.00 secs]
[Full GC (Allocation Failure) [PSYoungGen: 0K->0K(2560K)] [ParOldGen: 863K->846K(7168K)] 863K->846K(9728K), [Metaspace: 3117K->3117K(1056768K)], 0.0077848 secs] [Times: user=0.08 sys=0.00, real=0.01 secs]
Heap
PSYoungGen total 2560K, used 110K [0x00000000ffd00000, 0x0000000100000000, 0x0000000100000000)
eden space 2048K, 5% used [0x00000000ffd00000,0x00000000ffd1ba80,0x00000000fff00000)
from space 512K, 0% used [0x00000000fff80000,0x00000000fff80000,0x0000000100000000)
to space 512K, 0% used [0x00000000fff00000,0x00000000fff00000,0x00000000fff80000)
ParOldGen total 7168K, used 846K [0x00000000ff600000, 0x00000000ffd00000, 0x00000000ffd00000)
object space 7168K, 11% used [0x00000000ff600000,0x00000000ff6d3af0,0x00000000ffd00000)
Metaspace used 3195K, capacity 4496K, committed 4864K, reserved 1056768K
class space used 348K, capacity 388K, committed 512K, reserved 1048576K
Exception in thread "main" java.lang.OutOfMemoryError: Java heap space
at com.example.demo.test01.GcDemo.main(GcDemo.java:6)
GC结果解析
Allocation Failure分配失败。
如下:
[GC (Allocation Failure) [PSYoungGen: 2048K->504K(2560K)] 2048K->899K(9728K), 0.0013385 secs] [Times: user=0.00 sys=0.00, real=0.00 secs]
解析:
PSYoungGen: 2048K->504K(2560K)
新生区:PSYoungGen
2048K:youngGC前新生代大小。
504K:youngGC后新生代大小。
2560K:新生代总大小。
2048K->899K(9728K), 0.0013385 secs
2048K:youngGC前堆内存大小。
899K:youngGC后堆内存大小。
9728K:JVM堆总大小。
0.0013385 secs:youngGC耗时。
[Times: user=0.00 sys=0.00, real=0.00 secs]
user=0.00:youngGC用户耗时。
sys=0.00:youngGC系统耗时。
real=0.00:youngGC真实耗时。
注意:youg区默认大概占堆内存的三分之一:2560K ====> 9728K
Full GC结果解析
Allocation Failure分配失败。
如下:
[Full GC (Allocation Failure) [PSYoungGen: 440K->0K(2560K)] [ParOldGen: 523K->863K(7168K)] 963K->863K(9728K), [Metaspace: 3117K->3117K(1056768K)], 0.0079109 secs] [Times: user=0.00 sys=0.00, real=0.01 secs]
解析:
PSYoungGen: 440K->0K(2560K)
新生区:PSYoungGen。
440K:youngGC前新生代大小。
0K:youngGC后新生代大小,这里的0是数字0。
2560K:新生代总大小。
ParOldGen: 523K->863K(7168K)
养老区:ParOldGen。
523K:GC前养老区大小。
863K:GC后养老区大小。
7168K:养老区总大小。
Metaspace: 3117K->3117K(1056768K)], 0.0079109 secs
元空间/JDK7叫Perm区:Metaspace。
3117K:GC前元空间大小。
3117K:GC后元空间大小。
1056768K:元空间总大小。
0.0079109 secs:GC耗时。
Times: user=0.00 sys=0.00, real=0.01 secs
user=0.00:GC用户耗时。
sys=0.00:GC系统耗时。
real=0.01:GC真实耗时。
-XX:SurvivoRatio 设置新生代中eden和0/1(from/to)空间的比例
默认XX: SurvivorRatio=8, Eden: S0: S1 =8:1:1。
假如:XX: SurvivorRatio=4, Eden: S0: S1 =4:1:1。
SurvivorRatio值就是设置eden区的比例占多少,S0/S1相回。
-XX:NewRatio 配置年轻代与老年代在堆中的占比
默认XX: NewRatio=2;新生代占1,老年代2,年轻代占整个堆的1/3。
假如XX: Newratio=4;新生代占1,老年代4,年轻代占整个堆的1/5。
New Ratio值就是设置老年代的占比,剩下的1给新生代。
-XX:MaxTenuringThreshold 设置垃圾最大年龄
XX: MaxTenuringThreshold=0。如果设置为0的话,则年轻代对象不经过Survivors区,直接进入年老代。对于年老代比较多的应用,可以提高效率。如果将此值设置为一个较大值,则年轻代对象会在Survivor区进行多次复制,这样可以增加对象再年轻代的存活时间,增加在年轻代即被回收的概率。
注意:值必须在0到15之间,不然无法创建虚拟机。
典型设置案例
-Xms128m -Xmx4096m -Xss1024k -XX:MetaspaceSize=512m -XX:+PrintCommandLineFlags -XX:+PrintGCDetails XX:+useSerialGC -Dfile.encoding=UTF-8
注意:
-XX:+PrintCommandLineFlags让JVM打印出那些已经被用户或者JVM设置过的详细的XX参数的名称和值。
换句话说,它列举出 -XX:+PrintFlagsFinal的结果中第三列有":="的参数。
-XX:+UseSerialGC使用串行化回收器。