分代的垃圾回收策略,是基于这样一个事实:不同的对象的生命周期是不一样的
因此,不同生命周期的对象可以采取不同的收集方式,以便提高回收效率。

在 Java 程序运行的过程中,会产生大量的对象,其中有些对象是与业务信息相关,
比如 Http 请求中的 Session 对象、线程、Socket 连接,这类对象跟业务直接挂钩,
因此生命周期比较长。但是还有一些对象,主要是程序运行过程中生成的临时变量,
这些对象生命周期会比较短,比如:String 对象,由于其不变类的特性,系统会产生大量的这些对象,
有些对象甚至只用一次即可回收。在不进行对象存活时间区分的情况下,每次垃圾回收都是对整个堆空间进行回收,
花费时间相对会长,同时,因为每次回收都需要遍历所有存活对象,
实际上,对于生命周期长的对象而言,这种遍历是没有效果的,因为可能进行了很多次遍历,
但是他们依旧存在。因此,分代垃圾回收采用分治的思想,进行代的划分,
把不同生命周期的对象放在不同代上,不同代上采用最适合它的垃圾回收方式进行回收。
分代收集算法
当前商业虚拟机的垃圾收集都采用“分代收集”算法,这种算法并没有什么新的思想,只是根据对象存活周期的不同将内存
划分为几块。一般是把Java堆分为新生代和老年代,这样就可以根据各个年代的特点采用最适当的收集算法。在新生代中,
每次垃圾收集时都发现有大批对象死去,只有少量存活,那就选用复制算法,只需要付出少量存活对象的复制成本就可以
完成收集。而老年代中因为对象存活率高、没有额外空间对它进行分配担保,就必须使用“标记-清理”或者“标记-整理”算法
来进行回收。
年轻代(Young Generation)的回收算法 (主要以 Copying 为主) 
1. 所有新生成的对象首先都是放在年轻代的。年轻代的目标就是尽可能快速的收集掉那些生命周期短的对象。

19、分代收集下的年轻代和老年代应该采用什么样的垃圾回收算法?

  • 1. 年轻代(Young Generation)的回收算法 (主要以 Copying 为主) 

1. 所有新生成的对象首先都是放在年轻代的。年轻代的目标就是尽可能快速的收集掉那些生命周期短的对象。

2. 新生代内存按照 8:1:1 的比例分为一个 eden 区和两个 survivor(survivor0、 survivor1)区。大部分对象在 Eden 区中生成。回收时先将 Eden 区存活对象复制到一个 survivor0 区,然后清空 eden 区,当这个 survivor0 区也存放满了时,则将 eden 区和 survivor0 区存活对象复制到另一个 survivor1 区,然后清空 eden 区 和这个 survivor0 区,此时 survivor0 区是空的,然后将survivor0 区和 survivor1 区交换,即保持 survivor1 区为空, 如此往复。

3. 当 survivor1 区不足以存放 Eden 区 和 survivor0区 的存活对象时,就将存活对象直接存放到老年代。若是老年代也满了就会触发一次Full GC(Major GC),也就是新生代、老年代都进行回收。

4、新生代发生的 GC 也叫做 Minor GC,MinorGC 发生频率比较高(不一定等 Eden 区满了才触发)。

  • 2. 年老代(Old Generation)的回收算法(主要以 Mark-Compact 为主)

1. 在年轻代中经历了 N 次垃圾回收后仍然存活的对象,就会被放到年老代中。因此,可以认为年老代中存放的都是一些生命周期较长的对象。

2. 内存比新生代也大很多(大概比例是1 : 2),当老年代内存满时触发 Major GC 即 Full GC,Full GC 发生频率比较低,老年代对象存活时间比较长,存活率标记高。