堆_JVM 垃圾收集机制的讲解

2023-11-14 23:17:03 浏览数 (1)

堆_JVM 垃圾收集机制(新生代)

其实 JVM 的垃圾回收机制 前身今世有很多的。目前只从 Copying 算法下手进行解析。

大概过程可以作如下解释:

将内存平均分为 A、B 两块,新生对象被分配到 A 块中未使用的内存中,当 A 中的内存块用完了时,把 A 中存活的对象复制到 B 块中。然后清理 A 中所有的对象。新生对象之后会被分配在 B 块的未使用内存当中,当 B 块的内存用完了, 把 B 块的存活内存复制到 A 中,然后清理 B 块的所有对象。

这样做显而易见,简单高效,但是缺点也很明显,内存直接砍半使用,实际在使用的只是真实内存的一半,内存代价比较高。

对复制算法的进一步优化就是我们的主角了,即使用 Eden、S0、S1 三个分区。这三个分区的空间默认比例为 8:1:1,可以使用的内存(即可分配新生对象的内存空间)是总内存空间的 9/10,显然比 1/2 强得多。

过程和 Copying 算法的过程类似。首先在 Eden S0 中进行分配新对象。然后复制活对象进 S1

中,清理 Eden S0,一次新生代 GC 结束。然后在 Eden S1 中分配新对象...

这种做法除了对内存的空间利用率变高,还有便于计算 GC 次数。


后记:垃圾收集算法以及垃圾回收器概括(轻斧正怠)

垃圾收集算法

标记-清除算法

这个算法主要分为两个阶段即标记和清除。首先会标记处所有需要回收的对象,具体过程就是用可达性分析法判断对象是否需要进行回收。在标记结束后,统一回收所有被标记的对象,同时也可以反向操作。标记活的对象,统一回收未标记的对象。

优点:简单粗暴

缺点:1. 如果 Java 堆中包含大量的对象,并且大部分都是需要被回收的,这种情况,光标记就要花费比较大的开销

标记-复制算法

此算法可以比较好的解决清除算法的缺点。此算法具体的过程为在可用内存空间中,划出两块大小相同的区域,每次只使用其中一块,另一块保持空闲状态,第一块将要用完的时候,就把存活对象放到空的另一块,然后把当前块全部清除。 此算法比较适合存活率低的情况。

缺点:内存使用太过于浪费,一块内存空间实际上只有一半在用。

标记-整理算法

此算法很好的解决了清除算法的空间碎片化问题,其算法大概过程与标记清除算法一样,不过后续步骤不是直接就对可回收的对象进行清理,而是将所有的对象都向内存空间一段移动,然后清理边界以外的内存。

分代收集

可以注意到,没有加算法。是因为分代收集更多的是一种经验产物。即对象数量和对象年龄存在一定的关系。大部分对象的生存周期是非常短的,另一个就是经历了很多次垃圾收集的对象比较难消亡。所以依据这个经验把 JVM 的堆内存空间大致分为新生代和老年代。 新生代的对象大多存活时间短,每次回收时,只关注如何保留少量存活的对象,能以较低代价回收大量空间。多采用标记复制算法,频率高。而老年代,则是一些很难消除的对象,就可以采取标记清除和标记整理算法进行垃圾回收处理,频率也低一些。

垃圾回收器

串行(Serial)回收器是单线程的一个回收器,简单、易实现、效率高。

并行(ParNew)回收器是Serial的多线程版,可以充分的利用CPU资源,减少回收的时间。

吞吐量优先(Parallel Scavenge)回收器,侧重于吞吐量的控制。

并发标记清除(CMS,Concurrent Mark Sweep)回收器是一种以获取最短回收停顿时间为目标的回收器,该回收器是基于“标记-清除”算法实现的。

我正在参与2023腾讯技术创作特训营第三期有奖征文,组队打卡瓜分大奖!

0 人点赞