企业🤖AI智能体构建引擎,智能编排和调试,一键部署,支持私有化部署方案 广告
## 分代收集理论 ### 3个假说 * 弱分代假说:绝大多数对象都是朝生夕灭的。(设计了年轻代) * 强分代假说:熬过越多次垃圾收集过程的对象就越难以消亡。(设计了老年代) * 跨代引用假说:跨代引用相对于同代引用仅占极少数。(实际Java应用中,可能会存在年轻代的对象跨代引用了老年代的对象)(设计了`记忆集`,在新生代上建立全局的记忆集,把老年代划分为若干个小块,标识出老年代的哪一块内存会存在跨代引用,此后在Minor GC时,只有包含了跨代引用的小块内存里的对象才会被加入到GC Roots进行扫描) ### 分代实现 ![](https://img.kancloud.cn/24/13/241383bdd98b8d68858b9fe1586268ba_1252x516.png) HotSpot虚拟机中,根据对象存活周期的不同,将内存划分为几块。一般是将Java堆分为新生代和老年代,比例为`2:1`;新生代又细分为`Eden`区、`From Survivor`区和`To Survivor`区,比例为`8:1:1`。不同的代采用不同的回收算法: * 新生代:复制算法 * 老年代:标记-清除算法,或者标记-整理算法 ### 定义一些关于GC的名词 1. 部分收集(Partial GC): 不是完整收集Java堆的收集。 * 新生代收集(Minor GC/Young GC):只是新生代的收集。 * 老年代收集(Major GC/Old GC):只是老年代的收集。目前只有CMS收集器会有单独收集老年代的行为。 * 混合收集(Mixed GC):收集整个新生代以及部分老年代的垃圾收集。目前只有G1收集器会有这种行为。 2. 整堆收集(Full GC):收集整个Java堆和方法区的垃圾收集。 ## 垃圾收集算法 知道了如何判定**无用的对象**、**废弃常量**和**无用的类**后,接下来就是将这些无用的对象给回收掉。 如下是常用的3种垃圾收集算法。 ### 标记-清除 ![](https://img.kancloud.cn/73/5a/735a6efe6ff6caf8f94af147e5e4c4dc_1620x980.png) 该算法分为标记和清除两个阶段。 * 标记:遍历所有的 GC Roots,然后将所有 GC Roots 可达的对象标记为存活的对象。 * 清除:遍历堆中所有的对象,将没有标记的对象清除掉。同时清除对象上的标记,以便下一次垃圾回收。 这种方法有2个不足: 1. 效率问题:标记和清除2个过程效率都不高 2. 空间问题:回收后内存会有大量碎片;碎片太多可能导致以后需要分配大对象时,无法找到足够连续的内存不得不提前触发另一次垃圾回收动作。 ### 复制(新生代) ![](https://img.kancloud.cn/1b/8b/1b8bf2a00f285696149f4d3a2e633613_1618x978.png) 为了解决效率问题,复制算法出现了。它将可用内存按容量划分为大小相同的两块,每次只使用其中的一块。当这一块内存用完,需要进行垃圾收集时,就将存活的对象复制到另一块上,然后清除掉这一块内存。 这种算法有优有劣: * 优势:不会产生碎片。 * 劣势:内存缩小为原来的一般,浪费空间。 **为了解决空间利用率问题**,可以将内存分为3块:Eden、From Survivor、To Survivor,比例是8:1:1,每次使用Eden和其中一块Survivor。回收时,将Eden和Survivor中存活的对象一次性复制到另一块Survivor空间上,最后清理掉Eden和刚才使用的Survivor空间。这样只有10%的内存被浪费。 但是无法保证每次回收都只有不多于10%的对象存活,当Survivor空间不足时,需要依赖其他内存(老年代)进行**分配担保**。 **分配担保**是指如果另一块Survivor空间没有足够空间存放上一次新生代收集下来的存活对象时(超过10%),这些对象将直接通过分配担保机制进入老年代。 ### 标记-整理(老年代) ![](https://img.kancloud.cn/43/93/4393cc6bc80aa5131f1dfefa74939856_1612x984.png) 该算法分为标记和整理两个阶段。 * 标记:遍历所有的 GC Roots,然后将所有 GC Roots 可达的对象标记为存活的对象。(和标记-清除的标记阶段一样) * 整理:移动所有存活的对象,按着内存地址次序依次排列,然后将末端地址以后的全部内存回收。 这是一种老年代的收集算法,老年代的对象存活时间比较长。 ## 参考资料 * 周志明 * 《深入理解Java虚拟机》 * Java虚拟机底层原理知识总结 * https://doocs.github.io/jvm/