JVM的分代收集理论是一套符合大多数程序运行实际情况的经验法则。它基于两个主要的分代假说:弱分代假说和强分代假说。弱分代假说认为,绝大多数对象都是朝生夕灭的;而强分代假说则认为,熬过越多次垃圾收集过程的对象就越难以消亡。这两个假说共同构成了分代收集理论的基础。
基于上述假说,当前流行的垃圾收集器都遵循以下设计原则:收集器应该将Java堆划分出不同的区域,然后将回收对象依据其年龄(即对象熬过垃圾收集过程的次数)分配到不同的区域之中存储。这种设计原则旨在优化垃圾收集过程,提高内存管理效率。
在Java堆中,通常被划分为新生代和老年代两个主要区域。新生代又被进一步划分为Eden区和两个Survivor区(通常称为From Survivor和To Survivor,或者简称为S0和S1)。这种划分是为了更好地管理堆内存中的对象,并方便垃圾收集算法的执行。
- 新生代:主要用于存放新建的对象。由于大多数对象在创建后很快就会被回收,因此新生代垃圾收集(也称为Minor GC或Young GC)通常比较频繁。新生代使用的垃圾收集算法主要是复制算法,该算法将堆内存划分为两个相等的区域,将存活的对象从一个区域复制到另一个区域,并回收未被复制的对象。这种算法简单高效,尤其适用于新生代,因为它总是从空区域开始分配内存,不会产生内存碎片。
- 老年代:用于存放经过多次垃圾收集后仍然存活的对象。由于这些对象存活时间较长,因此老年代垃圾收集(也称为Major GC或Old GC)相对不那么频繁。老年代使用的垃圾收集算法主要是标记-整理算法,该算法首先标记所有的存活对象,然后将存活对象向堆的一端移动,并清理掉堆的另一端的空闲内存。这种算法可以解决内存碎片问题,适合老年代内存管理。
在分代收集理论中,还有两个重要的概念:对象的年龄和晋升。对象的年龄是指对象经过垃圾收集的次数。当一个对象在新生代中存活足够长的时间(即经过多次Minor GC后仍然存活),并且其年龄达到某个阈值(默认是15岁,但可以通过JVM参数-XX:MaxTenuringThreshold
来设置)时,它就会被晋升到老年代中。此外,一些较大的对象(需要分配连续的内存空间)也可能直接进入老年代,以避免在新生代中频繁复制和移动。
总的来说,JVM的分代收集理论通过划分不同的内存区域和使用不同的垃圾收集算法来优化内存管理效率。这种设计原则使得JVM能够更好地适应大多数程序的运行实际情况,提高程序的性能和稳定性。
(望各位潘安、各位子健不吝赐教!多多指正!🙏)