GC之路

  本文一样是参考周志明的《深入理解java虚拟机》和java虚拟机规范,加上一些自己的意见,希望大家批评指正。

面对GC(Garbage Collection)的三个问题

  1.哪些内存需要回收?

  2.什么时候回收?

  3.如何回收?

  了解这三个问题,可以当我们需要排查各种内存溢出,内存泄露问题时,当垃圾收集成为系统达到更高并发量的瓶颈时,我们可以自己针对其调控。

哪些内存需要回收

  首先我们根据内存模型(参照我的上一篇)来看,线程独享的三个内存区域:程序计数器,虚拟机栈(包含了栈帧),本地方法。他们三个都是随线程而生随线程而灭。这个几个都是在编译期间都可以确定大小了的,因此这几个区域的内存分配和回收都具备确定性,这几个区域内就不需要过多考虑回收的问题(因为方法结束或者线程结束时,内存自然就跟着回收了)。

  而java堆和方法区不一样,对于这两个区域我们只有在程序运行期间才能知道会创建哪些对象,这部分内存的分配和回收都是动态的,垃圾回收器所研究和关心正是这个部分内存。

什么时候回收?

  上面已经说到,我们只针对方法去和java堆。当我们会判断一个对象是否死去,这里有两个方法:

  1.引用计数法

  给对象中添加一个引用计数器,没当有一个地方引用它,计数器值加1;当引用失效时,计数器值减1;任何时刻计数器为0的对象就不能再被使用。对于引用计数法来说,实现比较简单也比较有效率,但是有一个很大的缺点就是很难解决对象之间的相互循环引用问题。
比如: ObjA.instance=ObjB和ObjB.instance=ObjA,这个时候就会出现循环引用问题,无法回收。

  2.可达性算法

  可达性算法也是javaGC机制中用的一个算法,这个算法的基本思路是:通过“GC Roots”的对象作为起点,从这些节点开始向下搜索,搜索所走过的路径称为引用链,当一个对象到GC Roots没有任何引用链相连,则证明此对象不可用。

GC Roots的对象包括:

1.虚拟机栈中引用的对象。

2.方法区中类静态属性引用的对象。 //static Obja obj=new ObjA();

3.方法区中常量引用的对象。//final Obja obj = new ObjA();

4.本地方法栈中引用的对象。

  3.引用的问题

  上面的两个算法都和“引用”有关,所以我们这里来说一下引用。在JDK1.2之前,JAVA中的引用的定义很传统:如果reference类型的数据中存储的数值代表的是另一块内存的起始地址,就称为这块内存代表着一个引用。对于这种定义只有引用和被引用的两种状态。在jdk1.2之后,java对引用的概率进行了扩充,分为强引用,软引用,弱引用,虚引用。

强引用:和ObJect obj=new Object()只要这个引用还在,垃圾收集器永远不会回收掉被引用的对象。

软引用:软引用的描述是一些还有用但并非必须的对象。对于软引用关联着的对象,在系统将要发生内存溢出之前,将会进行把这些软引用的对象回收。如果还没有足够的内存,就会抛出内存异常错误。

弱引用:弱引用只能生存到下一次垃圾收集发生之前。

虚引用:最弱的一种引用关系,设置这个唯一的目的就是能在这个对象被收集器回收时得到一个通知。

  4.一个对象到底死还是没死

  对于上面的算法即便是判断了没有引用的对象,这只是他们判了死刑但是还没有执行。真实的是要进行两次标记过程,第一次标记时用上面的算法判定,这个时候就等于被判了死刑,对他进行了第一次标记。然后进入第二次标记,判断其是否有必要执行finalize方法,就等于判断其有没有提出上诉。当对象没有提出上诉或者已经上诉过了,这个时候法院就认为没必要执行上诉,直接执行死刑。当一个对象判定有必要执行上诉(也就是自己的finalize()方法)的时候,这个对象会被放置在一个上诉列表中(也就是F-Queue),然后由一个法庭接手(也就是虚拟机自动建立的,低优先级的Finalizer线程),然后这个时候囚犯依然有机会洗脱罪名(在finalize()中重新与引用链上的一个对象建立关系,最多的是this(是栈中的引用的对象))。这个时候这个囚犯就活了。

  在这里我们要注意,第二次率先的条件是对象是否覆盖了finalize()方法,或者finalize()方法是否被虚拟机调用过了。

  5.回收方法区

  在java虚拟机的规范中没有要求对方法区实现GC,因为在方法区中进行GC比较低。

  对于永久代中回收一般是两部分:废弃常量和无用的类。回收废弃常量和回收java堆中的对象非常相似。对于判断一个常量是否是”废弃常量”比较简单,但是判断一个无用的类就不容易了。通常满足以下三个条件:

  1.该类所有的实例被回收。

  2.该类的类加载器被回收。

  3.该类的Class对象没有在任何地方呗引用,无法再其他任何地方通过反射再次创建。

*  满足了这三个条件,只是可以回收,注意是可以!!!*具体的回收还需要操作虚拟机的相关参数。

对于怎样回收下次在说

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值