垃圾回收

一、垃圾收集算法

1.标记清除算法

步骤:
(1)标记出所有需要回收的对象,
(2)在标记完成后统一回收所有被标记的对象。
不足:
(1)效率问题,标记和清除两个过程的效率都不高;
(2)空间问题,标记清除之后会产生大量不连续的内存碎片,导致在需要分配较大对象时,无法找到足够的连续内存而不得不提前触发另一个的垃圾收集动作。

2.复制算法

为了解决标记清除算法的效率问题,推出了复制算法(内存碎片化的问题也得到了解决)。
步骤:
(1)它将可用内存按容量划分为大小相等的两块,每次只使用其中的一块。
(2)当这一块内存用完了,就将还存活着的对象复制到另外一块上,然后再把已经使用过的内存空间一次清理掉。
缺点:
可使用的内存变为原来的一半。

  • 主要用来回收新生代。

扩展: Eden区和Survivor区的复制过程。
补充:

Minor GC:新生代的垃圾回收
Major GC:老年代的垃圾回收
Full GC: 整个堆空间的垃圾回收

问题一:为什么需要Survivor区,只有Eden区,行不行?(设置Survivor区的意义在哪里?)

(1)如果没有Survivor,Eden区每进行一次Minor GC,存活的对象就会被送到老年代。老年代很快被填满,触发Major GC。
(2)老年代的内存空间远大于新生代,进行一次Full GC消耗的时间比Minor GC长得多。
缺点:
会影响大型程序的执行和响应速度,更不要说某些连接会因为超时发生连接错误了。
方案:

方案 优点 缺点
增加老年代空间 更多存活对象才能填满老年代。降低Full GC频率 随着老年代空间加大,一旦发生Full GC,执行所需要的时间更长
减少老年代空间 Full GC所需时间减少 老年代很快被存活对象填满,Full GC频率增加

Survivor的存在意义:就是减少被送到老年代的对象,进而减少Full GC的发生,Survivor的预筛选保证,只有经历16次Minor GC还能在新生代中存活的对象,才会被送到老年代。

问题二:为什么需要两个survivor区,一个行不行?

设置两个Survivor区最大的好处就是解决了碎片化。

假设现在只有一个survivor区,我们来模拟一下流程:
刚刚新建的对象在Eden中,一旦Eden满了,触发一次Minor GC,Eden中的存活对象就会被移动到Survivor区。这样继续循环下去,下一次Eden满了的时候,问题来了,此时进行Minor GC,Eden和Survivor各有一些存活对象,如果此时把Eden区的存活对象硬放到Survivor区,很明显这两部分对象所占有的内存是不连续的,也就导致了内存碎片化。

问题三:两个survivor区的执行过程。

建立两块Survivor区,刚刚新建的对象在Eden中,经历一次Minor GC,Eden中的存活对象就会被移动到第一块survivor space S0,Eden被清空;等Eden区再满了,就再触发一次Minor GC,Eden和S0中的存活对象又会被复制送入第二块survivor space S1(这个过程非常重要,因为这种复制算法保证了S1中来自S0和Eden两部分的存活对象占用连续的内存空间,避免了碎片化的发生)。S0和Eden被清空,然后下一轮S0与S1交换角色,如此循环往复。如果对象的复制次数达到16次,该对象就会被送到老年代中。

3.标记整理算法

让所有存活的对象都向一端移动,然后直接清理端边界以外的内存

4.分代收集算法

  • 这种算法根据对象存活周期的不同将内存划分为几块。一般把Java堆分为新生代和老年代,这样就可以根据各个年代的特点采用最适当的收集算法。
  • 在新生代,每次垃圾收集时都发现大批对象死去,只有少量存活,那就选用复制算法,只需要付出少量存活对象的复制成本就可以完成收集。
  • 而老年代中因为对象存活率较高,没有额外的空间对它进行分配担保,就必须使用”标记-清理“和”标记-整理“算法来进行回收

二、垃圾收集器

CMS(Concurrent Mark Sweep) 收集器是一种以获取最短回收停顿时间为目标的收集器。目前很大一部分的Java应用集中在互联网站或者B/S系统的服务端上,这类尤其重视服务的响应速度,希望系统停顿时间最短。CMS收集器就非常符合这类应用的需求。

CMS基于 标记-清除算法实现。整个过程分为4个步骤:

初始标记(CMS initial mark) -stop the world
并发标记(CMS concurrent mark)
重新标记(CMS remark) -stop the world
并发清除(CMS concurrent sweep)

问题:CMS一共会有几次STW?

两次,初始标记和重新标记需要。

(1)CMS并发的代价是预留空间给用户,预留不足的时候触发FUllGC,这时Serail Old会STW.

(2)CMS是标记-清除算法,导致空间碎片,则没有连续空间分配大对象时,FUllGC, 而FUllGC会开始碎片整理, STW.

即2次或多次。

什么是垃圾回收

回收的步骤有2步:

1.查找内存中不再使用的对象

2.释放这些对象占用的内存

posted @ 2021-10-11 09:38  '蜗牛'  阅读(214)  评论(0)    收藏  举报