深刻理解Java虚拟机-经常使用vm参数分析

Java虚拟机深刻理解系列所有文章更新中...html

话很少说,今天就分析一下一些经常使用的Java虚拟机的参数设置,以及如何更好的使用!java

1 JVM参数简介

首先想说的是其实这些参数咱们并非陌生的,在平时的开发和使用中常常都会遇到,只是在平时缺乏一个比较系统的总结,因此,对这些参数感受是很陌生的,因此,经过这篇文章的总结,我相信你必定都会对这些参数熟稔于心,作作心中有数。算法

在Java虚拟机的参数中,其实能够把这些参数分为三类,固然,这是针对JDK1.6来讲的,若是对于JDK1.8,那么就不是这么分类的了,可是,因为这两个版本不少经常使用的参数的差异是不大的,因此这篇文章就先介绍JDK1.6的VM参数。windows

主要能够分为如下三类:服务器

  • 标准参数(-),全部的JVM实现都必须实现这些参数的功能,并且向后兼容。
  • 非标准参数(-X),默认JVM实现这些参数的功能,可是并不保证全部JVM实现都知足,且不保证向后兼容。
  • 非Stable参数(-XX),此类参数各个JVM实现会有所不一样,未来可能会随时取消,须要慎重使用。

虽然是这么分类的,实际上呢,非标准参数和非稳定的参数实际的使用中仍是用的很是的多的,在后面的文章的介绍中你就会发现。微信

2 标准参数

这一类参数能够说是咱们刚刚开始Java是就用的很是多的参数了,好比java -versionjava -jar等等,咱们在CMD中输入java -help就能够得到Java当前版本的全部标准参数了。markdown

深刻理解Java虚拟机-经常使用vm参数分析

如上图就是JDK1.8的全部标准参数了,下面咱们将介绍一些咱们会用的比较多的参数。网络

  • -client

以client模式启动JVM,这种方式启动速度快,但运行时性能和内存管理效率不高,适合客户端程序或者开发调试。并发

  • -server

以server模式启动JVM,与client状况刚好相反。适合生产环境,适用于服务器。64位的JVM自动以server模式启动。oracle

  • -classpath或者-cp

通知JVM类搜索路径。若是指定了-classpath,则JVM就忽略CLASSPATH中指定的路径。各路径之间以分号隔开。若是-classpathCLASSPATH都没有指定,则JVM从当前路径寻找class。

JVM搜索路径的顺序:

1.先搜索JVM自带的jar或zip包。

Bootstrap,搜索路径能够用System.getProperty("sun.boot.class.path")得到;

2.搜索JRE_HOME/lib/ext下的jar包。

Extension,搜索路径能够用System.getProperty("java.ext.dirs")得到;

3.搜索用户自定义目录,顺序为:当前目录(.),CLASSPATH,-cp。

搜索路径用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"));

深刻理解Java虚拟机-经常使用vm参数分析

如上就是我电脑的JVM的路径。

  • -DpropertyName=value

定义系统的全局属性值,如配置文件地址等,若是value有空格,则须要使用双引号。

另外用System.getProperty("hello")能够得到这些定义的属性值,在代码中也能够用System.setProperty("hello","world")的形式来定义属性。

如键值对设置为hello=world。
深刻理解Java虚拟机-经常使用vm参数分析

System.out.println(System.getProperty("hello"));

运行结果就是:
深刻理解Java虚拟机-经常使用vm参数分析

  • -verbose

查询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形成的应用暂停的时间。

3 非标准参数

非标注的参数主要是关于Java内存区域的设置参数,因此在看这些参数以前,应该先查看Java内存区域的基础知识,能够查看这篇文章:深刻理解Java虚拟机-Java内存区域透彻分析

非标准参数实在标准参数的基础上的一些扩充参数,能够输入java -X,得到当前JVM支持的非标准参数。

深刻理解Java虚拟机-经常使用vm参数分析

从图片中能够看出来,这些非标准的参数其实很少的,下面咱们再 讲解一些比较经常使用的参数。

  • -Xmn

新生代内存大小的最大值,包括E区和两个S区的总和。设置方法:-Xmn512m、-Xmn2g

  • -Xms

初始堆的大小,也是堆大小的最小值,默认值是总共的物理内存/64(且小于1G)。默认状况下,当堆中可用内存小于40%,堆内存会开始增长,一直增长到-Xmx的大小。

  • -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时,使用官方默认的状况以下:

