Jvm中垃圾收集器

    java开发中的GC是每一个开发人员都知道的,垃圾收集器,在java开发中我们不需要对创建出来的对象做"杀死"的操作,在堆中开辟的空间也不用去手动释放,替我们完成这一切的就是JVM中自带的GC.

    GC很多开发人员觉得他是java的附属,是有了java之后,出现的GC,但是其实不然,GC的出现比java要早的多。JVM内存中,程序计数器,虚拟机栈,本地方法栈这些个区域都是随着线程生而生,死而死。我们不用关心是否释放的问题,但是在堆和方法区却不会,而GC的重点也是在堆和方法区中。

在程序回收对象的时候,只需要判断一下这个对象是否还活着,如果活着,就放过,死了就直接回收掉。如何判断对象是否活着就是第一问题。

何判断对象是否活着?

1.采用引用计数器的算法,这个对象如果引用多了一次就次数+1,如果引用减少了一次,次数就 -1.当这个对象次数为0的时候,那么这个时候就回收!但是这个算法的弊端很明显,就是对象之间相互循环引用的问题。(两个对象,我引用你,你引用了我,没有别人在来使用这个对象,但是这个时候GC没有办法回收,可是他俩又没有什么作用了)

2.可达性分析算法,这个算法就是找一些GC ROOT 根节点,从这些跟节点往下排查,如果有引用,就把你放在这个   "大网"   上面,如果没有引用,那么就可以准备回收这个对象了。这个ROOT根节点可以包括(虚拟机栈中引用对象,方法区中类静态属性引用的对象,方法区中常量引用的对象,本地方法栈中JNI引用的对象)。

两种算法中,可达性分析算法较为常用。但是不管哪种算法,他们的根本就是查看这个对象是否被引用了。但是在JDK1.2之前,这个引用的概念很笼统,如果我这个数据代表的是内存区域的一个地址,那么这就是引用了。但是在JDK1.2之后,java对这个引用的关系进行了扩充,强引用,软引用,弱引用,虚引用四种。

在通过可达性分析算法第一步时候,如果对象没有被引用的话,按理说是会被回收的,但是JVM给对象留下了一线生机。如果在发现这个对象没有被引用之后,那么会查看这个对象有没有必要执行finalize方法,如果没有执行或者已经执行过了,不好意思,直接等死。如果说,这个对象有执行finalize的机会,那么会把这个对象存放在F-Queue队列中,然后会在这个队列中进行第二次标记,如果这个时候这个对象被某个对象所引用,就可以"救活",否则就会杀死。

 

如何将需要回收的对象标记出来?

上述所有步骤,全部都是为了先确定哪个对象要被回收的问题,当确定好了这个对象要回收时,紧接着是将这些对象全部都标记出来,做好统计,然后一起"杀死"。常见的算法有

1.标记-清除算法:先都标记上,然后执行清除操作。弊端是标记清除的速度都很慢,而且清除后会有大面积的不连续的空间

2.复制算法:将内存一分为二,先用一块,然后在清除的时候,将用的这块内存中,还存活的对象全部放到第二块内存中,然后把上一块内存抹空。这种回收方式适用于新生代的,因为新生代的对象都是"死的很快的",所以这种方式不需要将内存分为1:1,这样也能规避掉复制算法的弊端。但是复制算法是需要其他内存区域做担保的,如果我的内存不够,我需要用你们的内存,这里值的是,当新生代的空间不足时候,会使用老年代的一部分空间暂时存放。

3.标记-整理算法:这个算法是针对于老年代的对象考虑的,他就是说,我先都标记上,但是由于老年代的存活时间较长,所以我不直接清理 。而是让这些存活的对象往一端移动,然后处理掉边界以外的内存。

4.分代收集算法:目前商业的虚拟机都是采用的分代收集算法,他没有什么新的思想,只不过是把java区域根据对象的存活周期分为新生代和老年代,然后每个区域去使用最适合的回收算法。

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值