目录
JVM垃圾回收算法
前言
已经找到工作了,分享秋招时的笔记。祝大家都能顺利找到自己心仪的工作。
面试题
垃圾收集有哪些算法,各自的特点?
虚拟机的垃圾回收机制是一种自动内存管理的机制,用于回收不再被程序使用的内存,以便将其释放并重新分配给新的对象
常见的垃圾回收策略有:
标记 - 清除:
- 标记阶段:标记所有需要回收的对象
- 清除阶段:回收被标记的对象,但会产生内存碎片,影响内存利用率
标记 - 复制:
- 将内存分为两块,一块称为 “From” 空间,一块称为 “To” 空间
- 标记阶段,将存活对象复制到 “To” 空间
- 清除阶段,清空 “From” 空间
- 适用于存活率较低的场景,避免了碎片化
标记 - 整理:
- 标记阶段标记所有需要回收的对象
- 清除阶段将所有存活的对象向一端移动,然后清除边界以外的内存
- 避免碎片化
分代收集算法:
- 根据对象的存活周期将堆划分为不同的区域(一般分为新生代和老年代)
- 针对不同区域使用不同的收集算法,新生代一般使用复制算法,老年代使用标记 - 清除或标记 - 整理算法
- 根据大部分对象在新生代快速回收和老年代存活较长的特点,分代收集算法可以提高垃圾回收效率
说一下新生代的区域划分?
- 新生代的垃圾收集主要采用标记 - 复制算法,因为新生代的存活对象较少,每次复制少量的存活对象效率较高
- 新生代分为 Eden 空间和两块较小的 Survivor 空间,每次分配内存只使用 Eden 和其中一块 Survivor 空间
- 当发生垃圾收集时,将 Eden 和 Survivor 中仍然存活的对象复制到另一块 Survivor 空间后清理空间
Minor GC/Young GC、Major GC/Old GC、Mixed GC、Full GC?
- 部分收集 (Partial GC):目标不是完整收集整个 Java 堆的垃圾收集
- 新生代收集 (Minor GC/Young GC):指目标只是新生代的垃圾收集
- 老年代收集 (Major GC/Old GC):指目标只是老年代的垃圾收集,只有 CMS 收集有这种行为
- 混合收集 (Mixed GC):目标是收集整个新生代以及部分老年代的垃圾收集,只有 G1 收集有这种行为
- 整堆收集 (Full GC):收集整个 Java 堆和方法区的垃圾收集
Minor GC/Young GC 什么时候触发?
- 新创建的对象会先在新生代 Eden 区进行分配
- 如果 Eden 区没有足够的空间,就会触发 Minor GC 来清理新生代
什么时候会触发 Full GC?
- Young GC 之前检查老年代:在要进行 Young GC 的时候,发现老年代可用的连续空间小于平均升级对象大小,触发 Full GC
- 老年代空间不足:如果老年代内存使用率过高,就会触发 GC
- System.gc() 命令:使用命令执行 Full GC
频繁 minor gc 怎么办?
通常情况下,由于新生代空间较小,Eden 空间很快就满了,就会频繁 Minor GC
可以通过增大新生代空间来降低 Minor GC 频率
HotSpot 为什么要分为新生代和老年代?
- 是为了更好地适应不同对象的生命周期和垃圾收集算法,从而提高垃圾回收的效率和性能
对象什么时候会进入老年代?/ 内存分配和回收原则?
- 长期存活的对象将进入老年代:在对象的头信息中存储对象的迭代年龄,迭代年龄会在每次 Young GC 中增加一,当年龄达到 15 时,对象将进入老年代
- 大对象直接进入老年代:占用大量连续内存空间的对象在被加载就会直接进入老年代
- 动态对象年龄判定:如果相同年龄的对象占一半以上,则年龄大于等于该年龄的对象直接进入老年代
- 空间分配担保:在 Young GC 后,新生代仍然有大量对象存活,就需要老年代进行分配担保,把 Survivor 无法容纳的对象送入老年代