这是我参与8月更文挑战的第26天,活动详情查看:8月更文挑战
1. 前言
本文主要列出了 JVM 常用的配置参数,包括了堆内存的配置以及垃圾收集器的配置等等;对于 JVM 的参数来说,实在是太多了,我们记住几个常用的即可,其他的只是做一个了解,我们要用到的时候能想起来并查找到就行了。
所以本文只对一些开发中常用到的一些参数做一个解析
2. 堆内存相关参数
默认下, 新生代 ( Young ) = **1/3 的堆空间大小,**老年代 ( Old ) = 2/3 的堆空间大小; 新生代 ( Young ) 被细分为 Eden 和 两个 Survivor 区域,这两个 Survivor 区域分别被命名为 from 和 to,以示区分;默认的,Edem : from : to = 8 : 1 : 1
指定堆内存的参数:
-Xms:设定堆的起始内存,默认情况下,初始堆内存大小为:电脑内存大小/64-Xmx:设定堆的最大内存,默认情况下,最大堆内存大小为:电脑内存大小/4
示例,将堆空间的最小值设为 2G,最大值设为 5G,当然单位也是可以替换的,可以换成 m(MB),k(KB);通常我们会将这两个参数的大小设置为一样大,目的是为了提高性能
-Xms2G -Xmx5G
2.1 设置新生代的内存
设置新生代内存大小的方式有两种:
通过 -XX:NewSize 和 -XX:MaxNewSize
-XX:NewSize:配置新生代的最小内存-XX:MaxNewSize:配置新生代的最大内存
当最小内存和最大内存我们设置为一样时,也可以通过 -Xmn 参数实现
-Xmn设置新生代大小
示例:
--XX:NesSize1G --XX:MaxNesSize1G
或
-Xmn1G
小知识:GC 调优有一条重要的经验,那就是尽量将新对象预留在新生代,由于 Full GC 的成本远高于 Minor GC,因此尽可能将对象分配在新生代是明智的做法,实际项目中根据 GC 日志分析新生代空间大小分配是否合理,适当通过“-Xmn”命令调节新生代大小,最大限度降低新对象直接进入老年代的情况。
2.2 设置永久代/元空间的大小
在 JDK1.8 之后,永久代改为了元空间,如果我们不显示的指定元空间的大小,那么随着类的创建它有可能耗尽所有的可用内存
1)设置永久代大小
-XX:PermSize:设置永久代的初始化大小-XX:MaxPermSize:设置永久代的最大大小
2)设置元空间的大小
-XX:MetaspaceSize:设置元空间的初始化大小-XX:MaxMetaspaceSize:设置元空间的最大大小
需要注意的是:
- 对于一个 64 位的服务器端 JVM 来说,其默认的
-XX:MetaspaceSize的值为20.75MB,这就是初始的高水位线,一旦触及这个水位线,Full GC 将会被触发并卸载没用的类(即这些类对应的类加载器不再存活),然后这个高水位线将会重置,新的高水位线的值取决于 GC 后释放了多少元空间。如果释放的空间不足,那么在不超过MaxMetaspaceSize时,适当提高该值。如果释放空间过多,则适当降低该值 - 如果初始化的高水位线设置过低,上述高水位线调整情况会发生很多次,通过垃圾回收的日志可观察到 Full GC 多次调用。为了避免频繁 GC,可以将
-XX:MetaspaceSize设置为一个相对较高的值。
2.3 堆空间的其他参数
-
-XX:NewRatio:设置新生代与老年代比值,-XX:NewRatio=4 表示新生代与老年代所占比例为1:4 ,新生代占比整个堆的五分之一。如果设置了-Xmn的情况下,该参数是不需要在设置的。 -
-XX:MaxTenuringThreshold:新生代中对象存活次数,默认15;若对象在eden区,经历一次MinorGC后还活着,则被移动到Survior区,年龄加1;以后,对象每次经历MinorGC,年龄都加1;达到阀值,则移入老年代。 -
-XX:SurvivorRatio:Eden区与Subrvivor区大小的比值,如果设置为8,两个Subrvivor区与一个Eden区的比值为2:8,一个Survivor区占整个新生代的十分之一。
3. 总结
在一般的公司项目中,由于自动化流水线的存在,并且服务器资源有限,一般都设置了一个默认的启动参数,我们在开发的时候就应该考虑到是否会把这些内存耗尽,又是否会出现频繁 GC 的情况
毕竟,进行 JVM 调优,是最后的手段