【JVM】GCRoots和JVM的参数配置
如何理解GCRoots?
为了解决引用计数法的循环引用问题,Java使用了可达性分析的方法。GC Roots是一组活跃的引用,通过一系列名为GC Roots的对象作为起始点,沿着该对象向下搜索,如果一个对象到GC Roots没有任何引用链相连,则说明对象不可用。
哪些可以作为GC Roots的对象?
- 虚拟机栈(栈帧中的本地变量表)中引用的对象
- 方法区的类静态属性引用的对象
- 方法区中常量引用的对象
- 本地方法栈中JNI(Java本地接口)(native方法)中引用的对象
JVM的参数类型
参数的三大类型
标配参数:java -version、java -help
X参数(了解):
- -Xint:解释执行。在解释模式(interpreted mode)下,
-Xint
标记会强制JVM执行所有的字节码,当然这会降低运行速度,通常低10倍或更多。 - -Xcomp:第一次使用就编译成本地代码,与(-Xint)正好相反,JVM在第一次使用时会把所有的字节码编译成本地代码,从而带来最大程度的优化。很多应用在使用-Xcomp也会有一些性能损失,当然这比使用-Xint损失的少,原因是-xcomp没有让JVM启用JIT编译器的全部功能。JIT编译器可以对是否需要编译做判断,如果所有代码都进行编译的话,对于一些只执行一次的代码就没有意义。
- -Xmixed:混合模式,将解释模式与编译模式进行混合使用,由jvm自己决定,这是jvm默认的模式,也是推荐使用的模式。
XX参数:
- Boolean类型:【-XX:+/- 某个参数值】+表示开启,-表示关闭
- Key-Value类型:【-XX:key=value】例如:-XX:MetaspaceSize=128m、-XX:MaxTenuringThreshold=15
- jinfo类型:查看当前运行程序的配置
如何查询参数配置?
查看运行中的Java程序某个JVM参数值是否开启及具体值:
- jps:查看后来进程
- jinfo:查看当前运行程序的配置。【jinfo -flag + 需要查询的参数信息 + 进程号】/【jinfo -flags】
如上图所示,【jps -l】 获得正在运行的java进程的进程号,【jinfo -flag + 需要查询的参数信息 + 进程号】,得到-XX参数的配置结果,参数名称前面是 – 号,表示没有开启。
对于Key-Value类型的XX参数,如果没有显式的配置,则查询到的结果则是JVM的默认配置值。
Command line是手动配置项,Non -default VM flags是JVM默认没有修改过的项。
-Xms和-Xmx是属于那一类呢?
-Xms和-Xmx实际上是-XX类的参数,-Xms和-Xmx其实是别名。
-Xms等价于 -XX: InitialHeapSize【初始值是物理内存的1/64】
-Xmx等价于 -XX: MaxHeapSize【初始值是物理内存的1/4】
查询参数的其他命令
java -XX:+PrintFlagsInitial :查看JVM的参数的初始配置。
java -XX:+PrintFlagsFinal -version:查看修改过的参数配置。【=没有修改过,:=修改过】
java -XX:+PrintFlagsFinal -XX:MetaspaceSize=256m 运行的类名 :运行java命令的同时打印参数
java -XX:+PrintCommandLineFlags -version:打印HotSpotVM 采用的自动优化参数
JVM常用基本配置参数
- -Xms:初始大小内存,物理内存的1/64,等价于-XX:IntialHeapSize
- -Xmx:最大分配内存,物理内存的1/4,等价于-XX:MaxHeapSize
- -Xss:设置单个线程栈的大小,一般默认为512KB~1024KB,等价于-XX:ThreadStackSize
- -Xmn:设置年轻代的大小,默认堆内存的1/3
- -XX:MetaspaceSize:设置元空间大小。元空间的本质和永久代类似,都是对JVM规范中的方法区的实现,二者区别在于元空间不再虚拟机中,而是在本地内存中。所以默认情况下,元空间的大小仅受本地内存限制。一般只取出20多MB,可以自已调大一些。
- -XX:+PrintGCDetails:打印GC日志
- -XX:SurvivorRatio:设置年轻代eden/s0/s1的空间比例。默认值是8,也就是8:1:1,如果是4,就是4:1:1。
- -XX:NewRatio:设置年轻代和老年代在堆中的占比。默认值是2,也就是新生代1老年代2,如果是4,就是新生代1老年代4,老年代占堆的4/5
- -XX:MaxTenuringThreshold:设置进入老年代的最大年龄(在年轻代复制交换的次数),默认15次。只能设置为0~15之间。
每个Java线程都有两个堆栈:一个用于Java代码,一个用于本机代码。主线程的最大本机堆栈大小由本机应用程序启动器(例如,shell或操作系统)确定。对于后续线程,最大本机堆栈大小由该-Xss选项设置,尽管这可由基础操作系统忽略。-Xss的默认值为0,表示该值实际上是由本机环境设置的。