JVM之JVM虚拟机参数配置
JVM参数
JVM参数类型分为三类:
标准参数
-X参数 (非标准参数)
-XX参数(使用率较高)
标准参数
jvm的标准参数,一般很稳定,在未来JVM版本中不会改变,可以使用java -help检索出所有的标准参数
D:\>java -help
用法: 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。
设置运行JVM参数测试
1.程序代码如下
public class Test {
public static void main(String[] args) {
String test = System.getProperty("test");
System.out.println("test: " + test);
}
}
2.在运行时指定JVM参数,使用-D参数名=值
的形式,在spring boot中使用较多
已连接到目标 VM, 地址: ''127.0.0.1:6164',传输: '套接字''
test: Ok
与目标 VM 断开连接, 地址为: ''127.0.0.1:6164',传输: '套接字''
-X参数
jvm的-X参数是非标准参数,意味着在不同的jvm版本中,参数可能会变动,可以通过
java -X
查看非标准参数。
D:\>java -X
-Xmixed 混合模式执行(默认)
-Xint 仅解释模式执行
-Xbootclasspath:<用 ; 分隔的目录和 zip/jar 文件>
设置引导类和资源的搜索路径
-Xbootclasspath/a:<用 ; 分隔的目录和 zip/jar 文件>
附加在引导类路径末尾
-Xbootclasspath/p:<用 ; 分隔的目录和 zip/jar 文件>
置于引导类路径之前
-Xdiag 显示附加诊断消息
-Xnoclassgc 禁用类垃圾收集
-Xincgc 启用增量垃圾收集
-Xloggc:<file> 将 GC 状态记录在文件中(带时间戳)
-Xbatch 禁用后台编译
-Xms<size> 设置初始 Java 堆大小
-Xmx<size> 设置最大 Java 堆大小
-Xss<size> 设置 Java 线程堆栈大小
-Xprof 输出 cpu 分析数据
-Xfuture 启用最严格的检查,预计会成为将来的默认值
-Xrs 减少 Java/VM 对操作系统信号的使用(请参阅文档)
-Xcheck:jni 对 JNI 函数执行其他检查
-Xshare:off 不尝试使用共享类数据
-Xshare:auto 在可能的情况下使用共享类数据(默认)
-Xshare:on 要求使用共享类数据,否则将失败。
-XshowSettings 显示所有设置并继续
-XshowSettings:system
(仅限 Linux)显示系统或容器
配置并继续
-XshowSettings:all
显示所有设置并继续
-XshowSettings:vm 显示所有与 vm 相关的设置并继续
-XshowSettings:properties
显示所有属性设置并继续
-XshowSettings:locale
显示所有与区域设置相关的设置并继续
-X 选项是非标准选项。如有更改,恕不另行通知。
-XX参数
-XX参数也是非标准参数,数是使用得最多的参数,主要用于JVM调优和Debug操作。
-XX参数的使用方式:
一种是boolean类型
一种是非boolean类型
Boolean类型
格式:-XX:[+-]<name> +或-表示启用或者禁用name属性
-XX:+UseConcMarkSweepGC 表示启用CMS类型的垃圾回收器
-XX:+UseG1GC 表示启用G1类型的垃圾回收器
-XX:+DisableExplicitGC 表示禁用手动调用gc操作,调用System.gc()无效
非Boolean类型
格式:-XX:<name>=<value>表示name属性的值是value
-XX:MaxGCPauseMillis=500 表示每次GC最大的停顿毫秒数
-XX:GCTimeRatio=nnn 表示希望在GC花费不超过应用程序执行时间的1/(1+nnn),nnn为大于0小于100的整数。
-XX:NewRatio=1 表示新生代和老年代的比值
运行参数
运行java命令时打印参数
运行java命令时打印参数,添加 -XX:+PrintFlagsFinall参数即可
java -XX:+PrintFlagsFinal
查看正在运行的jvm参数
如果想要查看正在运行的jvm就需要借助于jinfo命令查看
通过jps
命令或者jps ‐l
命令查看java进程
[root@administrator ~]# jps
57797 Jps
1320 Application
18876 Bootstrap
[root@administrator ~]# jps -l
1320 com.aliyun.tianji.cloudmonitor.Application
57865 sun.tools.jps.Jps
18876 org.apache.catalina.startup.Bootstrap
查看所有的参数:jinfo ‐flags 进程id
[root@administrator ~]# jinfo -flags 1320
Attaching to process ID 1320, please wait...
查看某一参数的值:jinfo ‐flag 参数名 进程id
[root@administrator ~]# jinfo -flags MaxHeapSize 1320
Attaching to core 1320 from executable MaxHeapSize, please wait...
将运行JVM参数写入某路径某文件
java -XX:+PrintFlagsFinal > flagsFinal.txt
参数有boolean类型和数字类型,值的操作符是=或:=,分别代表默认值和被修改的值
JVM参数配置
虚拟机提供了一些跟踪系统状态的参数,使用给定的参数执行Java虚拟机,就可以在系统运行时打印相关日志,用于分析实际问题。进行虚拟机参数配置,其实就是围绕着堆、栈、方法区、进行配置。
堆的参数配置
-XX:+PrintGC 每次触发GC的时候打印相关日志
-XX:+UseSerialGC 串行回收
-XX:+PrintGCDetails 更详细的GC日志
-Xms 堆初始值
-Xmx 堆最大可用值
-Xmn 新生代堆最大可用值
-XX:SurvivorRatioo=eden/from=den/to 用来设置新生代中eden空间和from/to空间的比例
-XX:NewRatio=老年代/新生代 设置新生代和老年代的比例
设置最大堆内存
-Xms5m -Xmx20m -XX:+PrintGCDetails -XX:+UseSerialGC
public static void main(String[] args) throws InterruptedException {
byte[] bytes1 = new byte[1 * 1024 * 1024];
System.out.println("分配1m");
pintJvmInfo();
Thread.sleep(3000);
byte[] bytes2 = new byte[4 * 1024 * 1024];
System.out.println("分配4m");
Thread.sleep(3000);
pintJvmInfo();
}
static private void pintJvmInfo() {
// 最大内存
long maxMemory = Runtime.getRuntime().maxMemory();
System.out.println("最大内存:" + maxMemory);
// 当前空闲内存
long freeMemory = Runtime.getRuntime().freeMemory();
System.out.println("当前空闲内存:" +freeMemory);
// 已使用内存
long totalMemory = Runtime.getRuntime().totalMemory();
System.out.println("已使用内存:" +totalMemory);
}
[GC (Allocation Failure) [DefNew: 1580K->192K(1856K), 0.0060484 secs] 1580K->590K(5952K), 0.0062694 secs] [Times: user=0.00 sys=0.00, real=0.01 secs]
分配1m
最大内存:20316160
当前空闲内存:4391080
已使用内存:6094848
[GC (Allocation Failure) [DefNew: 1856K->192K(1856K), 0.0020850 secs] 2254K->1876K(5952K), 0.0021337 secs] [Times: user=0.01 sys=0.00, real=0.00 secs]
[GC (Allocation Failure) [DefNew: 619K->138K(1856K), 0.0007739 secs][Tenured: 1858K->1996K(4096K), 0.0021105 secs] 2303K->1996K(5952K), [Metaspace: 3800K->3800K(1056768K)], 0.0029790 secs] [Times: user=0.00 sys=0.00, real=0.00 secs]
分配4m
最大内存:20316160
当前空闲内存:4090896
已使用内存:10358784
Heap
def new generation total 1920K, used 45K [0x00000000fec00000, 0x00000000fee10000, 0x00000000ff2a0000)
eden space 1728K, 2% used [0x00000000fec00000, 0x00000000fec0b6f0, 0x00000000fedb0000)
from space 192K, 0% used [0x00000000fedb0000, 0x00000000fedb0000, 0x00000000fede0000)
to space 192K, 0% used [0x00000000fede0000, 0x00000000fede0000, 0x00000000fee10000)
tenured generation total 8196K, used 6092K [0x00000000ff2a0000, 0x00000000ffaa1000, 0x0000000100000000)
the space 8196K, 74% used [0x00000000ff2a0000, 0x00000000ff893390, 0x00000000ff893400, 0x00000000ffaa1000)
Metaspace used 3807K, capacity 4540K, committed 4864K, reserved 1056768K
class space used 420K, capacity 428K, committed 512K, reserved 1048576K
设置新生代比例参数
-Xms20m -Xmx20m -Xmn1m -XX:SurvivorRatio=2 -XX:+PrintGCDetails -XX:+UseSerialGC
-Xmn 新生代大小,一般设为整个堆的1/3到1/4左右
-XX:SurvivorRatio 设置新生代中eden区和from/to空间的比例关系n/1
public static void main(String[] args) {
//-Xms20m -Xmx20m -Xmn1m -XX:SurvivorRatio=2 -XX:+PrintGCDetails -XX:+UseSerialGC
//-XX:NewRatio=老年代/新生代
byte[] b = null;
for (int i = 0; i < 10; i++) {
b = new byte[1 * 1024 * 1024];
}
}
[GC (Allocation Failure) [DefNew: 507K->255K(768K), 0.0013037 secs] 507K->430K(20224K), 0.0013717 secs] [Times: user=0.00 sys=0.00, real=0.00 secs]
[GC (Allocation Failure) [DefNew: 767K->109K(768K), 0.0034085 secs] 942K->539K(20224K), 0.0035385 secs] [Times: user=0.02 sys=0.00, real=0.00 secs]
[GC (Allocation Failure) [DefNew: 621K->155K(768K), 0.0011903 secs] 1051K->586K(20224K), 0.0012244 secs] [Times: user=0.00 sys=0.00, real=0.00 secs]
Heap
def new generation total 768K, used 326K [0x00000000fec00000, 0x00000000fed00000, 0x00000000fed00000)
eden space 512K, 33% used [0x00000000fec00000, 0x00000000fec2aa90, 0x00000000fec80000)
from space 256K, 60% used [0x00000000fecc0000, 0x00000000fece6f08, 0x00000000fed00000)
to space 256K, 0% used [0x00000000fec80000, 0x00000000fec80000, 0x00000000fecc0000)
tenured generation total 19456K, used 10670K [0x00000000fed00000, 0x0000000100000000, 0x0000000100000000)
the space 19456K, 54% used [0x00000000fed00000, 0x00000000ff76ba28, 0x00000000ff76bc00, 0x0000000100000000)
Metaspace used 3298K, capacity 4496K, committed 4864K, reserved 1056768K
class space used 359K, capacity 388K, committed 512K, reserved 1048576K
设置新生与老年代参数
基本策略:尽可能将对象预留在新生代,减少老年代的GC次数。
-Xms20m -Xmx20m -XX:SurvivorRatio=2 -XX:+PrintGCDetails -XX:+UseSerialGC -XX:NewRatio=2
[GC (Allocation Failure) [DefNew: 2718K->1617K(5120K), 0.0031155 secs] 2718K->1617K(18816K), 0.0032612 secs] [Times: user=0.00 sys=0.00, real=0.00 secs]
[GC (Allocation Failure) [DefNew: 4790K->1044K(5120K), 0.0016988 secs] 4790K->1634K(18816K), 0.0017286 secs] [Times: user=0.00 sys=0.00, real=0.00 secs]
[GC (Allocation Failure) [DefNew: 4198K->1024K(5120K), 0.0006546 secs] 4788K->1635K(18816K), 0.0006926 secs] [Times: user=0.00 sys=0.00, real=0.00 secs]
Heap
def new generation total 5120K, used 4231K [0x00000000fec00000, 0x00000000ff2a0000, 0x00000000ff2a0000)
eden space 3456K, 92% used [0x00000000fec00000, 0x00000000fef21c88, 0x00000000fef60000)
from space 1664K, 61% used [0x00000000ff100000, 0x00000000ff2000c8, 0x00000000ff2a0000)
to space 1664K, 0% used [0x00000000fef60000, 0x00000000fef60000, 0x00000000ff100000)
tenured generation total 13696K, used 610K [0x00000000ff2a0000, 0x0000000100000000, 0x0000000100000000)
the space 13696K, 4% used [0x00000000ff2a0000, 0x00000000ff338b40, 0x00000000ff338c00, 0x0000000100000000)
Metaspace used 3244K, capacity 4496K, committed 4864K, reserved 1056768K
class space used 353K, capacity 388K, committed 512K, reserved 1048576K
内存溢出解决办法
设置堆内存大小
public static void main(String[] args) throws InterruptedException {
byte[] bytes1 = new byte[5 * 1024 * 1024];
}
-Xms5m -Xmx5m -XX:+PrintGCDetails -XX:+UseSerialGC
[GC (Allocation Failure) [DefNew: 1615K->192K(1856K), 0.0015666 secs][Tenured: 401K->592K(4096K), 0.0017534 secs] 1615K->592K(5952K), [Metaspace: 3202K->3202K(1056768K)], 0.0034064 secs] [Times: user=0.00 sys=0.00, real=0.00 secs]
[Full GC (Allocation Failure) [Tenured: 592K->574K(4096K), 0.0016865 secs] 592K->574K(5952K), [Metaspace: 3202K->3202K(1056768K)], 0.0017093 secs] [Times: user=0.00 sys=0.00, real=0.00 secs]
Heap
def new generation total 1856K, used 73K [0x00000000ffa00000, 0x00000000ffc00000, 0x00000000ffc00000)
eden space 1664K, 4% used [0x00000000ffa00000, 0x00000000ffa12798, 0x00000000ffba0000)
from space 192K, 0% used [0x00000000ffbd0000, 0x00000000ffbd0000, 0x00000000ffc00000)
to space 192K, 0% used [0x00000000ffba0000, 0x00000000ffba0000, 0x00000000ffbd0000)
tenured generation total 4096K, used 574K [0x00000000ffc00000, 0x0000000100000000, 0x0000000100000000)
the space 4096K, 14% used [0x00000000ffc00000, 0x00000000ffc8f990, 0x00000000ffc8fa00, 0x0000000100000000)
Metaspace used 3239K, capacity 4496K, committed 4864K, reserved 1056768K
class space used 356K, capacity 388K, committed 512K, reserved 1048576K
Exception in thread "main" java.lang.OutOfMemoryError: Java heap space
-Xms5m -Xmx10m -XX:+PrintGCDetails -XX:+UseSerialGC
[GC (Allocation Failure) [DefNew: 1615K->192K(1856K), 0.0017103 secs][Tenured: 402K->593K(4096K), 0.0017234 secs] 1615K->593K(5952K), [Metaspace: 3204K->3204K(1056768K)], 0.0035308 secs] [Times: user=0.00 sys=0.00, real=0.00 secs]
Heap
def new generation total 1920K, used 97K [0x00000000ff600000, 0x00000000ff810000, 0x00000000ff950000)
eden space 1728K, 5% used [0x00000000ff600000, 0x00000000ff618738, 0x00000000ff7b0000)
from space 192K, 0% used [0x00000000ff7b0000, 0x00000000ff7b0000, 0x00000000ff7e0000)
to space 192K, 0% used [0x00000000ff7e0000, 0x00000000ff7e0000, 0x00000000ff810000)
tenured generation total 6848K, used 5713K [0x00000000ff950000, 0x0000000100000000, 0x0000000100000000)
the space 6848K, 83% used [0x00000000ff950000, 0x00000000ffee4688, 0x00000000ffee4800, 0x0000000100000000)
Metaspace used 3285K, capacity 4496K, committed 4864K, reserved 1056768K
class space used 357K, capacity 388K, committed 512K, reserved 1048576K
设置栈内存大小
栈溢出产生于递归调用,循环遍历是不会的,但是循环方法里面产生递归调用, 也会发生栈溢出。
解决办法: -Xss5m 设置最大调用深度
private static int count;
public static void main(String[] args) {
count();
}
public static void count() {
try {
count++;
count();
} catch (Throwable e) {
System.out.println("最大深度:" + count);
e.printStackTrace();
}
}
-Xss1m
最大深度:12234
java.lang.StackOverflowError
at sun.misc.Unsafe.compareAndSwapLong(Native Method)
-Xss2m
最大深度:68047
*** java.lang.instrument ASSERTION FAILED ***: "!errorOutstanding" with message transform method call failed at JPLISAgent.c line: 844
java.lang.StackOverflowError
Tomcat内存溢出
在catalina.sh 修改JVM堆内存大小
JAVA_OPTS="-server -Xms800m -Xmx800m -XX:PermSize=256m -XX:MaxPermSize=512m -XX:MaxNewSize=512m"
常用参数
堆相关
参数 | 含义 |
---|---|
-XX:InitialHeapSize=100M | 设置JVM初始堆内存,简写:-Xms100M |
-XX:MaxHeapSize=100M | 设置JVM最大堆内存,简写:-Xms100M |
-XX:NewSize=20M | 设置年轻代的大小 |
-XX:MaxNewSize=50M | 年轻代最大大小 |
-XX:OldSize=50M | 设置老年代大小 |
-XX:MetaspaceSize=50M | 设置方法区大小 |
-XX:MaxMetaspaceSize=50M | 方法区最大大小 |
-XX:+HeapDumpOnOutOfMemoryError | 启动堆内存溢出打印,当JVM堆内存发生溢出时,也就是OOM,自动生成dump文件 |
-XX:HeapDumpPath=heap.hprof | 指定堆内存溢出打印目录,表示在当前目录生成一个heap.hprof文件 |
-XX:ThreadStackSize=128 | 设置每个线程的堆栈大小,简写:-Xss100 ,3000-5000最佳 |
GC相关
参数 | 含义 | 说明 |
---|---|---|
-XX:+UseParallelGC | 使用UseParallelGC | 新生代,吞吐量优先 |
-XX:+UseParallelOldGC | 使用UseParallelOldGC | 老年代,吞吐量优先 |
-XX:+UseConcMarkSweepGC | 使用CMS | 老年代,停顿时间优先 |
-XX:+UseG1GC | 使用G1GC | 新生代,老年代,停顿时间优先 |
-XX:+PrintGCDetails -XX:+PrintGCTimeStamps -XX:+PrintGCDateStamps -Xloggc:g1-gc.log | 打印出GC日志 | 可以使用不同的垃圾收集器,对比查看GC情况 |
-XX:G1HeapWastePercent | 允许的浪费堆空间的占比 | 默认是10%,如果并发标记可回收的空间小于10%,则不会触发MixedGC |
-XX:MaxGCPauseMillis=200ms | G1最大停顿时间 | 暂停时间不能太小,太小的话就会导致出现G1跟不上垃圾产生的速度。最终退化成FullGC。所以对这个参数的调优是一个持续的过程,逐步调整到最佳状态 |
-XX:ConcGCThreads=n | 并发垃圾收集器使用的线程数量 | 默认值随JVM运行的平台不同而不同 |
-XX:G1MixedGCLiveThresholdPercent=65 | 混合垃圾回收周期中要包括的旧区域设置占用率阈值 | 默认占用率为 65% |
-XX:G1MixedGCCountTarget=8 | 设置标记周期完成后,对存活数据上限为G1MixedGCLIveThresholdPercent的旧区域执行混合垃圾回收的目标次数 | 默认8次混合垃圾回收,混合回收的目标是要控制在此目标次数以内 |
-XX:G1OldCSetRegionThresholdPercent=1 | 描述Mixed GC时,Old Region被加入到CSet中 | 默认情况下,G1只把10%的Old Region加入到CSet中 |
-XX:InitiatingHeapOccupancyPercent | 启动并发GC周期时堆内存使用占比 | G1之类的垃圾收集器用它来触发并发GC周期,基于整个堆的使用率,而不只是某一代内存的使用比. 值为 0 则表示”一直执行GC循环”. 默认值为 45 |
其他
参数 | 含义 | 说明 |
---|---|---|
-XX:CICompilerCount=3 | 最大并行编译数 | 如果设置大于1,虽然编译速度会提高,但是同样影响系统稳定性,会增加JVM崩溃的可能 |
-XX:NewRatio | 新老生代的比值 | 如-XX:Ratio=4,则表示新生代:老年代=1:4,也就是新生代占整个堆内存的1/5 |
-XX:SurvivorRatio | 两个S区和Eden区的比值 | 如-XX:SurvivorRatio=8,也就是(S0+S1):Eden=2:8,也就是一个S占整个新生代的1/10 |
-XX:MaxTenuringThreshold=6 | 提升年老代的最大临界值 | 默认值为 15 |
JVM参数配置总结
默认情况不做任何JVM参数设置JVM会工作的很好。但是,在JVM启动参数中,可以设置跟内存、垃圾回收相关参数,针对不同应用,不断仔细调优后能获得最佳性能。
调优核心:
GC的时间足够的小
GC的次数足够的少
发生Full GC的周期足够的长
1.GC时间与GC次数是相悖的,要想GC时间小必须要一个更小的堆,要保证GC次数足够少,必须保证一个更大的堆,只能取其平衡。
2.针对JVM堆的设置,一般可以通过
-Xms -Xmx
限定其最小、最大值,防止垃圾收集器在最小、最大之间收缩堆而产生额外的时间,通常把最大、最小设置为相同的值
3.年轻代和年老代根据默认比例(1:2)分配堆内存,可以通过调整二者之间的比率NewRadio来调整二者间的大小,也可以针对回收代,如年轻代,通过
-XX:newSize -XX:MaxNewSize
设置其绝对大小。同样,防止年轻代的堆收缩,通常会把-XX:newSize -XX:MaxNewSize
设置为同样大小
4.年轻代和年老代设置的设置比例是需要根据实际场景调优设置的。
更大的年轻代必然导致更小的年老代,大的年轻代会延长普通GC的周期,但会增加每次GC的时间,小的年老代会导致更频繁的Full GC
更小的年轻代必然导致更大年老代,小的年轻代会导致普通GC很频繁,但每次的GC时间会更短,大的年老代会减少Full GC的频率
根据对象生命周期的分布情况判断:
如果应用存在大量的临时对象,应该选择更大的年轻代
如果存在相对较多的持久对象,年老代应该适当增大。
在多数应用中没有明显特性,可根据以下两点考虑:
本着Full GC尽量少的原则,让年老代尽量缓存常用对象,JVM的默认比例1:2也是这个道理
在不影响Full GC的前提下,根据实际情况加大年轻代,如把比例控制在1:1。但应该给年老代至少预留1/3的增长空间
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/136871.html