JVM垃圾回收机制(一)

导语

首先我觉得有必要去声明一件事情:本作者目前记录的内容,属于自己的口水话,差不多意思就是模拟自己面试的时候该如何去和面试官表达我对垃圾回收机制的理解。
谈起回收垃圾,我觉得可以从以下这三个方面去阐述java虚拟机的垃圾回收机制

一、回收的对象

回收对象就是不可能再通过任何途径进行再次引用的对象,通常来说我们会有利用判断对象是否还有引用来确定对象是否能回收;那么我们一般就有两种方法去判断:

1.引用计数算法

引用计数,那就是看计数,我是这么理解的,在编译加载等操作的时候,每个对象的引用都会有个“引用计数器”用来记录引用的次数,那么在使用的时候就会减1,知道引用计数器上的值等于0,那就证明完成了此对象所有的引用了。
但是这个方法可能就存在一个问题,那就是有些对象互相引用;

object1.object = object2;
object2.object = object1;
object1 = null;
object2 = null;

我们可以看到,object1,object2都是不可能再被访问了,但是,由于他们循环引用,他们的引用计数器上的值就不是0,那么就不会显示可以回收。那么我们就需要使用更为合适的方法去判断他的引用是否还存在了,使用可达性算法就产生了。

2.可达性分析算法

可达性算法也叫根搜索算法,他就是像一棵树,从父节点出发,寻找引用的一层层的联系,若是没有存在引用联系的对象就会被回收。
在这里插入图片描述
此图引用来自:https://www.cnblogs.com/1024Community/p/honery.html
寻找所有的引用节点结束之后剩下的就是无用的节点了。
但这个时候,有一种特殊情况可以帮助即将被回收的对象逃离回收;
那就是判断是否需要执行finalize()方法,若是执行此方法之后,还是没有产生引用关系,那就对此对象进行回收。
具体有一篇博客有个图写得很好:https://blog.csdn.net/clover_lily/article/details/80152300

3.回收方法区

方法区一般是永久代的存放,但事实上也是需要gc的,gc两个部分的内容:废弃常量和无用的类。

二、什么时候标记回收

且不说该怎么去回收我们刚刚找到的需要回收的对象,我们来看看在什么时候去回收;
可能会有下面的原因:内存不足,或者更改一些参数促使gc;
特别想说的是gc回收的适合时间点,我们会有两个标记回收安全的区;
一个就是安全点(safepoit)
当实现根枚举进行标记对象的时候,一般会生成很多指令,这样造成暂用的内存也相当多,也会造成一些引用关系发生变化,所以我们需要在一个特定的位置进行标记然后gc,这个合适的位置一般为安全点。
安全点:能够让程序长时间执行,比如指令复用,循环,异常跳转,方法调用,我们知道指令流水线执行的时间是比较小的,所以只有重复循环使用才可以长时间执行。

注意:对于线程就是一直在跑的,所以在需要gc的时候就要把它中断,一般我们采用两种方法;
1.抢先式中断:在准备gc的时候将所有的线程中断,若是线程没有在安全点上,那就恢复线程,使其跑到安全点,目前基本不会采用这种方法了。
2.主动式中断:这个很好理解,就是在需要对线程中断的时候就设置线程中断位,线程在轮询中断位的时候,自己产生中断,此时线程会陷入自己等待的过程。

另一个是安全区域
有些线程刚好在gc的时候进入sleep()状态或者阻塞(block()),所以无法进行中断响应,而其实这个时候他们就在安全区域内(在一段代码片段中若是引用关系没有发生变化,那就是安全区域),所以当线程进入安全区域的时候就会标志自己进入安全区域,当需要发生gc时,就判断这些线程的标志位,若是安全的就不需要管了,等到线程需要跑出安全区域的时候就会判断是否完成根枚举或者完成gc,若是完成就安全跑出,若是没有就停留在安全区域。

三、如何回收

参考:https://www.cnblogs.com/xiaoxi/p/6486852.html
之前我们在判断那些对象需要回收的时候就已经进行判断标记了,我们一般有四种方法

1.标记清除

我们之前是利用可达性分析算法来标记存活的对象,现在我们标记“死掉”的对象,然后进行清除,但是,这会导致两个后果:1.效率很低,标记和清除的过程都比较慢;2.产生的内存碎片比较多,当需要分配比较大的对象就无法有足够的空间分配就会触发下一次的gc。后面的回收方法也都是对这个方法的改进。

2.复制算法

复制算法适合新生代的对象,基本会有少量的对象存活,传统的我们会将内存一分为二,一半用来分配给对象,在gc的时候,将标记存活的对象复制到另外的一半内存,但是这样对内存是消耗很大,我也我们进行一个改进,就是将内存分成三块,(Eden)8:1:1(survivor),由于新生代的存活对象小这个特点,所以我们会优先使用一块Eden与一块survivor,等到可以gc的时候,一次性的的将这两块空间里的存活对象存放到最后百分之十的空间;这里会有一个问题,那就是虽然新生代的存活对象不会很多,但是我们并不能保证只有百分之十的,那么这个时候你,我们就需要向别人借贷空间了。

3.标记整理

在标记清除的方法中,我们知道会有很多内存碎片,标记整理就是将存活的对象往边界挪动,最后将回收的对象回收,实现避免空间碎片。

4.分代收集

对于分代收集,我们会根据新生代或者是老年代来采用不同的方法,若是新声代垃圾,通常采用复制算法,若是老年代,我们会使用标记清除或者标记整理方法。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值