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的增长空间
以上为个人经验,希望能给大家一个参考,也希望大家多多支持代码网。
发表评论