什么是Java里的垃圾回收?
自动管理内存的一种机制,自动释放不被程序引用的对象所占的内存
如何触发垃圾回收?
- 内存不足时
- 手动请求:System.gc()
或
Runtime.getRuntime().gc() - JVM参数
判断垃圾的方法
可达性分析算法:从一组称为GC Roots(垃圾收集根)的对象出发,向下追溯它们引用的对象,以及这些对象引用的其他对象,以此类推。如果一个对象到GC Roots没有任何引用链相连(即从GC Roots到这个对象不可达),那么这个对象就被认为是不可达的,可以被回收
引用计数法
垃圾回收算法是什么,是为了解决了什么问题?
需要手动分配和释放内存,导致的内存泄漏、内存溢出等问题
常见垃圾回收算法
标记-清除(Mark-Sweep)
- 原理:通过可达性分析(从GC Roots出发标记存活对象),清除未被标记的垃圾对象。
- 适用场景:老年代(存活对象多)。
- 缺点:产生内存碎片,需两次扫描内存
复制算法(Copying)
- 原理:将内存分为两块,存活对象复制到空白区域后清空原区域。
- 适用场景:新生代(存活对象少,如98%对象可回收)。
- 缺点:内存利用率低(仅使用50%空间)
标记-整理(Mark-Compact)
- 原理:标记存活对象后,将其压缩到内存一端,消除碎片。
- 适用场景:老年代(对象存活率高,需减少碎片)
分代收集(Generational)
原理:基于对象生命周期划分内存区域(新生代、老年代):
- 新生代:存活率低,使用复制算法(Eden + Survivor区)。
- 老年代:存活率高,使用标记-清除或标记-整理算法。
优势:结合不同算法优势,提升整体回收效率
垃圾回收器
新生代回收器
Serial(响应时间优先,串行回收)
- 算法:复制算法(Copying)
- 特点:单线程串行回收,适合单核环境或小内存应用(如客户端程序)
ParNew(并行回收,响应速度优先)
- 算法:复制算法
- 特点:多线程并行回收,是Serial的多线程版本,需与CMS配合使用
Parallel Scavenge(吞吐量优先,并行回收)
- 算法:复制算法
- 特点:多线程并行回收,关注吞吐量优化,支持动态调整内存(JDK8默认新生代回收器
老年代回收器
Serial Old(响应时间优先,串行回收)
- 算法:标记-整理(Mark-Compact)
- 特点:单线程串行回收,作为CMS失败后的备用回收器
Parallel Old(并行吞吐)
- 算法:标记-整理
- 特点:多线程并行回收,与Parallel Scavenge配合,适合吞吐量优先场景
CMS(并发响应)
- 算法:标记-清除(Mark-Sweep)
- 特点:并发标记清除,减少停顿时间,但会产生内存碎片;适用对延迟敏感的应用(如Web服务)
混合回收器
G1(Garbage-First)
- 算法:分代+分区,结合标记-整理与复制算法
- 特点:将堆划分为多个Region,优先回收垃圾最多的区域;支持可控停顿时间,适合大内存堆(JDK9+默认回收器
标记清除算法的缺点是什么?
- 效率低
- 内存碎片
垃圾回收算法哪些阶段会stop the world?
- 标记阶段
- 清理阶段
- 复制阶段
minorGC、majorGC、fullGC的区别,什么场景触发full GC
minorGC
- 触发条件:Eden区满时触发,清理年轻代(Eden + Survivor区),存活对象复制到另一Survivor区或晋升老年代。
- 特点:高频、低延迟(通常毫秒级),不涉及老年代。
majorGC
- 触发条件:老年代空间不足时触发,仅CMS回收器支持单独回收老年代。
- 特点:停顿时间较长,需配合Minor GC(存活对象晋升时触发)
Full GC(整堆GC)
- 触发条件:整个堆内存(新生代+老年代+元空间)空间不足、
System.gc()
显式调用、CMS并发失败、担保失败等。 - 特点:全局回收,停顿时间最长(秒级),影响性能显著
垃圾回收器 CMS 和 G1的区别?
- CMS是老年代收集器,G1是新生代和老年代的收集器
- STW:CMS是初始标记+重新标记,G1是初始标记+最终标记+筛选回收
- CMS会产生内存碎片和浮动垃圾
- 回收过程不同,初始标记+并发标记+重新标记+并发清除(cms),初始标记+并发标记+最终标记+筛选回收
什么情况下使用CMS,什么情况使用G1?
CMS:
- 低延迟
- 主要针对老年代收集
G1:
- 需要大堆内存
- 对内存碎片敏感
G1回收器的特色是什么?
- G1最大的特点是引入分区的思路,弱化了分代的概念。
- 精细化内存管理,每次回收仅处理部分Region,避免全堆扫描
- 优先回收垃圾比例高的Region
GC只会对堆进行GC吗?
堆和方法区