JVM学习(三)垃圾回收

JVM学习(三)垃圾回收

前言

侵删,记录自己学习时看到的一些片段


GC(垃圾回收)

通过一系列措施释放垃圾占用的内存空间,防止内存泄漏


垃圾判断算法

引用计数算法

这是一种实现简单,判定效率高的算法。

实现方法:给对象添加一个引用计数器,每当有一个地方引用它时,计数器+1,当引用失效时,计数器-1。当对象的计数器为0,此时判定此对象不可能再被使用。

算法缺陷

无法解决循环引用问题。当对象a和对象b相互引用对方,并且两对象再无任何引用时,引用计数算法无法通知GC系统回收对象a和对象b。


可达性分析

为了解决引用计数法的循环引用问题,Java使用了可达性分析方法。

算法思路:通过一系列的称为“GC Roots”的对象作为起始点,从这些节点向下搜索,搜索所走过的路径称为引用链,当一个对象到GC Roots没有任何引用链相连时,则证明此对象不可用

JVM学习(三)垃圾回收

不可达对象不等价于可回收对象,不可达对象变为可回收对象至少要经过两次标记过程。两次标记后仍然是可回收对象,则面临回收


垃圾回收算法

标记清除算法

最基础的垃圾回收算法。分为两个阶段,标记和清除

标记阶段:标记出所有需要回收的对象

清除阶段:回收被标记的对象所占用的空间

JVM学习(三)垃圾回收

算法缺陷

内存碎片化严重,容易造成后续实例化大对象时无法找到可利用空间


复制算法

为了解决标记清除算法内存碎片化问题而被提出的算法。按内存容量划分为等大小的两块每次只使用其中一块,当一块内存满后将仍然存活的对象复制到另一块上,后将已使用的内存清除

JVM学习(三)垃圾回收

算法缺陷

在空间上造成浪费,可用内存只有总内存的一半。当存活对象增多之后,算法效率会大大降低


标记整理算法

结合标记清除算法和复制算法而提出。标记阶段和标记清除算法相同,不同在于标记后不是回收对象所占用的内存,而是将存活的对象移向内存的一端,然后清除端边界外的对象

JVM学习(三)垃圾回收

算法缺陷

虽说解决了内存碎片问题,同时也规避复制算法只能利用一半内存的弊端,但标记整理算法内存变动更加频繁,需要整理所有存活对象的引用地址,效率比复制算法差很多


分代收集算法

分代收集算法目前大部分JVM所采用的方法,核心思想是根据对象存活的不同生命周期将内存划分为不同区域,一般划分为新生代老年代

对新生代而言,大部分JVM的GC对新生代都采用复制算法但并不会按照原复制算法1:1划分空间,而是将新生代空间划分为eden区(较大),from survivor区(较小)和to survivor区(较小)每次仅使用eden区和其中一块survivor区回收时,将该两块空间存活对象复制到另一块survivor区。

对老年代而言,由于老年代每次只回收少量对象,对象存活率高,因此采用标记整理算法标记清除算法

新生代与老年代

  • 当新生代发生了一次GC,eden区和from survivor区往to survivor区复制对象内存不足时,则会将这个对象存储到老年代。
  • 当一个对象实例化所需内存过大时,会直接移入老年代存储。
  • 当对象在survivor区存活一次后,年龄+1。默认情况下年龄达到15会被移到老年代中。

参考资料

JVM垃圾回收机制

《Java虚拟机(第二版)》

《JAVA核心面试知识整理.pdf》