垃圾回收机制

1. 如何判断对象已死

1.1、引用计数法
在对象中添加一个引用计数器,每有代码引用它,计数器便加1,引用失效则减1。引用计数法在实现上相对简单,判定效率高。但在Java虚拟机里没有使用引用计数器算法进行内存管理,因为它难以解决对象间循环引用的问题。

public class Test{
	public Object instance = null;
}

public static void testGC(){
	Test objA = new Test();
	Test objB = new Test();
	objA.instance = objB;
	objB.instance = objA;
	objA = null;
	objB = null;//由于两个对象间相互引用,所以并不会将它们回收。
}

1.2、可达性分析算法
目前,主流程序语言都是通过可达性分析来判断对象是否存活。基本思想是通过一系列GC Root(GC根节点)起始,向下搜索,走过的路径称为引用链,当一个对象到根节点之间没有任何引用链相连,则这个对象是不可达的。

在这里插入图片描述

Java中可作为GC Root的对象包括:

  • 虚拟机栈中的引用对象
  • 方法区中类静态属性引用的对象
  • 方法区中常量引用对象
  • 本地方法栈中引用对象

但是当一个对象为不可达时,也不一定就 ”非死不可“ ,至少需要经过两次标记过程

  1. 如果可达性分析后,对象没有与GCRoot相连接的引用链,则会进行第一次标记,然后根据对象是否有必要执行finalize()进行一次筛选,若对象没有覆盖finalize(),或者该对象的finalize()已经被虚拟机调用过了,则认为没有必要执行。
  2. 如果对象判定为有必要执行finalize()方法,会将其放置到F-Queue队列,并由Finalizer线程执行。GC将对F-Queue中对象进行第二次标记,如果对象重写的finalize()方法中重新与GCRoot建立引用链,那么再第二次标记时将被移出F-Queue,逃脱被回收的命运。,

2. 垃圾收集算法
2.1 标记—清除算法
对需要回收的对象进行标记,完成后扫描内存空间,将所有标记的对象进行回收

标记-清除算法

缺点:

  • 标记和清除过程效率不高
  • 回收之后产生大量不连续的内存碎片,导致在分配较大对象时找不到足够的连续空间,提前触发另一次垃圾收集动作。

2.2 复制算法
先将内存划分为等大的两部分,每次只使用其中一块,当一块内存用完时,采用可达行分析,将还存活的对象复制到另一块内存中,然后将之前的内存空间清空。
复制算法
缺点:
每次只能使用一半的内存空间。

2.3 标记-整理算法
标记过程与标记清除算法一样,但后续步骤不是直接清理对象,而是将存活对象都移动到空闲的一端,并更新指针。
标记-整理算法
缺点
由于需要移动对象,成本更高。

2.5 JVM为了优化垃圾收集效率,采用分代收集算法。一般把Java堆划分为新生代和老年代。在新生代中每次GC都只有少量对象存活,因此使用复制算法提高效率。而老年代中,对象存活率高,使用标记-清除或者标记-整理算法

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值