垃圾收集(GC)就是对Java对象的回收,Java不需要像C++那样去手动release,是有JVM的垃圾回收机制来管理的,理解垃圾收集,一般就需要弄懂以下3个问题:
- 回收哪些内存(what)
- 什么时候回收(when)
- 如何回收(how)
回收哪些内存
具体来说就是回收那些已经没有被引用到的对象(对象是否存活),可以通过一下方法来判断对象是否有被引用到呢
1. 引用计数法:
就是给对象添加一个引用计数器,当有被引用时候计数器就加1,引用失效时候就减1,任何时刻计数器为0的时候就认为对象是没有被引用;但是这种计算方法会存在问题,很难解决对象直接互相循环引用,所以不纳入jvm的对象管理中,如下片段代码:
package test;
public class Reference {
public Object instanceObject = null;
public static void testGC() {
Reference referenceA = new Reference();
Reference referenceB = new Reference();
referenceA.instanceObject = referenceB;
referenceB.instanceObject = referenceA;
referenceA = null;
referenceB = null;
System.gc();
}
}
referenceA和referenceB其实已经没有被引用了,但是这时候的计数器不是为0,因为它们之间存在循环相互引用,所以这两个对象在没有被引用的情况下没有被GC掉(所以面试时候就不要再回答这种算法啦)。
2. 可达性分析算法
过一系列的称为“GC Roots”的对象作为起点,从这些起点开始向下搜索,搜索所走过的路径称为引用链,当一个对象到GC Roots没有任何引用链相连,就说明对象不可达。
GC Roots对象:
- 虚拟机栈中引用的对象
- 方法区中类静态属性引用的对象
- 方法区中常量引用的对象
- Native方法引用的对象
3. 回收方法区
方法区是永久代的内存,这里边回收主要是回收废弃常量和无用的类。废弃常量是指定义了一些常量,但是没有任何引用对象存在了,这时候如果发生GC的话,就会把这些常量回收掉。
无用的类是指要同时满足以下3个条件:
- 该类所有的实例都已经被回收,Java堆中不存在该类的实例了
- 加载该类的ClassLoader已经被回收
- 该类对应的Class对象没有在任何对方被引用,就是不能在其他地方通过反射的形式调用到该类的方法
同时满足以上3个条件的类才算是无用的类,可以用-Xnoclassgc这个jvm参数来控制事都回收类
什么时候回收
在新生代的Eden区满了会触发新生代GC(MiMor GC),经过多次触发新生代GC存活下来的对象就会升级到老年代,升级到老年代的对象所需要的内存大于老年代剩余内存,则会触发老年代GC(Full GC)。
当程序调用System.gc()时也会触发Full GC。
如何回收
1.标记-清除算法
分为两个阶段,就是标记和清除两个阶段,只是标记后清除,会产生大量不连续的内存碎片,导致后续程序运行过程中需要分配较大内存对象的时候找不到连续的内存和不得不粗发另一次的GC
2.复制算法
复制算法是把内存按照容量划分成大小相等的两块,每次只使用其中的一块,当这一块的内存使用完了,就将还存活的虚像复制到两外一块内存上,再把已经使用过的内存一次性清理掉。效率上就比标记清除算法来的高,且每次都是对整个半区的回收,就不用考虑标记-清除算法的内存碎片问题;但是这种算法要牺牲掉一半的内存,代价非常高(年老代不使用这种算法)
3.标记-整理算法
标记-整理是指标记完需要回收的对象后,并不是直接清理掉,而是让所有存活的对象都移动到同一块区域,后再清理
4.分代回收算法
分代回收是目前经典的使用方法,,就是把对象存活周期的不同,华为称新生代和老年代,这就可以根据不同年代的特点来使用不同的回收算法,在新生代中,每次垃圾手时都会发现有大批量的对象死去,那么久可以选择复制短发,只需要付出少量的复制成本来完成,而年老代的对象存活率时很高的/而且没有额外的空间进行使用,所以使用标记-清理或者标记-整理比较适合。
垃圾收集器
如果说垃圾回收算法时内存回收的方法论,那么垃圾收集器就是内存回收的具体实现,jvm包含的垃圾收集器如下图:
- Serial收集器是单线程收集,不是指只会使用一个CPU或者一条收集线程去做回收工作,是指在垃圾回收的时候,必须暂停其他线程的工作。
- ParNew是Serial的多线程版。
- Parallel Scavenge是采用复制算法的收集器,CMS收集器是更关注收集时候的停顿时间,而它是保证达到一个可控制的吞吐量。
- CMS是一种以获取最短回收停顿时间为目标的收集器,基于标记清除算法。
- G1收集器是当今收集器技术发展最前沿的成果之一,并发症与并行,同时有分代回收,使用标记-整理算法,比CMS来得更优势。