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