1. 什么是垃圾回收?
垃圾回收(Garbage Collection,简称GC)是Java虚拟机(JVM)中的一种自动内存管理机制。它可以自动识别和清除不再使用的对象,释放内存空间,防止内存泄漏。
例如:
public void createObjects() {
String str1 = new String("Hello"); // 创建对象
String str2 = new String("World");
str1 = null; // str1不再引用对象,该对象成为垃圾
// 方法结束后str2也不再引用对象,两个String对象都会被回收
}
2. 为什么需要垃圾回收?
垃圾回收的主要目的是:
- 自动释放不再使用的内存,简化内存管理
- 防止内存泄漏
- 有效利用内存资源
没有GC的语言(如C/C++)需要程序员手动管理内存,容易出错。
3. 垃圾回收的原理
基本原理是:
- 找出内存中不再使用的对象
- 释放这些对象占用的内存空间
判断对象是否可以回收的主要方法有:
- 引用计数法
- 可达性分析
3.1 引用计数法
为每个对象设置一个引用计数器,被引用时加1,引用失效时减1。计数为0时可以回收。
Object obj = new Object(); // 引用计数为1
Object obj2 = obj; // 引用计数为2
obj = null; // 引用计数减为1
obj2 = null; // 引用计数为0,可以回收
缺点:无法解决循环引用问题。
3.2 可达性分析
从GC Roots开始搜索,搜索不到的对象即为可回收对象。
GC Roots包括:
- 虚拟机栈中引用的对象
- 方法区中静态属性引用的对象
- 方法区中常量引用的对象
- 本地方法栈中引用的对象
public class GCRootExample {
private static Object staticObj; // GC Root
public void method() {
Object localObj = new Object(); // 可能是GC Root
}
}
4. 常见的垃圾回收算法
4.1 标记-清除算法
- 标记阶段:标记出所有需要回收的对象
- 清除阶段:清除被标记的对象
缺点:效率低,产生内存碎片
4.2 复制算法
- 将内存分为两块,每次只使用其中一块
- 存活对象复制到另一块
- 清理当前使用的内存块
// 伪代码
void copy() {
for (Object obj : fromSpace) {
if (isAlive(obj)) {
toSpace.add(copy(obj));
}
}
swap(fromSpace, toSpace);
}
优点:效率高
缺点:内存利用率低
4.3 标记-整理算法
- 标记阶段:同标记-清除
- 整理阶段:将存活对象向一端移动,然后清理边界外内存
优点:不产生内存碎片
缺点:移动对象成本较高
4.4 分代收集算法
根据对象存活周期将内存划分为新生代和老年代,分别采用不同的收集算法。
- 新生代:复制算法
- 老年代:标记-清除或标记-整理
5. 触发垃圾回收
垃圾回收在以下情况会被触发:
- 当Eden区满时
- 老年代空间不足
- 方法区空间不足
- 手动调用System.gc() (不保证立即执行)
6. 垃圾收集器
常见的垃圾收集器:
- Serial收集器:单线程收集
- Parallel收集器:多线程收集
- CMS收集器:并发标记清除
- G1收集器:分区域增量式收集
7. 如何优化垃圾回收
- 减少对象创建
- 及时释放无用对象
- 使用软引用和弱引用
- 调整新生代和老年代的比例
- 选择合适的GC收集器
8. 小结
垃圾回收是Java的重要特性,理解其原理和机制对于优化Java程序至关重要。合理利用垃圾回收机制,可以让我们更专注于业务逻辑开发,而不用过多关心内存问题。
如果对垃圾回收底层原理感兴趣和想要了解可以看下面这一篇
http://t.csdnimg.cn/ctVJ9