深刻理解Java虚拟机-经常使用vm参数分析

上图能够看出,新生代(Eden Space + Survivor 0 + Survivor 1):老年代(Old Gen)≈ 1:2

当咱们设置了-XX:NewRatio=4 -XX:SurvivorRatio=8时,状况以下:

深刻理解Java虚拟机-经常使用vm参数分析

变成了新生代(Eden Space + Survivor 0 + Survivor 1):老年代(Old Gen)≈ 1:4,Eden Space:Survivor 0: Survivor 1 = 8:1:1。

深刻理解Java虚拟机-经常使用vm参数分析

从上图可知,堆的信息是正确的。

  • -Xss

设置每一个线程的栈内存,默认1M,通常来讲是不须要改的。

  • -Xprof

跟踪正运行的程序,并将跟踪数据在标准输出输出;适合于开发环境调试。

  • -Xnoclassgc

禁用类垃圾收集,关闭针对class的gc功能;由于其阻止内存回收,因此可能会致使OutOfMemoryError错误,慎用。

  • -Xincgc

开启增量gc(默认为关闭);这有助于减小长时间GC时应用程序出现的停顿;但因为可能和应用程序并发执行,因此会下降CPU对应用的处理能力。

  • -Xloggc:file

-verbose:gc功能相似,只是将每次GC事件的相关状况记录到一个文件中,文件的位置最好在本地,以免网络的潜在问题。
若与verbose命令同时出如今命令行中,则以-Xloggc为准。

  • -Xint

在解释模式(interpreted mode)下,-Xint标记会强制JVM执行全部的字节码,这会下降运行速度,一般低10倍或更多。

  • -Xcomp

-Xcomp参数与它(-Xint)正好相反,JVM在第一次使用时会把全部的字节码编译成本地代码,从而带来最大程度的优化。

然而,不少应用在使用-Xcomp也会有一些性能损失,固然这比使用-Xint损失的少,缘由是-xcomp没有让JVM启用JIT编译器的所有功能。JIT编译器能够对是否须要编译作判断,若是全部代码都进行编译的话,对于一些只执行一次的代码就没有意义了。

  • -Xmixed

-Xmixed是混合模式,这是JVM默认的模式,也是推荐使用的模式。将解释模式与编译模式进行混合使用,由JVM本身决定。

4 非Stable参数

这类参数你一看官网觉得不能使用呢,官网给你的建议就是这些参数不稳定,慎用,其实这主要的缘由仍是由于每一个公司的实现都是不同的,因此就是致使不稳定。可是呢,在实际的使用中倒是很是的多的,并且这部分的参数很重要。

这些参数大体能够分为三类:

  • 性能参数(Performance Options):用于JVM的性能调优和内存分配控制,如初始化内存大小的设置;
  • 行为参数(Behavioral Options):用于改变JVM的基础行为,如GC的方式和算法的选择;
  • 调试参数(Debugging Options):用于监控、打印、输出等jvm参数,用于显示jvm更加详细的信息;

下面仍是先罗列一些比较经常使用的参数,其实,这些文章不少了,这里主要仍是作一个总结,之后本身看文章的时候比较方便,若是有同行看到了文章,你能够参考参考,仍是颇有帮助的。

另外,选取其中的一些参数作一些例子来解释,这样也可以更加的形象。

注意:如下参数都是JDK1.7及如下可使用。

  • 性能参数
参数及其默认值 描述
-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:-TraceCla***esolution 跟踪常量池
-XX:-TraceClassUnloading 跟踪类的卸载信息
-XX:-TraceLoaderConstraints 跟踪类加载器约束的相关信息

5 JDK8的VM参数

因为考虑到如今JDK8用的很是的普遍,因此,接下来总结一些JDK8会使用到的参数。

查看这篇JDK8的参数文章你会发现,标准参数和非标准参数JDK8的差异并非很大,若是有其余的参数须要使用,能够查看上面这篇文章。

一、原创不易,老铁,文章须要你的 点赞 让更多的人看到,但愿可以帮助到你们!

二、文章有不当之处,欢迎指正,若是喜欢微信阅读,你也能够关注个人微信公众号好好学java,公众号已有 6W 粉丝,回复:1024,获取公众号的大礼包,公众号长期发布 Java 优质系列文章,关注咱们必定会让你收获不少!

深刻理解Java虚拟机-经常使用vm参数分析

相关文章
相关标签/搜索