正文
引言:
最近墨白在学习jvm优化相关的技术,所以我准备出一个jvm优化系列的文章,最近也是比较忙,抽空我就会更新,文章内有代码和命令建议大家手敲增加印象,最好能理解,不明白的可以后台留言或者在群里提问;
在本地开发环境中我们很少会遇到需要对jvm进行优化的需求,但是到了生产环境,我们可能将有下面的需求:
在本系类文章中,我将对jvm进行深入的讲解,我们不仅要让程序能跑起来,而且是可以跑的更快!可以分析解决在生产环境中所遇到的各种“棘手”的问题,其中运行的代码和程序建议小伙伴们和墨白一起动手敲敲。
说明:本系列文章使用的jdk版本Windows为1.8,Linux是1.9
在jvm中有很多的参数可以进行设置,这样可以让jvm在各种环境中都能够高效的运行。绝大部分的参数保持默认即可。
标准参数
-help
-version
-X参数 (非标准参数)
-Xint
-Xcomp
-XX参数(使用率较高)
-XX:newSize
-XX:+UseSerialGC
我们可以用java-命令挨个测试这些参数
jvm的标准参数,一般都是很稳定的,在未来的JVM版本中不会改变,可以使用java -help
检索出所有的标准参数。
[root@localhost ~]# java -help
用法: java [options] <主类> [args...]
(执行类)
或 java [options] -jar <jar 文件> [args...]
(执行 jar 文件)
或 java [options] -m <模块>[/<主类>] [args...]
java [options] --module <模块>[/<主类>] [args...]
(执行模块中的主类)
将主类, -jar <jar 文件>, -m 或 --module
<模块>/<主类> 后的参数作为参数传递到主类。
其中, 选项包括:
-d32 已过时, 在以后的发行版中将被删除
-d64 已过时, 在以后的发行版中将被删除
-cp <目录和 zip/jar 文件的类搜索路径>
-classpath <目录和 zip/jar 文件的类搜索路径>
--class-path <目录和 zip/jar 文件的类搜索路径>
使用 : 分隔的, 用于搜索类文件的目录, JAR 档案
和 ZIP 档案列表。
-p <模块路径>
--module-path <模块路径>...
用 : 分隔的目录列表, 每个目录
都是一个包含模块的目录。
--upgrade-module-path <模块路径>...
用 : 分隔的目录列表, 每个目录
都是一个包含模块的目录, 这些模块
用于替换运行时映像中的可升级模块
--add-modules <模块名称>[,<模块名称>...]
除了初始模块之外要解析的根模块。
<模块名称> 还可以为 ALL-DEFAULT, ALL-SYSTEM,
ALL-MODULE-PATH.
--list-modules
列出可观察模块并退出
-d <module name>
--describe-module <模块名称>
描述模块并退出
--dry-run 创建 VM 并加载主类, 但不执行 main 方法。
此 --dry-run 选项对于验证诸如
模块系统配置这样的命令行选项可能非常有用。
--validate-modules
验证所有模块并退出
--validate-modules 选项对于查找
模块路径中模块的冲突及其他错误可能非常有用。
-D<名称>=<值>
设置系统属性
-verbose:[class|module|gc|jni]
启用详细输出
-version 将产品版本输出到错误流并退出
--version 将产品版本输出到输出流并退出
-showversion 将产品版本输出到错误流并继续
--show-version
将产品版本输出到输出流并继续
--show-module-resolution
在启动过程中显示模块解析输出
-? -h -help
将此帮助消息输出到错误流
--help 将此帮助消息输出到输出流
-X 将额外选项的帮助输出到错误流
--help-extra 将额外选项的帮助输出到输出流
-ea[:<程序包名称>...|:<类名>]
-enableassertions[:<程序包名称>...|:<类名>]
按指定的粒度启用断言
-da[:<程序包名称>...|:<类名>]
-disableassertions[:<程序包名称>...|:<类名>]
按指定的粒度禁用断言
-esa | -enablesystemassertions
启用系统断言
-dsa | -disablesystemassertions
禁用系统断言
-agentlib:<库名>[=<选项>]
加载本机代理库 <库名>, 例如 -agentlib:jdwp
另请参阅 -agentlib:jdwp=help
-agentpath:<路径名>[=<选项>]
按完整路径名加载本机代理库
-javaagent:<jar 路径>[=<选项>]
加载 Java 编程语言代理, 请参阅 java.lang.instrument
-splash:<图像路径>
使用指定的图像显示启动屏幕
自动支持和使用 HiDPI 缩放图像
(如果可用)。应始终将未缩放的图像文件名 (例如, image.ext)
作为参数传递给 -splash 选项。
将自动选取提供的最合适的缩放
图像。
有关详细信息, 请参阅 SplashScreen API 文档
@argument 文件
一个或多个包含选项的参数文件
-disable-@files
阻止进一步扩展参数文件
要为长选项指定参数, 可以使用 --<名称>=<值> 或
--<名称> <值>。
[root@localhost ~]# java -version
java version "9.0.4"
Java(TM) SE Runtime Environment (build 9.0.4+11)
Java HotSpot(TM) 64-Bit Server VM (build 9.0.4+11, mixed mode)
package com.mobaijun.jvm;
/**
* @Author:Auser·杰
* @DATE:2019/10/8 23:27
*/
public class TestJVM {
public static void main(String[] args) {
String str = System.getProperty("str");
if (str == null){
System.out.println("mobaijun");
}else {
System.out.println(str);
}
}
}
结果:
用Linux编译运行,通过-D设置属性参数
== 根目录下创建test文件夹存放java文件
[root@localhost ~]# mkdir test
== 查看目录内容
[root@localhost ~]# ll
总用量 2
drwxr-xr-x. 2 root root 6 10月 8 23:57 test
== 进入test目录
[root@localhost ~]# cd test
== vim命令创建TestJVM.java文件,复制刚刚写的代码,esc返回,shift+:,输入wq保存
[root@localhost test]# vim TestJVM.java
== 编译class文件
[root@localhost test]# javac TestJVM.java
[root@localhost test]# ll
总用量 8
-rw-r--r--. 1 root root 575 10月 8 23:58 TestJVM.class
-rw-r--r--. 1 root root 225 10月 8 23:58 TestJVM.java
== 运行
[root@localhost test]# java TestJVM
mobaijun
== 通过-D设置属性参数
[root@localhost test]# java -Dstr=nihaojvm TestJVM
== 运行结果
nihaojvm
可以通过-server或-client设置jvm的运行参数。
1.如果是Windows系统,不论硬件配置如何,都默认使用Client类型的JVM。
2.如果是其他操作系统上,机器配置有2GB以上的内存同时有2个以上CPU的话默认使用server模式,否则使用client模式。
1.只有server类型,不支持client类型。
运行测试
[root@localhost test]# java -client -showversion TestJVM
java version "9.0.4"
Java(TM) SE Runtime Environment (build 9.0.4+11)
Java HotSpot(TM) 64-Bit Server VM (build 9.0.4+11, mixed mode)
mobaijun
[root@localhost test]# java -server -showversion TestJVM
java version "9.0.4"
Java(TM) SE Runtime Environment (build 9.0.4+11)
Java HotSpot(TM) 64-Bit Server VM (build 9.0.4+11, mixed mode)
mobaijun
jvm的-X参数是非标准参数,在不同版本的jvm中,参数可能会有所不同,可以通过java -X查看非标准参数。
[root@localhost test]# java -X
-Xbatch 禁用后台编译
-Xbootclasspath/a:<directories and zip/jar files separated by :>
附加在引导类路径末尾
-Xcheck:jni 对 JNI 函数执行其他检查
-Xcomp 在首次调用时强制编译方法
-Xdebug 为实现向后兼容而提供
-Xdiag 显示附加诊断消息
-Xfuture 启用最严格的检查, 预期将来的默认值
-Xint 仅解释模式执行
-Xinternalversion
显示比 -version 选项更详细的 JVM
版本信息
-Xloggc:<file> 将 GC 状态记录在文件中 (带时间戳)
-Xmixed 混合模式执行 (默认值)
-Xmn<size> 为年轻代 (新生代) 设置初始和最大堆大小
(以字节为单位)
-Xms<size> 设置初始 Java 堆大小
-Xmx<size> 设置最大 Java 堆大小
-Xnoclassgc 禁用类垃圾收集
-Xprof 输出 cpu 分析数据 (已过时)
-Xrs 减少 Java/VM 对操作系统信号的使用 (请参阅文档)
-Xshare:auto 在可能的情况下使用共享类数据 (默认值)
-Xshare:off 不尝试使用共享类数据
-Xshare:on 要求使用共享类数据, 否则将失败。
-XshowSettings 显示所有设置并继续
-XshowSettings:all
显示所有设置并继续
-XshowSettings:locale
显示所有与区域设置相关的设置并继续
-XshowSettings:properties
显示所有属性设置并继续
-XshowSettings:vm 显示所有与 vm 相关的设置并继续
-Xss<size> 设置 Java 线程堆栈大小
-Xverify 设置字节码验证器的模式
--add-reads <module>=<target-module>(,<target-module>)*
更新 <module> 以读取 <target-module>, 而无论
模块声明如何。
<target-module> 可以是 ALL-UNNAMED 以读取所有未命名
模块。
--add-exports <module>/<package>=<target-module>(,<target-module>)*
更新 <module> 以将 <package> 到处到 <target-module>,
而无论模块声明如何。
<target-module> 可以是 ALL-UNNAMED 以导出到所有
未命名模块。
--add-opens <module>/<package>=<target-module>(,<target-module>)*
更新 <module> 以在 <target-module> 中打开
<package>, 而无论模块声明如何。
--illegal-access=<value>
允许或拒绝通过未命名模块中的代码对命名模块中的
类型成员进行访问。
<value> 为 "deny", "permit", "warn" 或 "debug" 之一
此选项将在未来发行版中删除。
--limit-modules <module name>[,<module name>...]
限制可观察模块的领域
--patch-module <module>=<file>(:<file>)*
使用 JAR 文件或目录中的类和资源
覆盖或增强模块。
--disable-@files 禁止进一步扩展参数文件
这些额外选项如有更改, 恕不另行通知。
在解释模式(interpreted mode)下,-Xint标记会强制JVM执行所有的字节码,当然这会降低运行速度,通常低10倍或更多。
-Xcomp参数与它(-Xint)正好相反,JVM在第一次使用时会把所有的字节码编译成本地代码,从而带来最大程度的优化。
然而,很多应用在使用-Xcomp也会有一些性能损失,当然这比使用-Xint损失的少,原因是-xcomp没有让JVM启用JIT编译器的全部功能。JIT编译器可以对是否需要编译做判断,如果所有代码都进行编译的话,对于一些只执行一次的代码就没有意义了。
-Xmixed是混合模式,将解释模式与编译模式进行混合使用,由jvm自己决定,这是jvm默认的模式,也是推荐使用的模式。
比方强制设置运行模式:
== 强制设置为解释模式
[root@localhost test]# java -showversion -Xint TestJVM
java version "9.0.4"
Java(TM) SE Runtime Environment (build 9.0.4+11)
Java HotSpot(TM) 64-Bit Server VM (build 9.0.4+11, interpreted mode)
mobaijun
== 强制设置为编译模式
== 需要注意的是:编译模式下,第一次执行速度会比解释模式下执行速度慢一些,需要注意观察。
[root@localhost test]# java -showversion -Xcomp TestJVM
java version "9.0.4"
Java(TM) SE Runtime Environment (build 9.0.4+11)
Java HotSpot(TM) 64-Bit Server VM (build 9.0.4+11, compiled mode)
mobaijun
== 默认的混合模式
[root@localhost test]# java -showversion TestJVM
java version "9.0.4"
Java(TM) SE Runtime Environment (build 9.0.4+11)
Java HotSpot(TM) 64-Bit Server VM (build 9.0.4+11, mixed mode)
mobaijun
-XX参数也是非标准参数,主要用于jvm的调优和debug操作。
-XX参数的使用有2种方式,一种是boolean类型,一种是非boolean类型:
boolean类型
格式:-XX:[+-]
如:-XX:+DisableExplicitGC 表示禁用手动调用gc操作,也就是说调用
System.gc()无效
非boolean类型
格式:-XX:
如:-XX:NewRatio=1 表示新生代和老年代的比值
测试:
[root@localhost test]# java -showversion -XX:+DisableExplicitGC TestJVM
java version "9.0.4"
Java(TM) SE Runtime Environment (build 9.0.4+11)
Java HotSpot(TM) 64-Bit Server VM (build 9.0.4+11, mixed mode)
mobaijun
1.-Xms与-Xmx分别是设置jvm的堆内存的初始大小和最大大小。
2.-Xmx2048m:等价于-XX:MaxHeapSize,设置JVM最大堆内存为2048M。
3.-Xms512m:等价于-XX:InitialHeapSize,设置JVM初始堆内存为512M。
4.适当的调整jvm的内存大小,可以充分利用服务器资源,让程序跑的更快。
测试:
== 可以很明显的感觉到输出速度变快了
[root@localhost test]# java -Xms512m -Xmx2048m TestJVM
mobaijun