java语言中判定一个对象是否存活,用的是根搜索算法。
算法思路:从一系列名为“GC Roots”的对象作为起始点,开始向下搜索,搜索经过的路线称为引用链。当一个对象到GC Roots没有任何应用链相连,则证明此对象是不可用的。
可以作为GC Roots的对象包括:
(1)虚拟机栈(栈帧中的本地变量表)中的引用的对象。
(2)方法区中的类静态属性引用的对象。
(3)方法区中常量引用对象。
(4)本地方法栈中JNI(native方法)的引用对象。
对象不可用并不是代表一个对象已经死亡,可以进行回收,在这之前至少要经历两次标记过程:如果对象被宣告为不可用,那它将会被第一次标记并进行第一次筛选,筛选条件是此对象是否有必要执行finalize()方法。当对象没有覆盖该方法,或者该方法已经被虚拟机执行,则这两种情况都被视为“没有必要执行”。
如果这个对象被判定为有必要执行finalize()方法,那么这个对象将被放置在一个名为F-Queue的队列中,并在稍后由一条由虚拟机自动创建的、低优先级的Finalizer线程去执行,但是虚拟机不会阻塞在该方法上,这是为了避免由于finalize()方法执行时间过长或者死循环造成的内存回收系统崩溃。finalize()是对象逃逸的最后一次机会。如果对象在finalize()方法成功的将自己和引用链连接上,那么在F-Queue上的第二次标记时,它将被移出即将回收的集合。还有一点要注意的是finalize()方法对于一个对象而言只会执行一次。
jdk1.2以后java对引用的概念进行了扩充:
(1)强引用(Strong Reference):在程序代码中普遍存在的。类似“Object obj = new Object()”,这类引用只要存在垃圾收集器永远不会回收。
(2)软引用(Soft Reference):一些还有用,但并非必须的对象。系统将在发生内存溢出异常之前,将这些对象列进回收范围之中并进行第二次回收。如果回收后还没有足够内存,才抛出异常。
(3)弱引用(Weak Reference):也是描述非必须对象,被弱引用关联的对象只能生存到下一次垃圾收集之前。
(4)虚引用(Phabntom Reference):最弱的引用关系。为一个对象设置虚引用的唯一目的就是希望能在这个对象被回收时收到一个通知。
首先标记出要回收的对象,在标记完成后统一回收掉被标记的对象。
缺点:效率问题,标记和清除效率都不高。导致产生大量不连续的内存碎片。
将空间容量等量的划分成两块,每次使用其中一块。当当前块用完时,将存活对象复制到另外一块,然后将前面一块清理掉。
优点:实现简单、运行高效。
缺点:内存缩小了一半,空间代价高昂。
现在的商业虚拟机都采用这种方法来回收新生代。新生代的对象一般都是朝生夕死,所以不需要1:1的划分空间。而是将分为较大的一块为Eden,两块较小为Survivor空间,每次使用一块Survivor,回收时将Eden和Survivor中存活对象复制到另外一块Survivor空间。HotSpot默认Eden:Survivor=8:1。但是也有可能会出现Survivor大小不足以满足一次复制的需求,这就需要依赖其他内存(这里指老年代)进行分配担保(Handle Promotion),一旦出现这种Survivor空间不够的情况,这些对象将直接进入老年代。
复制算法在对象存活率较高时就要执行较多的复制操作,效率就变低。如果Survivor空间不足还需要额外的空间分配担保。所以根据老年代的特点,运用“标记-整理”算法。标记过程和前面提到的标记算法一致,后面将存活对象都移动到空间的一段,然后清理另一端。
(1)Serial收集器:用户线程将暂停,GC为单个线程。
(2)ParNew收集器:Serial收集器的多线程版本。用户线程将暂停,在新生代收集时GC为多个线程。
(3)Parallel Scavenge收集器:并行的多线程收集器。其他收集器关注缩短收集时用户线程暂停时间,而此收集器的目标是到达一个可控的吞吐量(Throughput),就是cpu用于用户的时间与CPU总消耗时间的比值。
(4)Serial Old收集器:Serial收集器的老年代版本。单线程。
(5)Parallel Old收集器:Parallel Scavenge收集器的老年代版本。多线程。
(6)CMS(concurrent Mark Sweep)收集器:最短回收时间为目标的收集器。垃圾收集过程分为4个过程:
(1)在新生代进行Minor GC。发生频繁,回收速度也比较快。老年代进行Full GC,经常会伴随一次Minor GC,也叫Major GC一般比Minor GC慢10倍。
(2)多数情况下,对象直接在新生代Eden区中分配。当Eden区没有足够的空间进行分配时,虚拟机将发起一次Minor GC。当Survivor区空间不足时,Minor GC将对象存入老年代。