分代回收
上篇文章介绍了几种垃圾回收的算法,但这些算法当中并没有一个是完美的,可以代替其他所有算法,他们各自有各自的优势。因此JVM需要根据垃圾回收对象的特性,选择合适的回收算法。
JVM中大部分对象的生命周期非常短,朝生夕灭;还有一些对象,他们的生命周期很长,有的甚至长生不老、寿与JVM齐。于是就有了分代的概念。
分代
- 新生代(
Young Generation
)
+Eden
+Survivor From
+Survivor To - 老年代(
Old Generation
) - 永久代(
Permanent Generation
)
如上面所描述的,JVM将内存分成不同的区域。针对新生代和老年代分别才用了如下两种回收方式:
- Minor Collection(
对新生代进行垃圾回收,Hot Spot采用的复制算法
) - Full Collection(
对所有分代进行垃圾回收,也叫Major Collection,Hot Spot采用的是标记-压缩算法
)
回收过程
一般情况下,新产生的对象,会被分配到新生代的Eden( 大对象会直接进入老年代
)。当Eden没有足够空间的时候,就会进行Minor Collection。在Minor Collection执行的时候,会将存活下来的对象复制到Survivor区。如果Survivor也没有足够空间的时候,将会有一部分对象被迁移到老年代,这个迁移的过程称作晋升(Promotion
)。
随着Minor Collection的不断进行,老年代中的对象也会越来越多,当老年代内存紧张的时候,就会触发Full Collection。通常Full Collection会对整个堆进行回收(CMS收集器除外,它不对新生代进行回收
)。相比新生代,老年代的回收频率非常低,因为它每一次回收耗时很长。
JVM会通过以下两个参数判断对象是否晋升到老年代:
- 年龄,经历Minor Collection的次数代表对象的年龄
- 大小,即占用内存空间的大小
一些JVM的参数
选项 | 默认值 | 作用 |
-XX:InitialSurvivorRatio | 8 | 新生代Eden/Survivor空间的初始比例 |
-XX:SurvivorRatio | 8 | 新生代Eden/Survivor空间的比例 |
-XX:MinSurvivorRatio | 3 | 新生代Eden/Survivor空间的最小比例 |
-XX:TargetSurvivorRatio | 50 | 垃圾回收后期望的Survivor区空间使用率 |
-XX:InitialTenuingThreshold | 7 | 晋升到老年代的对象年龄初始阀值 |
-XX:MaxTenuringThreshold | 15 | 晋升到老年代的年龄阀值 |
-XX:PretenureSizeThreshold | 0 | 直接晋升老年代的对象大小 |
-XX:UsePSAdaptiveSurvivorSizePolicy | true | 自适应调整Survivor区域大小策略 |
关于JVM调优
我们经常谈到JVM调优,JVM也为我们提供了非常多的自定义参数(上表只是跟今天内容比较紧密的一些参数
),供我们配置。现实中,我们的软硬件环境各不相同,实际的需求场景也千差万别,所以我们很难(说很难是因为严谨,其实就没有
)写出一套放诸四海皆准的配置来。具体的调优方案,还得根据具体的应用,以及工程师的个人经验和能力来制定。目前小弟能力有限,没有什么调优的经验,所以就不过多的说啦,待日后时机成熟了,一定再跟大家分享。