01-JVM参数选项
官网地址:https://docs.oracle.com/javase/8/docs/technotes/tools/windows/java.html
类型一:标准参数选项
特点
比较稳定,后续版本基本不会变化
以-开头
各种选项
直接在DOS窗口中运行java或者java -help可以看到所有的标准选项
TN-MA-L00000832deMacBook-Pro:~ lzg$ 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
补充内容:-server与-client
Hotspot JVM 有两种模式,分别是 server 和 client,分别通过-server 和-client 模式设置
- 32 位系统上,默认使用 Client 类型的 JVM。要想使用 Server 模式,机器配置至少有 2 个以上的 CPU 和 2G 以上的物理内存。client 模式适用于对内存要求较小的桌面应用程序,默认使用 Serial 串行垃圾收集器
- 64 位系统上,只支持 server 模式的 JVM,适用于需要大内存的应用程序,默认使用并行垃圾收集器
官网地址:https://docs.oracle.com/javase/8/docs/technotes/guides/vm/server-class.html
如何知道系统默认使用的是那种模式呢?
通过 java -version 命令:可以看到 Server VM 字样,代表当前系统使用是 Server 模式
类型二:-X参数选项
特点
非标准化参数
功能还是比较稳定的。但官方说后续版本可能会变更
以-X开头
各种选项
直接在DOS窗口中运行java -X命令可以看到所有的X选项
TN-MA-L00000832deMacBook-Pro:~ lizhengguang$ 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 选项是非标准选项。如有更改,恕不另行通知。 以下选项为 Mac OS X 特定的选项: -XstartOnFirstThread 在第一个 (AppKit) 线程上运行 main() 方法 -Xdock:name=<应用程序名称>" 覆盖停靠栏中显示的默认应用程序名称 -Xdock:icon=<图标文件的路径> 覆盖停靠栏中显示的默认图标
JVM的JIT编译模式相关的选项
-Xint:
只使用解释器:所有字节码都被解释执行,这个模式的速度是很慢的
-Xcomp:
只使用编译器:所有字节码第一次使用就被编译成本地代码,然后在执行
-Xmixed
混合模式:这是默认模式,刚开始的时候使用解释器慢慢解释执行,后来让JIT即时编译器根据程序运行的情况,有选择地将某些热点代码提前编译并缓存在本地,在执行的时候效率就非常高了
默认使用的就是这种模式,证明如下:
特别地
-Xmx -Xms -Xss属于XX参数?
-Xms<size>
设置初始Java堆大小,等价于-XX:InitialHeapSize
-Xmx<size>
设置最大Java堆大小,等价于-XX:MaxHeapSize
-Xss<size>
设置Java线程堆栈大小,等价于-XX:ThreadStackSize
类型三:-XX参数选项
特点
非标准化参数
使用的最多的参数类型
这类选项属于实验性,不稳定
以-XX开头
作用
用于开发和调试JVM
分类
Boolean类型格式
-XX:+<option> 表示启用option属性
-XX:-<option> 表示禁用option属性
举例
说明:因为有的指令默认是开启的,所以可以使用-关闭
-XX:+UseParallelGC //选择垃圾收集器为并行垃圾收集器 -XX:+UseG1GC //表示开启G1收集器 -XX:-UseAdaptiveSizePolicy //自动选择年轻代大小和相应的Survivor区比例
非Boolean类型格式(key-value类型)
子类型1:数值型格式-XX:<option>=<number>
number表示数值,number可以带上单位,比如:m,M表示兆,k,K表示Kb,g,G表示Gb
-XX:NewSize=1024m //表示设置新生代大小是1G -XX:MaxGCPauseMillis=500 //表示设置GC停顿时间:500毫秒 -XX:GCTimeRatio=19 //表示设置吞吐量 -XX:NewRatio=2 //表示新生代与老年代的比例是1:2
子类型2:非数值型格式-XX:<name>=<string>
-XX:HeapDumpPath=C:/log/java/java_heapdump.hprof //用来指定heap转储文件位置
特别地
-XX:+PrintFlagsFinal
输出所有参数的名称和默认值
默认不包括Diagnostic和Experimental的参数
可以配合-XX:+UnlockDiagnosticVMOptions和-XX:UnlockExperimentalVMOptions使用
02-添加JVM参数选项
Eclipse
1、在空白处单击右键,选择Run As,在选择Run Configurations……
2、设置虚拟机参数
IDEA
1、Edit Configurations…
2、设置虚拟机参数
运行jar包
这是在java -jar demo.jar中的java -jar之间添加了虚拟机配置信息
java -Xms50m -Xmx50m -XX:+PrintGCDetails -XX:+PrintGCTimeStamps -jar demo.jar
通过Tomcat运行war包
Linux系统下可以在tomcat/bin/catalina.sh中添加类似如下配置: JAVA_OPTS="-Xms512M -Xmx1024M"
Windows系统下载catalina.bat中添加类似如下配置: set "JAVA_OPTS=-Xms512M -Xmx1024M"
程序运行过程中
# 设置Boolean类型参数 jinfo -flag [+|-]<name> <pid> # 设置非Boolean类型参数 jinfo -flag <name>=<value> <pid>
03-常用的JVM参数选项
打印设置的XX选项及值
-XX:+PrintCommandLineFlags //程序运行时JVM默认设置或用户手动设置的XX选项 -XX:+PrintFlagsInitial //打印所有XX选项的默认值 -XX:+PrintFlagsFinal //打印所有XX选项的实际值 -XX:+PrintVMOptions //打印JVM的参数
堆、栈、方法区等内存大小设置
# 栈 -Xss128k <==> -XX:ThreadStackSize=128k //设置线程栈的大小为128K # 堆 -Xms2048m <==> -XX:InitialHeapSize=2048m //设置JVM初始堆内存为2048M -Xmx2048m <==> -XX:MaxHeapSize=2048m //设置JVM最大堆内存为2048M -Xmn2g <==> -XX:NewSize=2g -XX:MaxNewSize=2g //设置年轻代大小为2G,官方推荐配置为整个堆大小的3/8 -XX:SurvivorRatio=8 //设置Eden区与Survivor区的比值,默认为8 -XX:NewRatio=2 //设置老年代与年轻代(包括1个Eden区和2个Survivor区)的比例,默认为2 -XX:+UseAdaptiveSizePolicy //设置大小比例自适应,默认开启(开启之后,新生代的 Eden 区域和 Survive 区域不再是 8:1:1,除非通过SurvivorRatio指定) -XX:PretenureSizeThreadshold=1024 //设置让大于此阈值的对象直接分配在老年代,单位为字节,只对Serial、ParNew收集器有效 -XX:MaxTenuringThreshold=15 //设置新生代晋升老年代的年龄限制,默认为15 -XX:TargetSurvivorRatio=50 //设置年轻垃圾收集后使用的幸存者空间的所需百分比(0到100)。默认此选项设置为50%。 # 方法区 永久代 -XX:PermSize=256m //设置永久代初始值为256M -XX:MaxPermSize=256m //设置永久代最大值为256M 元空间 -XX:MetaspaceSize //设置元空间(jdk8)初始值 -XX:MaxMetaspaceSize //设置元空间(jdk8)最大值 -XX:+UseCompressedOops //使用压缩对象指针 -XX:+UseCompressedClassPointers //使用压缩类指针 -XX:CompressedClassSpaceSize //设置Klass Metaspace的大小,默认1G # 直接内存 -XX:MaxDirectMemorySize //指定DirectMemory容量,默认等于Java堆最大值
OutOfMemory相关的选项
-XX:+HeapDumpOnOutOfMemoryError //内存出现OOM时生成Heap转储文件,和-XX:+HeapDumpBeforeFullGC两者互斥 -XX:+HeapDumpBeforeFullGC //出现FullGC时生成Heap转储文件,和-XX:+HeapDumpOnOutMemoryError两者互斥 -XX:HeapDumpPath=<path> //指定heap转储文件的存储路径,默认当前目录 -XX:OnOutOfMemoryError=<path> //指定可行性程序或脚本的路径,当发生OOM时执行脚本
垃圾收集器相关选项
首先需了解垃圾收集器之间的搭配使用关系
- 红色虚线表示在 jdk8 时被 Deprecate,jdk9 时被删除
- 绿色虚线表示在 jdk14 时被 Deprecate
- 绿色虚框表示在 jdk9 时被 Deprecate,jdk14 时被删除
查看默认的垃圾回收器
Serial回收器
Seria收集器作为HotSpot中Client模式下的默认新生代垃圾收集器。Serial old是运行在Client模式下默认的老年代的垃圾回收器。
-XX:+UseSerialGC
指定年轻代和老年代都使用串行收集器。等价于新生代用Serial GC,且老年代用Serial Old GC。可以获得最高的单线程收集效率。
Parnew回收器
-XX:UseParNewGC
手动指定使用ParNew收集器执行内存回收任务,它表示年轻代使用并行收集器,不影响老年代
-XX:ParallelGcThreads
设置年轻代并行收集器的线程数。一般的最好与CPU数量相等,以避免过多的线程影响垃圾收集性能。
默认情况下,当CPU数量小于8个,ParallelGCThreads的值等于CPU数量
当CPU数量大与8个,ParallelGCThreads的值等于3+[5*CPU_count]/8]
根据下图可知,该回收器最终将会没有搭档,那就相当于被遗弃了
Parallel回收器
注意:
1. Parallel回收器主打吞吐量,而CMS和G1主打低延迟,如果主打吞吐量,那么就不应该限制最大停顿时间,所以-XX:MaxGCPauseMills不应该设置
2. -XX:MaxGCPauseMills中的调整堆大小通过默认开启的-XX:+UseAdaptiveSizePolicy来实现
3.
-XX:GCTimeRatio用来衡量吞吐量,并且和-XX:MaxGCPauseMills矛盾,因此不会同时使用
CMS回收器
-XX:ParallelCMSThreads和ParallelGCThreads有关系,ParallelGCThreads在上面Parnew回收器中有提到
补充参数
特别说明
G1回收器
如果使用G1垃圾收集器,不建议设置-Xmn和-XX:NewRatio,毕竟可能影响G1的自动调节
Mixed GC调优参数
怎么选择垃圾收集器
GC日志相关选项
常用参数
-verbose:gc
输出日志信息,默认输出的标准输出
可以独立使用
-XX:+PrintGC
等同于-verbose:gc 表示打开简化的日志
可以独立使用
-XX:+PrintGCDetails
在发生垃圾回收时打印内存回收详细的日志, 并在进程退出时输出当前内存各区域的分配情况
可以独立使用
-XX:+PrintGCTimeStamps
程序启动到GC发生的时间秒数
不可以独立使用,需要配合-XX:+PrintGCDetails使用
-XX:+PrintGCDateStamps
输出GC发生时的时间戳(以日期的形式,例如:2013-05-04T21:53:59.234+0800)
不可以独立使用,可以配合-XX:+PrintGCDetails使用
-XX:+PrintHeapAtGC
每一次GC前和GC后,都打印堆信息
可以独立使用
-XIoggc:<file>
把GC日志写入到一个文件中去,而不是打印到标准输出中
其他参数
-XX:TraceClassLoading
监控类的加载
-XX:PrintGCApplicationStoppedTime
打印GC时线程的停顿时间
-XX:+PrintGCApplicationConcurrentTime
垃圾收集之前打印出应用未中断的执行时间
-XX:+PrintReferenceGC
记录回收了多少种不同引用类型的引用
-XX:+PrintTenuringDistribution
让JVM在每次MinorGC后打印出当前使用的Survivor中对象的年龄分布
-XX:+UseGCLogFileRotation
启用GC日志文件的自动转储
-XX:NumberOfGCLogFiles=1
GC日志文件的循环数目
-XX:GCLogFileSize=1M
控制GC日志文件的大小
其他参数
-XX:+DisableExplicitGC
禁用hotspot执行System.gc(),默认禁用
-XX:ReservedCodeCacheSize=<n>[g|m|k]、-XX:InitialCodeCacheSize=<n>[g|m|k]
指定代码缓存的大小
-XX:+UseCodeCacheFlushing
使用该参数让jvm放弃一些被编译的代码, 避免代码缓存被占满时JVM切换到interpreted-only的情况
-XX:+DoEscapeAnalysis
开启逃逸分析
-XX:+UseBiasedLocking
开启偏向锁
-XX:+UseLargePages
开启使用大页面
-XX:+PrintTLAB
打印TLAB的使用情况
-XX:TLABSize
设置TLAB大小
04-通过Java代码获取JVM参数
/** * * 监控我们的应用服务器的堆内存使用情况,设置一些阈值进行报警等处理 * * @author shkstart * @create 15:23 */ public class MemoryMonitor { public static void main(String[] args) { MemoryMXBean memorymbean = ManagementFactory. getMemoryMXBean (); MemoryUsage usage = memorymbean.getHeapMemoryUsage(); System. out .println( "INIT HEAP: " + usage.getInit() / 1024 / 1024 + "m" ); System. out .println( "MAX HEAP: " + usage.getMax() / 1024 / 1024 + "m" ); System. out .println( "USE HEAP: " + usage.getUsed() / 1024 / 1024 + "m" ); System. out .println( " \n Full Information:" ); System. out .println( "Heap Memory Usage: " + memorymbean.getHeapMemoryUsage()); System. out .println( "Non-Heap Memory Usage: " + memorymbean.getNonHeapMemoryUsage()); System. out .println( "======================= 通过 java 来获取相关系统状态 ============================ " ); System. out .println( " 当前堆内存大小 totalMemory " + ( int ) Runtime. getRuntime ().totalMemory() / 1024 / 1024 + "m" ); // 当前堆内存大小 System. out .println( " 空闲堆内存大小 freeMemory " + ( int ) Runtime. getRuntime ().freeMemory() / 1024 / 1024 + "m" ); // 空闲堆内存大小 System. out .println( " 最大可用总堆内存 maxMemory " + Runtime. getRuntime ().maxMemory() / 1024 / 1024 + "m" ); // 最大可用总堆内存大小 } }
上篇通过Runtime获取