标签:space 一半 两种 hang 选择 综合 产生 这一 java
参考:
https://blog.csdn.net/clover_lily/article/details/80160726
https://blog.csdn.net/ChenRui_yz/article/details/88392945
想要回收垃圾,必须得先知道,哪些对象可以被认定为垃圾。关于垃圾确定方式,主要有两种,分别是引用计数法与可访问性分析法,其原理分别如下:
在 Java 中,引用与对象相关联,如果要操作对象,则必须使用引用。因此,可以通过引用计数来确定对象是否可以回收。实现原则是,如果一个对象被引用一次,计数器 +1,反之亦然。当计数器为 0 时,该对象不被引用,则该对象被视为垃圾,并且可以被 GC 回收利用。
为了解决引用计数法的循环引用问题,Java 采用了可达性分析的方法。其实现原理是,将一系列"GCroot"对象作为搜索起点。如果在"GCroot"和一个对象之间没有可达的路径,则该对象被认为是不可访问的。
要注意的是,不可达对象不等价于可回收对象,不可达对象变为可回收对象至少要经过两次标记过程。两次标记后仍然是可回收对象,则将面临回收。
了解了垃圾的确定方法后,我们将继续了解垃圾是怎么被回收的,即垃圾回收算法。在Java中主要有四中垃圾回收算法,分别是标记清除算法、复制算法、标记整理算法 和 分代收集算法。
“标记-清除”算法是最基础的算法,分为标记和清除两个阶段:首先标记出所有需要回收的对象,在标记完成后统一回收掉所有被标记的对象。
由标记清除算法的实现我们可以看出,其主要存在两个缺点:
为了解决标记清除算法内存碎片化严重的缺陷,提出了复制算法。复制算法主要思想是,按内存容量将内存划分为大小相等的两块区域。每次只使用其中一块,当这一块内存满后将其中存活的对象复制到另一块上去,然后把该内存中的垃圾对象清理掉,其实现过程如图:
复制算法虽然实现简单,内存效率高,不易产生碎片,但是最大的问题是可用内存被压缩到了原本的一半。且存活对象增多的话,Copying 算法的效率会大大降低。
结合了以上两个算法,为了避免缺陷而提出。标记阶段和标记清理算法相同,标记后不是清理对象,而是将存活对象移向内存的一端。然后清除端边界外的对象。如图:
在结合以上三种算法的综合分析及 JVM 内存对象生命周期的特点,诞生了一种新的垃圾回收算法——分代收集算法。其核心思想是根据对象存活的不同生命周期将内存划分为不同的域,一般情况下将 GC 堆划分为老年代(Tenured/Old Generation)和新生代(Young Generation)。老年代的特点是每次垃圾回收时只有少量对象需要被回收,新生代的特点是每次垃圾回收时都有大量垃圾需要被回收,因此可以根据不同区域选择不同的算法。
因为新生代中每次垃圾回收都要回收大部分对象,即要复制的操作比较少,但通常并不是按照 1:1 来划分新生代。一般将新生代划分为一块较大的 Eden 空间和两个较小的 Survivor 空间(From Space/S0, To Space/S1),每次使用 Eden 空间和其中的一块 Survivor 空间,当进行回收时,将该两块空间中还存活的对象复制到另一块 Survivor 空间中。
而老年代因为每次只回收少量对象,因而采用标记整理算法。
标签:space 一半 两种 hang 选择 综合 产生 这一 java
原文地址:https://www.cnblogs.com/personsiglewine/p/12892841.html