Java虚拟机(JVM)的垃圾回收(Garbage Collection, GC)机制是其自动内存管理的核心特性之一,它负责自动回收不再使用的对象所占用的内存空间,以避免内存泄漏和内存溢出,同时提高程序的运行效率。
基本原理
-
自动管理: JVM为程序中的对象分配内存,并在对象不再需要时自动回收内存,无需我们显式释放。
-
可达性分析: 垃圾回收的第一步是确定哪些对象是可达的,哪些是不可达的。可达性分析通过从一系列称为“GC Roots”的对象开始,沿着对象引用关系遍历对象图,标记所有可达对象。未被标记的对象被视为垃圾。
回收区域
- 堆内存划分: 主要针对堆内存进行回收,堆被划分为不同的代:
- 新生代(Young Generation): 新创建的对象通常分配在这里,此区域经常进行垃圾回收,回收速度快但频率高。
- 老年代(Old Generation / Tenured Generation): 经过几次回收仍然存活的对象会被移至此区域,回收频率较低,但每次回收耗时较长。
- 永久代/元空间(PermGen / Metaspace): 在Java 8以前,用于存储类元数据;Java 8及以后,永久代被元空间取代,后者位于本地内存中,且不进行常规的垃圾回收,但可以动态扩展。
垃圾回收算法
- 标记-清除(Mark-Sweep): 首先标记所有活动对象,然后清除未标记的对象。此算法简单,但会产生内存碎片。
- 复制(Copying): 将内存分为两块,只使用其中一块。回收时,将存活对象复制到另一块,然后清除原块。此算法简单高效,但内存使用率不高。
- 标记-整理(Mark-Compact): 结合了标记-清除和复制的优点,首先标记所有活动对象,然后将它们移动到内存的一端,最后清除剩余部分,避免了碎片化。
- 分代收集: 根据对象的生命周期将堆分为不同代,新生代常用复制算法,老年代常用标记-清除或标记-整理算法,以适应不同对象的回收特点。
触发时机
- 当堆内存不足时: JVM会自动触发垃圾回收。
- 显式调用: 在Java中,虽然不鼓励,但可以通过System.gc()方法建议JVM进行垃圾回收,不过最终是否执行取决于JVM的具体实现和策略。
优化与调优
- 调优参数: 通过JVM参数(如-XX:NewRatio、-Xmx、-Xms等)调整堆大小、代的比例和GC策略,以适应不同应用的需求。
- 监控工具: 使用VisualVM、JConsole、Java Mission Control等工具监控和分析GC行为,辅助调优。