快捷搜索:  汽车  科技

java虚拟机底层原理大揭秘(深入理解Java虚拟机)

java虚拟机底层原理大揭秘(深入理解Java虚拟机)虽然是这么分类的,实际上呢,非标准参数和非稳定的参数实际的使用中还是用的非常的多的,在后面的文章的介绍中你就会发现。首先想说的是其实这些参数我们并不是陌生的,在平时的开发和使用中经常都会遇到,只是在平时缺少一个比较系统的总结,所以,对这些参数感觉是很陌生的,所以,通过这篇文章的总结,我相信你一定都会对这些参数熟稔于心,做做心中有数。在Java虚拟机的参数中,其实可以把这些参数分为三类,当然,这是针对JDK1.6来说的,如果对于JDK1.8,那么就不是这么分类的了,但是,由于这两个版本很多常用的参数的差别是不大的,所以这篇文章就先介绍JDK1.6的VM参数。主要可以分为以下三类:

原文地址:https://dwz.cn/K6FpQqPD

作者:思海


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

1 JVM参数简介

首先想说的是其实这些参数我们并不是陌生的,在平时的开发和使用中经常都会遇到,只是在平时缺少一个比较系统的总结,所以,对这些参数感觉是很陌生的,所以,通过这篇文章的总结,我相信你一定都会对这些参数熟稔于心,做做心中有数。

在Java虚拟机的参数中,其实可以把这些参数分为三类,当然,这是针对JDK1.6来说的,如果对于JDK1.8,那么就不是这么分类的了,但是,由于这两个版本很多常用的参数的差别是不大的,所以这篇文章就先介绍JDK1.6的VM参数。

主要可以分为以下三类:

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

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


2 标准参数

这一类参数可以说是我们刚刚开始Java是就用的非常多的参数了,比如java -version、java -jar等等,我们在CMD中输入java -help就可以获得Java当前版本的所有标准参数了。

java虚拟机底层原理大揭秘(深入理解Java虚拟机)(1)

如上图就是JDK1.8的所有标准参数了,下面我们将介绍一些我们会用的比较多的参数。

  • -client

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

  • -server

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

  • -CLASSPATH或者-cp

通知JVM类搜索路径。如果指定了-classpath,则JVM就忽略CLASSPATH中指定的路径。各路径之间以分号隔开。如果-classpath和CLASSPATH都没有指定,则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")获得。

1System.out.println(System.getProperty("sun.boot.class.path")); 2System.out.println(System.getProperty("java.ext.dirs")); 3System.out.println(System.getProperty("java.class.path"));


java虚拟机底层原理大揭秘(深入理解Java虚拟机)(2)

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

  • -DpropertyName=value

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

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

如键值对设置为hello=world。

java虚拟机底层原理大揭秘(深入理解Java虚拟机)(3)

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

运行结果就是:

java虚拟机底层原理大揭秘(深入理解Java虚拟机)(4)

  • -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虚拟机底层原理大揭秘(深入理解Java虚拟机)(5)

    从图片中可以看出来,这些非标准的参数其实不多的,下面我们再 讲解一些比较常用的参数。

    • -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。

    1** 2 * @ClassName MethodTest 3 * @Description vm参数设置:-Xms512m -Xmx512m -Xmn128m -XX:NewRatio=4 -XX:SurvivorRatio=8 4 * @Author 欧阳思海 5 * @Date 2019/11/25 20:06 6 * @Version 1.0 7 **/ 8 9public class MethodTest { 10 11 public static void main(String[] args) { 12 List<String> list = new ArrayList<String>(); 13 long i = 0; 14 while (i < 1000000000) { 15 System.out.println(i); 16 list.add(String.valueOf(i ).intern()); 17 } 18 } 19}

    运行之后,用VisualVM查看相关信息是否正确。

    当我们没有设置-XX:NewRatio=4 -XX:SurvivorRatio=8时,使用官方默认的情况如下:

    java虚拟机底层原理大揭秘(深入理解Java虚拟机)(6)

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

    当我们设置了-XX:NewRatio=4 -XX:SurvivorRatio=8时,情况如下:

    java虚拟机底层原理大揭秘(深入理解Java虚拟机)(7)

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

    java虚拟机底层原理大揭秘(深入理解Java虚拟机)(8)

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

    • -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及以下可以使用。


    • 性能参数

    java虚拟机底层原理大揭秘(深入理解Java虚拟机)(9)

    • 行为参数

    java虚拟机底层原理大揭秘(深入理解Java虚拟机)(10)


    java虚拟机底层原理大揭秘(深入理解Java虚拟机)(11)

    前面6个参数都是关于垃圾收集器的行为参数,也是经常会用到的参数。

    • 调试参数

    java虚拟机底层原理大揭秘(深入理解Java虚拟机)(12)


    java虚拟机底层原理大揭秘(深入理解Java虚拟机)(13)

    5 JDK8的VM参数

    由于考虑到现在JDK8用的非常的广泛,所以,接下来总结一些JDK8会使用到的参数。

    查看这篇JDK8的参数文章你会发现,标准参数和非标准参数JDK8的差别并不是很大,如果有其他的参数需要使用,可以查看上面这篇文章。

    我目前是在职Java开发,如果你现在正在了解Java技术,想要学好Java,渴望成为一名Java开发工程师,在入门学习Java的过程当中缺乏基础的入门视频教程,你可以关注并私信我:01。我这里有一套最新的Java基础JavaSE的精讲视频教程,这套视频教程是我在年初的时候,根据市场技术栈需求录制的,非常的系统完整

    猜您喜欢: