垃圾收集器(Garbage Collector)
外观
垃圾收集器(Garbage Collector)[编辑 | 编辑源代码]
垃圾收集器(Garbage Collector,简称 GC)是 Java虚拟机(JVM)的重要组成部分,负责自动管理内存,回收不再使用的对象以释放内存空间。Java 开发者无需手动释放内存,从而避免了内存泄漏和野指针等问题。
1. 垃圾收集的基本概念[编辑 | 编辑源代码]
1.1 什么是垃圾收集?[编辑 | 编辑源代码]
在 Java 中,垃圾收集是指 JVM 自动检测并回收不再被引用的对象所占用的内存。当一个对象不再被任何活动线程或静态变量引用时,它就被视为“垃圾”,可以被回收。
1.2 为什么需要垃圾收集?[编辑 | 编辑源代码]
- **避免内存泄漏**:自动回收不再使用的对象,防止内存被无效占用。
- **减少开发负担**:开发者无需手动管理内存,降低代码复杂度。
- **提高程序稳定性**:减少因内存管理不当导致的程序崩溃。
2. 垃圾收集算法[编辑 | 编辑源代码]
JVM 使用不同的垃圾收集算法来识别和回收垃圾对象。以下是几种常见的算法:
2.1 标记-清除(Mark-Sweep)[编辑 | 编辑源代码]
1. **标记阶段**:遍历所有可达对象,标记为“存活”。 2. **清除阶段**:回收未被标记的对象。
- 缺点**:产生内存碎片。
2.2 复制(Copying)[编辑 | 编辑源代码]
将内存分为两块,每次只使用其中一块。垃圾回收时,将存活对象复制到另一块内存,然后清空当前块。
- 优点**:避免内存碎片。
- 缺点**:内存利用率低(仅 50%)。
2.3 标记-整理(Mark-Compact)[编辑 | 编辑源代码]
1. **标记阶段**:标记所有存活对象。 2. **整理阶段**:将所有存活对象移动到内存的一端,然后清理剩余部分。
- 优点**:避免碎片,内存利用率高。
- 缺点**:整理过程耗时较长。
2.4 分代收集(Generational Collection)[编辑 | 编辑源代码]
基于对象的生命周期将内存划分为不同的代(如新生代、老年代),并采用不同的回收策略。
- **新生代(Young Generation)**:存放新创建的对象,使用复制算法(如 Serial、ParNew、G1)。
- **老年代(Old Generation)**:存放长期存活的对象,使用标记-清除或标记-整理算法(如 CMS、G1)。
3. JVM 中的垃圾收集器[编辑 | 编辑源代码]
JVM 提供了多种垃圾收集器,适用于不同的应用场景:
3.1 Serial GC[编辑 | 编辑源代码]
- **特点**:单线程,适用于小型应用或客户端程序。
- **算法**:新生代(复制),老年代(标记-整理)。
- **适用场景**:低内存、单核 CPU。
3.2 Parallel GC(吞吐量优先)[编辑 | 编辑源代码]
- **特点**:多线程并行回收,提高吞吐量。
- **算法**:新生代(复制),老年代(标记-整理)。
- **适用场景**:多核 CPU,注重吞吐量的应用(如批处理)。
3.3 CMS(Concurrent Mark-Sweep)[编辑 | 编辑源代码]
- **特点**:并发标记和清除,减少停顿时间(低延迟)。
- **算法**:标记-清除(老年代)。
- **缺点**:内存碎片问题。
3.4 G1(Garbage-First)[编辑 | 编辑源代码]
- **特点**:分区(Region)收集,兼顾吞吐量和低延迟。
- **算法**:标记-整理 + 复制(混合)。
- **适用场景**:大内存、多核服务器(JDK 9+ 默认)。
3.5 ZGC & Shenandoah[编辑 | 编辑源代码]
- **特点**:超低停顿(<10ms),适用于超大堆内存(TB 级别)。
- **适用场景**:云原生、实时系统。
4. 代码示例:观察垃圾收集[编辑 | 编辑源代码]
以下代码演示如何手动触发垃圾收集并观察其行为:
public class GCDemo {
public static void main(String[] args) {
// 创建大量临时对象
for (int i = 0; i < 100000; i++) {
new Object(); // 这些对象很快会被回收
}
// 手动建议 JVM 执行 GC(不保证立即执行)
System.gc();
// 查看内存使用情况
Runtime runtime = Runtime.getRuntime();
long freeMemory = runtime.freeMemory();
long totalMemory = runtime.totalMemory();
System.out.println("Free Memory: " + freeMemory);
System.out.println("Total Memory: " + totalMemory);
}
}
- 输出示例**:
Free Memory: 12345678 Total Memory: 16777216
5. 实际应用场景[编辑 | 编辑源代码]
- **Web 服务器**:使用 G1 或 ZGC 减少 GC 停顿,提高响应速度。
- **大数据处理**:使用 Parallel GC 最大化吞吐量。
- **Android 应用**:使用 ART 的并发 GC 减少卡顿。
6. 性能调优建议[编辑 | 编辑源代码]
- **调整堆大小**:`-Xms`(初始堆)、`-Xmx`(最大堆)。
- **选择收集器**:如 `-XX:+UseG1GC` 启用 G1。
- **监控 GC 日志**:使用 `-Xlog:gc*` 分析停顿时间。
7. 总结[编辑 | 编辑源代码]
垃圾收集器是 JVM 内存管理的核心组件,不同的收集器适用于不同的场景。理解其工作原理有助于优化 Java 应用的性能和稳定性。