JVM参数

768 阅读13分钟

引言:更多相关请看 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为例。

在VM options框里配置相关参数
执行下面代码

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使用串行化回收器。