GC(垃圾回收)详解


基础:

1、引用计数法:无法解决循环引用的问题,不被java采纳

2、根搜索算法:从根结点扫描,只要这个对象在引用链中,那就是可触及的。

3、GC分为年轻代GC和老年代GC

4、新生代、老年代、元数据区


现代虚拟机中的垃圾搜索算法:

  • 标记清除
  • 复制算法(新生代)
  • 标记压缩(老年代)

这三种算法都扩充了根搜索算法。



1、标记清除算法

概念: 标记清除算法是现代垃圾回收算法的思想基础。标记清除将垃圾回收分为两个阶段:标记阶段和清除阶段。

  • 标记阶段:首先通过根结点,标记所有从根节点开始的可达对象。因此未被标记的对象就是未被引用的垃圾对象。
  • 清除阶段:在清除阶段,清除所有未被标记的对象。

GC(垃圾回收)详解

实践: 在堆中的有效空间被耗尽时,就会停止整个程序(stop the world),然后进行标记清除。

  • 标记:遍历所有的GC Roots,然后将所有的GC Roots可达的对象标记为存活的对象。
  • 清除:清除的过程将遍历堆中的所有的对象,将没有标记的对象全部清除。

标记清除算法的缺点:

  • 等待时间长(递归与全堆对象遍历),导致stop the world的时间很长。
  • 不能解决内存碎片的问题



2、复制算法

概念: 将原有的内存空间分为两块,每次只使用其中的一块。在垃圾回收的时候,将存活对象复制到未使用的内存块中,之后,清除正在使用的内存块中的所有对象,交换两个内存的角色,完成垃圾回收。

GC(垃圾回收)详解

不适用于存活对象较多的场合,如老年代(复制算法适合做新生代的GC),和标记清除算法相比解决了内存碎片的问题。

复制算法的缺点:

  • 空间浪费,复制算法每次都只对半区内存进行回收,复制算法要想使用,最起码对象的存活率要非常低才行,而且重要的是要克服50%的内存浪费。
  • 如果要应对所有对象都100%存活的极端情况,就必须要有很大的额外空间担保,所以这种算法不适用很多的对象存活率都很高的时候(老年代)。

新生代:Eden区、Surivor区(From区和to区)

GC(垃圾回收)详解

现代商业虚拟机都采用这种收集算法来回收新生代,新生代中的对象98%都是“朝生夕死”的,所以并不需要1:1的比例来划分内存空间,而是将内存划分为一块比较大的Eden区和两块比较小的Surivor空间(From区和to区),每次使用Eden和其中一块Surivor。当回收的时候,先根据分代收集算法将年龄大的对象放入老年代,然后将Eden和Surivor中还存活着的对象一次性的复制到另一块Surivor空间上,最后清理掉Eden和刚才用过的Surivor空间。HotSpot虚拟机默认Eden和Surivor的大小比例是8:1,也就是说,每次新生代中可用内存空间为整个新生代容量的90%(80%+10%),只有10%的空间会被浪费。

当然,我们没法保证每次回收都只有不超过10%的对象存活,当Surivor空间不够用时,需要依赖于老年代进行分配,所以大对象直接进入老年代。如下图所示:

GC(垃圾回收)详解



3、标记-整理算法

概念: 在标记-清除算法的基础上做了一些优化,和标记-清除算法一样,首先需要从根结点开始,对所有可达对象做一次标记。但是之后,将所有存活的对象压缩到内存一端,然后清理边界外所有的空间。

GC(垃圾回收)详解

实践:

  • 标记:遍历所有的GC Roots,然后将所有的GC Roots可达的对象标记为存活的对象。
  • 整理:移动所有存活的对象,按照内存地址依次排列,然后将末端内存地址以后的内存全部回收。

标记-压缩算法不仅可以弥补标记-清除算法的内存碎片问题,也消除了复制算法中,额外内存空间的问题。

标记-整理算法的缺点:

效率很低,不仅要标记所有存活的对象,还要整理所有存活对象的引用地址。效率是上面两个算法中最低的。



4、标记-清除算法、复制算法、标记整理算法的总结

效率: 复制算法>标记-整理算法>标记-清除算法

内存整齐度:复制算法=标记/整理算法>标记/清除算法。

内存利用率: 标记/整理算法=标记/清除算法>复制算法。



5、分代收集算法

概念: 根据对象的存活周期的不同,将堆内存划分为老年代和新生代。存活时间短的对象未新生代,寻获时间长的为老年代。

实践:

少量对象存活,适合复制算法,在新生代中,每次GC都会有大量对象死亡,那么就选择用复制算法。

大量对象存活,适合标记-清理\标记-压缩算法,在老年代中,对象存活率高,就用标记-清理\标记-压缩算法进行GC。



6、Stop-The_World

java中一种全局暂停的现象,全局停顿,所有代码停止,native代码可以执行,但不能和JVM交互。多半情况下时由于GC引起的。

GC(垃圾回收)详解

危害:

  • 长时间服务停止,没有响应(将用户正常工作的线程全部暂停掉)
  • 比如上面的这主机和备机:现在是主机在工作,此时如果主机正在GC造成长时间停顿,那么备机就会监测到主机没有工作,于是备机开始工作了;但是主机不工作只是暂时的,当GC结束之后,主机又开始工作了,那么这样的话,主机和备机就同时工作了。主机和备机同时工作其实是非常危险的,很有可能会导致应用程序不一致、不能提供正常的服务等,进而影响生产环境。



7、GC时为什么会有全局停顿?

1、避免无法彻底清理干净

2、GC的工作必须在一个能确保一致性的快照中进行