1. 对象在什么时候变为垃圾
判断标准:没有被其他对象引用
1.1 引用计数法
- 优点:执行效率高,程序执行受影响小
- 缺点:循环引用
1.2 可达性分析算法
通过判断对象的引用链是否可达来决定对象是否可被回收
结构图

可以作为 GC Root 的对象
- 虚拟机栈中引用的对象(栈帧中的本地变量表)
- 方法区中的常量引用对象
- 方法区中的类静态属性引用的对象
- 本地方法栈中 JNI (Native 方法)的引用对象
- 活跃线程的引用对象
2. GC 算法
2.1 标记-清除算法 (Mark and Sweep)
- 标记:从 GC Root (可达性分析算法) 进行扫描,对存活的对象进行标记
- 清除:对堆内存进行从头到尾的遍历,对标记对象进行清理

2.2 复制算法 (Copying)
该算法把内存分为两个区域:对象面和空闲面
- 对象在对象面上创建
- 存活的对象将会从对象面中复制到空闲面
- 最后将对象面的所有对象的内存释放 ps:该算法适用于对象存活率低的场景 (一般用于回收年轻代)

- 优点
- 解决了碎片化问题
- 顺序分配内存,简单高效
- 适用与对象存活率低的场景
- 缺点
- 需要两倍的内存空间
- 当对象存活率高的时候,需要复制的对象较多
2.3 标记-整理算法 (Compacting)
- 标记:与标记清除相同
- 整理:移动所有存活对象,且按照内存地址次序依次排列,然后将末端地址以后的内存全部回收

- 优点
- 避免了内存的不连续行
- 不用设置两块互换内存
- 适用于存活率高的场景
2.4 分代收集算法
按照对象的生命周期划分出不同的区域以采用不同的垃圾回收算法
目的:提高 JVM 垃圾回收的效率
版本差异
JDK 6 与 JDK 7


2.4.1 Young Generation
目的:尽可能块的收集掉那些生命周期短的对象
- Eden 区
- 两个 Survivor 区

当 Eden 空间不足时,会触发 Minor GC
2.4.2 Old Generation
目的:存放生命周期较长的对象
Full GC
触发 Full GC 的条件
- 老年代空间不足
- JDK 7 及之前的版本,永久代空间不足
- CMS GC 时,出现 promotion failed 或者 concurrent mode failure
- Minor GC 晋升到老年代的平均大小大于老年代的剩余空间
- 调用 System.gc() (还是由虚拟机决定是否 GC)
3. GC 相关面试题
3.1 Object 的 finalize() 方法是否与 C++ 中的析构函数类似
- C++ 中的析构函数的调用时机是确定的,而 Java 中的是不确定的
- Java 中将未被引用的对象放在 F-Queue 队列
- Java 中的 finalize 方法执行随时可能会被终止
- 对象最后一次"重生"机会
3.2 Java 中强引用、软引用、弱引用和虚引用有什么用
3.2.1 强引用 (Strong Reference)
- 最普遍的引用:Object obj = new Object();
强引用在 GC 中的特性
- 在 GC 中,GC 宁可抛出 OutOfMemoryError 终止程序,也不会回收具有强引用的对象
- 如果需要使用 GC 来回收强引用,将对象置为 null 来弱化引用,从而被 GC 回收
3.2.2 软引用 (Soft Reference)
- 表示一个对象处于有用但非必须的状态
- 只有在内存空间不足时 GC 才会回收该对象使用的内存空间
- 可以用来实现内存敏感的高速缓存
// 软引用的创建方法
SoftReference<String> stringSoftReference = new SoftReference<String>("abc");
3.2.3 弱引用 (Weak reference)
- 非必须的对象,比软引用更弱一些
- GC 的时候会被回收,但是被回收的概率也并不大,毕竟 GC 线程的优先级很低
- 适用于引用偶尔被使用且不影响垃圾收集的对象
// 弱引用的创建方法
WeakReference<String> stringWeakReference = new WeakReference<String>("abc");
3.2.4 虚引用 (Phantom Reference)
- 不会决定内存的生命周期
- 任何时候都可能被 GC 回收
- 主要用来跟踪对象被垃圾收集器回收的活动,起哨兵的作用
- 虚引用必须和引用队列 ReferenceQueue 联合使用
// 虚引用的用法
ReferenceQueue<String> referenceQueue = new ReferenceQueue<String>();
PhantomReference phantomReference = new PhantomReference("abc", referenceQueue);
3.2.5 层次结构

3.2.6 引用队列 (Reference Queue)
- 虽然名字中有队列,但无实际存储结构,存储逻辑依赖于内部节点之间的关系来表达
- 存储关联且被 GC 的软引用,弱引用和虚引用
- 虚、