借鉴:
https://blog.csdn.net/u010796790/article/details/52213708
关于Minor GC 以及新生代与年老代的解释请看上述博文,此处添加一些自己的理解:
关于Java中年老代与新生代的区别,是一种时序表现,明白JVM设置其原理即可:
上图的机制是一种新生代垃圾回收策略造成的,该策略为复制-清除算法,该算法原理是将新生代的堆内存划分为两个相等大小的内存区域,新生代只分配其中一块内存区域,当要进行垃圾回收时,将该块存活对象复制到另外一块内存且按顺序连续的进行存储,从而可以改进标记-清除垃圾回收策略产生大量碎片内存的缺点,但是一般商用的虚拟机并不需要按照1:1的内存划分区域,因为这意味着有一半的内存在一定时间内是不可用的,而新生代中大量的对象都是“朝生夕死”,故在垃圾回收时存活的对象占极少,所以可以采用将内存分为一块较大的Eden块和2块较小的内存块Survivor空间,每次使用Eden区和1个Survivor区,而另一个Survivor区用做复制。默认的Eden区与Survivor区的大小比为8:1:1。
回到上述图示,第一次Minor GC,会将Eden中存活的对象复制至survivor space 1并将这些对象的年龄设置为1,当进行第二次Minor GC时,则将Eden区存活对象复制至Survivor2,并将他们的年龄设置为1,而Survivor 1中的继续存活的对象则复制进入survivor2,并判断其年龄是否小于阈值,若小于,则复制,否则进入年老代的内存区域(对象晋升老年代的年龄阈值,可以通过参数
-XX:MaxTenuringThreshold
(阈值)来设置),当第三次Minor GC发生时,又将survivor2 和Eden区的对象复制进入survivor1。如此往复,所以设置两个survivor块是为了实现循环往复的复制操作,并且又设置对象存活的年龄,是一种缓冲的机制,其中Eden和一块survivor是变化的内存块,另外一块survivor也是动态的缓冲区,且能不断的整理碎片。
为什么要用两个survivor区,因为当从Eden复制到survivor1,又继续要进行复制时,survivor1中也存在需要丢弃的对象,这时又产生了碎片,所有采用这种双survivor块的方式可以不断无碎片式复制并且保证年龄的正确性