1.基本概念:
垃圾回收(Garbage Collection, GC)是自动内存管理的一种机制,用于回收程序运行过程中不再使用的对象所占用的内存空间。在编程语言(如Java、Python等)中,垃圾回收机制有助于减少内存泄漏和内存管理的复杂性。垃圾回收算法和回收器是实现这一机制的核心部分。
2.垃圾回收算法:
(1).引用计数算法:
- 基本思想:每个对象都有一个引用计数器,记录有多少个引用指向该对象。当一个对象的引用计数为0时,该对象会被立即回收。
- 优点:实现简单,对象的回收是及时的。
- 缺点:无法处理循环引用(即两个对象互相引用)。
(2).标记-清除算法:
- 基本思想:GC暂停程序的执行,遍历所有的对象,将所有可达的对象进行标记,然后清除未被标记的对象。
- 优点:能够处理循环引用,回收所有不再使用的对象。
- 缺点:需要暂停程序执行("Stop-The-World"),导致停顿时间较长,且清理后可能会产生内存碎片,分配速度慢。
(3).复制算法:
- 基本思想:将内存分为两个区域(如"From"和"To"),每次GC时将存活的对象从一个区域复制到另一个区域,然后清空原来的区域。
- 优点:高效地分配和回收内存(分配速度快),不会产生碎片。
- 缺点:需要双倍的内存空间(只能使用一半的内存空间),内存利用率较低。
(4).标记-整理算法:
- 基本思想:与标记-清除类似,通过可达性分析标记所有被引用的对象。然后,在整理阶段,将所有存活的对象向一端移动,并且清理掉末尾的垃圾对象
- 优点:没有内存碎片,提高内存利用率。
- 缺点:整理阶段需要良好的算法,否则效率不高。
(5).分代GC:
- 基本思想:将堆内存分为多个代(一般为年轻代和老年代),不同代使用不同的GC策略。年轻代频繁回收,老年代回收频率较低。
- 优点:提高了GC的效率,减少了GC停顿时间。
- 缺点:实现复杂,需要适应不同对象的生命周期。
分代垃圾算法中,年轻代一般选择复制算法效率高,不会产生内存碎片,老年代可以选择标记-清除算法或者标记-整理算法。
3.FullGC:
FullGC 是 Java虚拟机(JVM)中垃圾收集过程的一种情况。它是一个较为昂贵的操作,会对整个堆(包括年轻代和老年代)进行垃圾回收,通常会导致较长的"Stop-The-World"(STW)暂停时间,因此开发者往往会尽量避免频繁的Full GC。
3.1 触发条件:
(1).老年代空间不足:
当老年代(Old Generation)空间不足时,需要触发Full GC来回收老年代中的垃圾对象
(2).永久代(PermGen)或元空间(Metaspace)空间不足:
在JDK 8之前,永久代存储类的元数据,PermGen满了可能会触发Full GC。
在JDK 8及之后,永久代被替换为元空间(Metaspace),如果元空间满了也会触发Full GC。
(3).显式触发:
通过调用 System.gc() 方法显式触发垃圾回收。虽然调用该方法只是向 JVM 发出建议,但在某些情况下,JVM 可能会选择执行 Full GC。
3.2 Full GC总结:
Full GC 是一种较为耗时的操作,因为它需要扫描和回收整个堆内存。在 Full GC 过程中,
应用程序的执行通常会暂停,这可能会导致较长的停顿时间(长时间的停顿会影响应用程序的响应性能)。
为了避免频繁的 Full GC,通常采取一些优化措施,如合理设置堆大小、调优垃圾回收参数、减少对象的创建和存活时间等。
4.垃圾回收器:
(1).Serial GC:
- 单线程垃圾回收器,适用于单处理器环境。
- 简单且低开销,适合小型应用程序或低内存环境。
- 停止所有应用线程(Stop-the-World)进行垃圾回收,导致停顿时间较长。
(2).Parallel GC(Throughput Collector)
- 多线程垃圾回收器,适合多处理器环境。
- 主要目标是提高吞吐量(减少垃圾回收的总时间)。
- 停止应用线程,但垃圾回收期间并行工作,适合批处理和后台任务。
(3).CMS(Concurrent Mark-Sweep) GC
- 低停顿时间垃圾回收器,适合响应时间敏感的应用程序。
- 在标记和清除阶段与应用线程并发工作,但会产生内存碎片。
- 逐步被G1 GC取代。
(4).G1 GC(Garbage-First Garbage Collector):
- 面向大内存、多处理器的应用程序设计,适合大多数应用。
- 分区化的内存管理,能有效减少内存碎片,提供可预测的停顿时间。
- 自动选择年轻代和老年代的内存回收区域。
(5).ZGC(Z Garbage Collector):
- 专为低延迟设计,停顿时间通常低于10毫秒。
- 适用于高吞吐量、高并发的应用,能处理大规模的堆(最大可达TB级)。
- 采用染色指针和加载屏障技术来实现并发垃圾回收。
(5).Shenandoah GC:
- 类似于ZGC的低停顿垃圾回收器。
- 采用并发压缩算法,最大化减少停顿时间。
- 更适用于大堆内存和响应时间要求高的应用程序。
垃圾回收器组合:
JDK8及之前:
ParNew +CMS(关注暂停时间),
Parallel Scavenge + Parallel Old (关注吞吐量),
G1(JDK8之前不建议,.较大堆并且关注暂停时间)
JDK9之后:G1(默认)
从JDK9之后,由于G1日趋成熟,JDK默认的垃圾回收器已经修改为G1,所以强烈建议在生产环境上使用G1。
如果对低延迟有较高的要求,可以使用Shenandoah或者ZGC。