话不多说,今天就分析一下一些常用的Java虚拟机的参数设置,以及如何更好的使用!
首先想说的是其实这些参数我们并不是陌生的,在平时的开发和使用中经常都会遇到,只是在平时缺少一个比较系统的总结,所以,对这些参数感觉是很陌生的,所以,通过这篇文章的总结,我相信你一定都会对这些参数熟稔于心,做做心中有数。
在Java虚拟机的参数中,其实可以把这些参数分为三类,当然,这是针对JDK1.6来说的,如果对于JDK1.8,那么就不是这么分类的了,但是,由于这两个版本很多常用的参数的差别是不大的,所以这篇文章就先介绍JDK1.6的VM参数。
主要可以分为以下三类:
标准参数(-) 非标准参数(-X) 非Stable参数(-XX)
虽然是这么分类的,实际上呢,非标准参数和非稳定的参数实际的使用中还是用的非常的多的,在后面的文章的介绍中你就会发现。
这一类参数可以说是我们刚刚开始Java是就用的非常多的参数了,比如 java -version
、 java -jar
等等,我们在CMD中输入 java -help
就可以获得Java当前版本的所有标准参数了。
如上图就是JDK1.8的所有标准参数了,下面我们将介绍一些我们会用的比较多的参数。
以client模式启动JVM,这种方式启动速度快,但运行时性能和内存管理效率不高,适合客户端程序或者开发调试。
以server模式启动JVM,与client情况恰好相反。适合生产环境,适用于服务器。64位的JVM自动以server模式启动。
通知JVM类搜索路径。如果指定了 -classpath
,则JVM就忽略 CLASSPATH
中指定的路径。各路径之间以分号隔开。如果 -classpath
和 CLASSPATH
都没有指定,则JVM从当前路径寻找class。
JVM搜索路径的顺序:
Bootstrap,搜索路径可以用 System.getProperty("sun.boot.class.path")
获得;
JRE_HOME/lib/ext
下的jar包。 Extension,搜索路径可以用 System.getProperty("java.ext.dirs")
获得;
搜索路径用 System.getProperty("java.class.path")
获得。
System.out.println(System.getProperty("sun.boot.class.path")); System.out.println(System.getProperty("java.ext.dirs")); System.out.println(System.getProperty("java.class.path"));
如上就是我电脑的JVM的路径。
定义系统的全局属性值,如配置文件地址等,如果value有空格,则需要使用双引号。
另外用 System.getProperty("hello")
可以获得这些定义的属性值,在代码中也可以用 System.setProperty("hello","world")
的形式来定义属性。
如键值对设置为hello=world。
System.out.println(System.getProperty("hello"));
运行结果就是:
查询GC问题最常用的命令之一,参数如下:
-verbose:class
输出JVM载入类的相关信息,当JVM报告说找不到类或者类冲突时可此进行诊断。
-verbose:gc
输出每次GC的相关情况。
-verbose:jni
输出native方法调用的相关情况,一般用于诊断jni调用错误信息。
另外,控制台 输出GC信息 还可以使用如下命令:
在JVM的启动参数中加入 -XX:+PrintGC -XX:+PrintGCDetails -XX:+PrintGCTimeStamps -XX:+PrintGCApplicationStoppedTime
,按照参数的顺序分别输出GC的简要信息,GC的详细信息、GC的时间信息及GC造成的应用暂停的时间。
非标注的参数主要是关于Java内存区域的设置参数,所以在看这些参数之前,应该先查看Java内存区域的基础知识,可以查看这篇文章: 深入理解Java虚拟机-Java内存区域透彻分析 。
非标准参数实在标准参数的基础上的一些扩充参数,可以输入 java -X
,获得当前JVM支持的非标准参数。
从图片中可以看出来,这些非标准的参数其实不多的,下面我们再 讲解一些比较常用的参数。
新生代内存大小的最大值,包括E区和两个S区的总和。设置方法: -Xmn512m、-Xmn2g
。
初始堆的大小,也是堆大小的最小值,默认值是总共的物理内存/64(且小于1G)。默认情况下,当堆中可用内存小于40%,堆内存会开始增加,一直增加到-Xmx的大小。
堆的最大值,默认值是总共的物理内存/64(且小于1G),默认情况下,当堆中可用内存大于70%,堆内存会开始减少,一直减小到-Xms的大小。
因此,为了避免这种浮动,所以在设置 -Xms
和 -Xmx
参数时,一般会设置成一样的,能够提高性能。
另外,官方默认的配置为 年老代大小:年轻代大小=2:1 左右,使用 -XX:NewRatio
可以设置年老代和年轻代之比,例如, -XX:NewRatio=4
,表示 年老代:年轻代=4:1
设置 -Xms
、 -Xmn
和 -Xmx
参数分别为 -Xms512m -Xmx512m -Xmn128m
。同时设置新生代和老生代之比为1:4,E:S0:S1=8:1:1。
** * @ClassName MethodTest * @Description vm参数设置:-Xms512m -Xmx512m -Xmn128m -XX:NewRatio=4 -XX:SurvivorRatio=8 * @Author 欧阳思海 * @Date 2019/11/25 20:06 * @Version 1.0 **/ public class MethodTest { public static void main(String[] args) { List<String> list = new ArrayList<String>(); long i = 0; while (i < 1000000000) { System.out.println(i); list.add(String.valueOf(i++).intern()); } } }
运行之后,用VisualVM查看相关信息是否正确。
当我们 没有设置 -XX:NewRatio=4 -XX:SurvivorRatio=8
时,使用官方默认的情况如下:
上图可以看出, 新生代(Eden Space + Survivor 0 + Survivor 1):老年代(Old Gen)≈ 1:2 。
当我们 设置了 -XX:NewRatio=4 -XX:SurvivorRatio=8
时,情况如下:
变成了 新生代(Eden Space + Survivor 0 + Survivor 1):老年代(Old Gen)≈ 1:4 ,Eden Space:Survivor 0: Survivor 1 = 8:1:1。
从上图可知,堆的信息是正确的。
设置每个线程的栈内存,默认1M,一般来说是不需要改的。
跟踪正运行的程序,并将跟踪数据在标准输出输出;适合于开发环境调试。
禁用类垃圾收集,关闭针对class的gc功能;因为其阻止内存回收,所以可能会导致OutOfMemoryError错误,慎用。
开启增量gc(默认为关闭);这有助于减少长时间GC时应用程序出现的停顿;但由于可能和应用程序并发执行,所以会降低CPU对应用的处理能力。
与 -verbose:gc
功能类似,只是将每次GC事件的相关情况记录到一个文件中,文件的位置最好在本地,以避免网络的潜在问题。
若与verbose命令同时出现在命令行中,则以-Xloggc为准。
在解释模式(interpreted mode)下, -Xint
标记会强制JVM执行所有的字节码,这会降低运行速度,通常低10倍或更多。
-Xcomp参数与它(-Xint)正好相反,JVM在第一次使用时会把所有的字节码编译成本地代码,从而带来最大程度的优化。
然而,很多应用在使用 -Xcomp
也会有一些性能损失,当然这比使用-Xint损失的少,原因是 -xcomp
没有让JVM启用 JIT
编译器的全部功能。JIT编译器可以对是否需要编译做判断,如果所有代码都进行编译的话,对于一些只执行一次的代码就没有意义了。
-Xmixed
是混合模式,这是JVM默认的模式,也是推荐使用的模式。将解释模式与编译模式进行混合使用,由JVM自己决定。
这类参数你一看官网以为不能使用呢,官网给你的建议就是这些参数不稳定,慎用,其实这主要的原因还是因为每个公司的实现都是不一样的,所以就是导致不稳定。但是呢,在实际的使用中却是非常的多的,而且这部分的参数很重要。
这些参数大致可以分为三类:
下面还是先罗列一些比较常用的参数,其实,这些文章很多了,这里主要还是做一个总结,以后自己看文章的时候比较方便,如果有同行看到了文章,你可以参考参考,还是很有帮助的。
另外,选取其中的一些参数做一些例子来解释,这样也能够更加的形象。
参数及其默认值 | 描述 |
---|---|
-XX:LargePageSizeInBytes=4m | 设置用于Java堆的大页面尺寸 |
-XX:MaxHeapFreeRatio=70 | GC后java堆中空闲量占的最大比例 |
-XX:MinHeapFreeRatio=40 | GC后java堆中空闲量占的最小比例 |
-XX:MaxNewSize=size | 新生成对象能占用内存的最大值 |
-XX:MaxPermSize=64m | 老生代对象能占用内存的最大值 |
-XX:NewRatio=2 | 新生代内存容量与老生代内存容量的比例 |
-XX:NewSize=2.125m | 新生代对象生成时占用内存的默认值 |
-XX:ReservedCodeCacheSize=32m | 保留代码占用的内存容量 |
-XX:ThreadStackSize=512 | 设置线程栈大小,若为0则使用系统默认值 |
-XX:+UseLargePages | 使用大页面内存 |
参数及其默认值 | 描述 |
---|---|
-XX:+ScavengeBeforeFullGC | 新生代GC优先于Full GC执行 |
-XX:+UseGCOverheadLimit | 在抛出OOM之前限制jvm耗费在GC上的时间比例 |
-XX:-UseParNewGC | 打开此开关,使用 ParNew+Serial Old 收集器 |
-XX:-UseConcMarkSweepGC | 使用 ParNew+CMS+Serial Old 收集器对老生代采用并发标记交换算法进行GC |
-XX:-UseParallelGC | 启用并行GC,使用 ParallelScavenge+Serial Old 收集器 |
-XX:-UseParallelOldGC | 对Full GC启用并行,当 -XX:-UseParallelGC 启用时该项自动启用, ParallelScavenge+Parallel Old 收集器 |
-XX:-UseSerialGC | 启用串行GC |
-XX:+UseG1GC | 使用垃圾优先(G1)收集器 |
-XX:SurvivorRatio=n | Eden区域与Survivor区域大小之比。预设值为8 |
-XX:PretenureSizeThreshold=n | 直接晋升到老年代的 对象大小 ,设置这个参数之后,大于这个参数的对象直接进入到老年代分配 |
-XX:MaxTenuringThreshold=n | 晋升到老年代的 对象年龄 ,每个对象在坚持过一次Minor GC之后,年龄加1,当超过这个值之后就进入老年代。预设值为15 |
-XX:+UseAdaptiveSizePolicy | 动态调整Java堆中各个区域的大小以及进入老年代的年龄 |
-XX:ParallelGCThreads=n | 设置并行收集器收集时使用的CPU数。并行收集线程数 |
-XX:MaxGCPauseMillis=n | 设置并行收集最大暂停时间 |
-XX:GCTimeRatio=n | 设置垃圾回收时间占程序运行时间的百分比。公式为1/(1+N) |
-XX:+UseThreadPriorities | 启用本地线程优先级 |
-XX:-DisableExplicitGC | 禁止调用 System.gc() ;但jvm的gc仍然有效 |
-XX:+MaxFDLimit | 最大化文件描述符的数量限制 |
前面6个参数都是关于 垃圾收集器 的行为参数,也是经常会用到的参数。
参数及其默认值 | 描述 |
---|---|
-XX:-CITime | 打印消耗在JIT编译的时间 |
-XX:ErrorFile=./hs_err_pid<pid>.log | 保存错误日志或者数据到文件中 |
-XX:HeapDumpPath=./java_pid<pid>.hprof | 指定导出堆信息时的路径或文件名 |
-XX:-HeapDumpOnOutOfMemoryError | 当首次遭遇OOM时导出此时堆中相关信息 |
-XX:OnError="<cmd args>;<cmd args>" | 出现致命ERROR之后运行自定义命令 |
-XX:OnOutOfMemoryError="<cmd args>;<cmd args>" | 当首次遭遇OOM时执行自定义命令 |
-XX:-PrintClassHistogram | 遇到Ctrl-Break后打印类实例的柱状信息,与 jmap -histo 功能相同 |
-XX:-PrintConcurrentLocks | 遇到Ctrl-Break后打印并发锁的相关信息,与 jstack -l 功能相同 |
-XX:-PrintCommandLineFlags | 打印在命令行中出现过的标记 |
-XX:-PrintCompilation | 当一个方法被编译时打印相关信息 |
-XX:-PrintGC | 每次GC时打印相关信息 |
-XX:-PrintGCDetails | 每次GC时打印详细信息 |
-XX:-PrintGCTimeStamps | 打印每次GC的时间戳 |
-XX:-TraceClassLoading | 跟踪类的加载信息 |
-XX:-TraceClassLoadingPreorder | 跟踪被引用到的所有类的加载信息 |
-XX:-TraceClassResolution | 跟踪常量池 |
-XX:-TraceClassUnloading | 跟踪类的卸载信息 |
-XX:-TraceLoaderConstraints | 跟踪类加载器约束的相关信息 |
由于考虑到现在JDK8用的非常的广泛,所以,接下来总结一些JDK8会使用到的参数。
查看这篇 JDK8的参数文章 你会发现,标准参数和非标准参数JDK8的差别并不是很大,如果有其他的参数需要使用,可以查看上面这篇文章。
Java虚拟机深入理解系列全部文章更新中...
2、文章有不当之处,欢迎指正,如果喜欢微信阅读,你也可以关注我的 微信公众号 : 好好学java
,公众号已有 6W 粉丝,回复: 1024 ,获取公众号的大礼包,公众号长期发布 Java 优质系列文章 ,关注我们一定会让你收获很多!