通常,比较有经验的java程序员,都会遇到JVM调优的诉求,这就需要我们了解JVM的工作机制和调优涉及到的运行参数。在jvm中有很多的参数可以自行设置,这样可以让jvm在各种环境中都能够高效的运行。其实绝大部分的参数保持默认即可。
JVM的运行参数有哪些呢?今天先来混个脸熟吧。
标准参数
jvm的标准参数,一般都是很稳定的,在未来的JVM版本中不会改变,可以使用java -help 检索出所有的标准参数。
例如,如下是我本机运行的结果,每个参数后面有比较明确的中文解释。
apple@tank ~ % java -help用法: java [-options] class [args...] (执行类) 或 java [-options] -jar jarfile [args...] (执行 jar 文件)其中选项包括: -d32 使用 32 位数据模型 (如果可用) -d64 使用 64 位数据模型 (如果可用) -server 选择 "server" VM 默认 VM 是 server, 因为您是在服务器类计算机上运行。 -cp -classpath 用 : 分隔的目录, JAR 档案 和 ZIP 档案列表, 用于搜索类文件。 -D= 设置系统属性 -verbose:[class|gc|jni] 启用详细输出 -version 输出产品版本并退出 -version: 警告: 此功能已过时, 将在 未来发行版中删除。 需要指定的版本才能运行 -showversion 输出产品版本并继续 -jre-restrict-search | -no-jre-restrict-search 警告: 此功能已过时, 将在 未来发行版中删除。 在版本搜索中包括/排除用户专用 JRE -? -help 输出此帮助消息 -X 输出非标准选项的帮助 -ea[:...|:] -enableassertions[:...|:] 按指定的粒度启用断言 -da[:...|:] -disableassertions[:...|:] 禁用具有指定粒度的断言 -esa | -enablesystemassertions 启用系统断言 -dsa | -disablesystemassertions 禁用系统断言 -agentlib:[=] 加载本机代理库 , 例如 -agentlib:hprof 另请参阅 -agentlib:jdwp=help 和 -agentlib:hprof=help -agentpath:[=] 按完整路径名加载本机代理库 -javaagent:[=] 加载 Java 编程语言代理, 请参阅 java.lang.instrument -splash: 使用指定的图像显示启动屏幕有关详细信息, 请参阅 http://www.oracle.com/technetwork/java/javase/documentation/index.html。
开发过程中常用的参数有-version、-D,例如通过-version查询当前jdk的版本信息,如下信息可以知道,当前使用的jdk版本是1.8.0_211,使用的是HotSpot 64位虚拟机,默认以Server模式启动,mixed mode代表当前编译器是以混合模式执行,当然我们也可指定其他工作模式,下面就就会介绍。
apple@tank ~ % java -versionjava 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)
-D参数主要用于设置系统数据,设置的键值信息可以通过System.get("key")来进行获取,比如通过如下代码,可以获得外部指定的数据信息
import org.apache.commons.lang3.StringUtils;public class JvmTest { public static void main(String[] args) { testPropertyParam(); } private static void testPropertyParam() { String value = System.getProperty("key"); if (StringUtils.isEmpty(value)) { System.out.println("not exist"); } else { System.out.println(value); } }}
如果我们执行运行程序,会得到输出:not exist
如果我们java -Dkey=value JvmTest,或者在IDE中指定VM Options,则会得到输出:value
-server和-client可以指定JVM运行模式java -server -showversion JvmTest、java -client -showversion JvmTest,大家可以自己测试,不过64位系统总会显示JVM以Server模式运行的,具体原因前文以描述过,不了解的可以再重温下。
-X参数
-X参数是非标准参数,在不同版本的jvm中,参数可能会有所不同,可以通过java - X查看非标准参数,同样会有比较明确的中文解释。
apple@tank ~ % java -X -Xmixed 混合模式执行 (默认) -Xint 仅解释模式执行 -Xbootclasspath: 设置搜索路径以引导类和资源 -Xbootclasspath/a: 附加在引导类路径末尾 -Xbootclasspath/p: 置于引导类路径之前 -Xdiag 显示附加诊断消息 -Xnoclassgc 禁用类垃圾收集 -Xincgc 启用增量垃圾收集 -Xloggc: 将 GC 状态记录在文件中 (带时间戳) -Xbatch 禁用后台编译 -Xms 设置初始 Java 堆大小 -Xmx 设置最大 Java 堆大小 -Xss 设置 Java 线程堆栈大小 -Xprof 输出 cpu 配置文件数据 -Xfuture 启用最严格的检查, 预期将来的默认值 -Xrs 减少 Java/VM 对操作系统信号的使用 (请参阅文档) -Xcheck:jni 对 JNI 函数执行其他检查 -Xshare:off 不尝试使用共享类数据 -Xshare:auto 在可能的情况下使用共享类数据 (默认) -Xshare:on 要求使用共享类数据, 否则将失败。 -XshowSettings 显示所有设置并继续 -XshowSettings:all 显示所有设置并继续 -XshowSettings:vm 显示所有与 vm 相关的设置并继续 -XshowSettings:properties 显示所有属性设置并继续 -XshowSettings:locale 显示所有与区域设置相关的设置并继续-X 选项是非标准选项, 如有更改, 恕不另行通知。以下选项为 Mac OS X 特定的选项: -XstartOnFirstThread 在第一个 (AppKit) 线程上运行 main() 方法 -Xdock:name=" 覆盖停靠栏中显示的默认应用程序名称 -Xdock:icon= 覆盖停靠栏中显示的默认图标
这里,我们又看到了-Xmixed,其实和他类似的还有-Xcomp、-Xint。
- -Xmixed是混合模式,将解释模式与编译模式进行混合使用,由jvm自己决定,这是jvm默认的模式,也是推荐使用的模式。
- -Xint表示在解释模式(interpreted mode)下,-Xint标记会强制JVM执行所有的字节码,当然这会降低运行速度,通常低10倍或更多。
- -Xcomp参数与它(-Xint)正好相反,JVM在第一次使用时会把所有的字节码编译成本地代码,从而带来最大程度的优化。然而,很多应用在使用-Xcomp也会有一些性能损失,当然这比使用-Xint损失的少,原因是-xcomp没有让JVM启用JIT编译器的全部功能。JIT编译器可以对是否需要编译做判断,如果所有代码都进行编译的话,对于一些只执行一次的代码就没有意义了。
下面是强制设定运行模式的示例:
在IDE中指定VM Options为-showversion -Xint(以我使用的IDEA为例)
![b6efafcfd3e299716e3c8c61d954b5bf.png](https://i-blog.csdnimg.cn/blog_migrate/5cb41ab559e796945cbe6b2c948dd75a.jpeg)
设置运行参数
得到输出结果如下,结果显示JVM是运行在解释执行模式:
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)value
同样可以指定其他模式,修改-X参数即可。
-Xms与-Xmx分别是设置jvm的堆内存的初始大小和最大大小。
-Xmx1024m:等价于-XX:MaxHeapSize,设置JVM最大堆内存为1024M。-Xms512m:等价于-XX:InitialHeapSize,设置JVM初始堆内存为512M。适当的调整jvm的内存大小,可以充分利用服务器资源,让程序跑的更快。
-Xms、-Xmx、-Xss等参数的意义看中文描述即可,此处大致了解,后续调优介绍中,会给出设置的建议。
-XX参数
-XX参数也是非标准参数,主要用于jvm的调优和debug操作。-XX参数的使用有2种方式,一种是boolean类型,一种是非boolean类型:
- boolean类型:格式:-XX:[+-],例如:-XX:+DisableExplicitGC 表示禁用手动调用gc操作,也就是说调用System.gc()无效
- 非boolean类型:格式:-XX:,例如:-XX:NewRatio=1 表示新生代和老年代的比值
查看JVM运行参数
- 运行java命令时打印参数:需要添加-XX:+PrintFlagsFinal参数即可。打印结果较长,这里就不粘贴了,感兴趣可以自己查看。
- 查看正在运行的jvm参数:借助于jinfo命令查看,这个更常用一些。
apple@tank bin % jps39141 KotlinCompileDaemon39192 Launcher39193 JvmTest39195 Jps36190apple@tank bin % jinfo -flags 39193VM Flags:-XX:CICompilerCount=4 -XX:InitialHeapSize=536870912 -XX:MaxHeapSize=8589934592 -XX:MaxNewSize=2863136768 -XX:MinHeapDeltaBytes=524288 -XX:NewSize=178782208 -XX:OldSize=358088704 -XX:+UseCompressedClassPointers -XX:+UseCompressedOops -XX:+UseFastUnorderedTimeStamps -XX:+UseParallelGC
以上是jdk13执行的结果,mac上jdk1.8运行的时候,会有如下异常
apple@tank ~ % jinfo -flags 39143Attaching to process ID 39143, please wait...Error attaching to process: sun.jvm.hotspot.debugger.DebuggerException: Can't attach symbolicator to the processsun.jvm.hotspot.debugger.DebuggerException: sun.jvm.hotspot.debugger.DebuggerException: Can't attach symbolicator to the processat sun.jvm.hotspot.debugger.bsd.BsdDebuggerLocal$BsdDebuggerLocalWorkerThread.execute(BsdDebuggerLocal.java:169)at sun.jvm.hotspot.debugger.bsd.BsdDebuggerLocal.attach(BsdDebuggerLocal.java:287)at sun.jvm.hotspot.HotSpotAgent.attachDebugger(HotSpotAgent.java:671)at sun.jvm.hotspot.HotSpotAgent.setupDebuggerDarwin(HotSpotAgent.java:659)at sun.jvm.hotspot.HotSpotAgent.setupDebugger(HotSpotAgent.java:341)at sun.jvm.hotspot.HotSpotAgent.go(HotSpotAgent.java:304)at sun.jvm.hotspot.HotSpotAgent.attach(HotSpotAgent.java:140)at sun.jvm.hotspot.tools.Tool.start(Tool.java:185)at sun.jvm.hotspot.tools.Tool.execute(Tool.java:118)at sun.jvm.hotspot.tools.JInfo.main(JInfo.java:138)at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)at java.lang.reflect.Method.invoke(Method.java:498)at sun.tools.jinfo.JInfo.runTool(JInfo.java:108)at sun.tools.jinfo.JInfo.main(JInfo.java:76)Caused by: sun.jvm.hotspot.debugger.DebuggerException: Can't attach symbolicator to the processat sun.jvm.hotspot.debugger.bsd.BsdDebuggerLocal.attach0(Native Method)at sun.jvm.hotspot.debugger.bsd.BsdDebuggerLocal.access$100(BsdDebuggerLocal.java:65)at sun.jvm.hotspot.debugger.bsd.BsdDebuggerLocal$1AttachTask.doit(BsdDebuggerLocal.java:278)at sun.jvm.hotspot.debugger.bsd.BsdDebuggerLocal$BsdDebuggerLocalWorkerThread.run(BsdDebuggerLocal.java:144)
具体错误分析可以参考https://blog.csdn.net/Dongguabai/article/details/88736589
下一篇JVM系列-4.了解JIT