java的垃圾回收机制

从上篇的那个JVM虚拟机中的内存分配情况兄弟们就可以看出,有些时候我们的那个GC老大爷是要去把这个内存的区域巡检并且清楚一遍的,之前看过的文章都告诉我们要去对我们的那个堆进行清理,但是为什么呢?其他的内存区域不要清理吗,堆说凭什么欺负人?

哈哈哈哈,GC老大爷说,堆,你还别不服,你去和各位兄弟们比较比较,是谁占用的空间多,我们一个个来说
1: 人程序计数器就存了个字节码的指令地址而已,少的可怜,而且还是当前的一个指令地址呢,你有啥可说的
2: 本地方方法区和栈就不用说了,人会有自动入栈和出栈操作,当一个线程结束后,这个栈就空了,多自觉,都不用我催,而且人平时存储的就是一些局部变量和操作栈而已,字节数估计就三四个字节
3: 堆,你看看你自己,不停地创建对象,创建一个对象所开辟的内存空间还不少呢,又是整形变量,数组,链表啥的,他么的内存大哥要给你切一块大肉,线程结束后如果我不盯着你,我们的这个区域空间迟早会被你给撑爆,到时候大家一起玩完。所以给本大爷好好听话,乖乖接受监督。
4: 方法区,人就一个运行时的常量池需要我盯着,而且占的空间又不是很大,不过这个常量池如果太多常量我这个老大爷也会秉公执法,乖乖监督的。

哈哈哈,兄弟们看清楚了吧,所以最终我们GC老大爷重点关注内存区域中的堆和方法区,尤其是堆,要时刻监管,启动空间回收,把一些不用的对象当作垃圾清理掉。

那么GC老大爷如何对这个堆里面的对象做清理呢?有什么规则没?哈哈哈,GC老大爷说瞧不起谁呢,你大爷也还是你大爷,老骥伏枥,志在千里。哈哈哈,扯远了,要清楚GC老大爷有什么清楚的方法,我们首先来看下堆里面的具体空间分配,如下图所示:
在这里插入图片描述
GC老大爷感叹,要不内存老大偏袒堆呢,内存老大这个仓库总监,一下子就把30个房间的仓库给了堆,怪不得堆天天一副趾高气昂的样子,谁让人家是享受了偏爱呢?
兄弟们仔细看看,上面的这个30个房间,存活时间比较长的老年代占据了20个房间,而新出生的小年轻占据了10个房间,而这10个房间里面还按照8:1:1 分成了三部分,相对来说比较年轻的比如就是1-10岁的占据了8个房间教程Eden区的房间,而20-40 以及40-60的中年群体才占据了2个房间,分别是surviorFrom 以及surivorTo的房间;如果从一个社会的构成来说,这样的社会很不健康,小年轻和老年人占据了大多数。但是兄弟们,如果我们从古董的这个角度来看,存活时间相对来说比较久算是比较有价值的,那这个分配算是勉强合理的。
咳咳咳,GC老大爷说别扯淡了,赶紧进入正题吧,这他么我还干着去下一个场清理垃圾呢,兄弟们搬好小板凳听老大爷指教。
一:MiorGC
GC老大爷说:“这两个区域大家也看的出来,我关注频率比较高的是这个新生代,毕竟老古董价值还算比较大,不用太频繁清理。我每次会去巡逻一边,当发现那8个房间的eden区几乎装不下新出生的小屁孩的时候,我就开始动手了,首先把Eden区和SurivorFrom区的还有活力的小屁孩们赶到ShurviorTo 区域,如果surivorTo 区域装不下,那就放一部分到老顽童的那个区域,接着把那8+1的9个房间的不活跃的小屁孩赶走,全部清空,完成这项工作后先让我歇息下抽口烟,哈哈哈,抽完烟之后接着把刚刚surivorTo 区域的小屁孩赶到surivorFrom区域,这个时候就出现了Eden+surivorTo 9个房间,一次小小的垃圾清理完成了,哈哈哈,本大爷把它叫做MinorGC, 这个清理的方法就叫做复制-算法可以继续抽烟了!”
哈哈哈,你大爷不愧是你大爷,讲的还挺清晰, 兄弟们是不是意犹未尽啊,不过是不是还有个疑虑,什么叫做不活跃的小屁孩,大爷说,“孺子可教也,这个是关键,不活跃的小屁孩可不就是生产线(线程)再也不太用的人力吗,就是对应我们书本上说的引用,你的作用都没了,不清理你清理谁,哈哈哈,感觉有亿点点残忍啊!”
二:MajorGC
兄弟们,讲完了小屁孩的清理,是不是该讲讲如何清理下这个老年代,看看GC老大爷和老顽童们如何斗智斗勇的,继续做好小板凳吧!
把最后一口烟吸完,GC老大爷踩灭了烟头,接着说,“虽然这些老顽童比较多,但是还不太怎么耗费我的精力,毕竟他们的空间够大,我只是每天定点的时间过去看看,比如每天的15点,当发现这20个房间有19个房间已经满了的时候,我就赶紧去这20个房间巡逻一边,之前当发现有些老顽童和上帝去见面的时候,我就赶紧标记房间号,用小本子标记下来,然后等待巡检完成的时候,我立马叫来搬运工,把这些老顽童给搬走,留出来一些空房间供新的老顽童使用,这种方法叫做标记-清除算法,这个过程也就是我们所说的MarjorGC,不过这种方法存在一个缺点,房间小的装不下以后进来的体格大的老顽童,就是你们所说的内存碎片,后来向仓库总监反映下了,这个方法要改进下,把清理小屁孩的那一套参考下, 原来的方法不变,移走了不活跃的老顽童之后,我们把现存的老顽童集中移到这20个房间的一侧,留出些集中的空白区域给新的老顽童,这样就不存在所谓的狭小空间的碎片一说了,身体比较庞大的老顽童过来照样可以获取到想要的大小的空间,请给我鼓掌,这个就是咱发明的标记–整理算法”
还得是GC老大爷啊,兄弟们请给予最大的掌声,我们老大爷三言两语就把这个垃圾清理的一套给大家整明白了
三:垃圾清理对象的根本逻辑
“大爷”,我举手道,GC老大爷说,“你个小兔崽子还有啥问题吗?”,我疑惑道,“大爷,兄弟们现在都大致明白了这一套内存分配机制和清理的算法了,不过还是有一点很关键啊,到底啥时候才决定某个对象才能被清理呢,刚刚还是有点模糊。”
“哈哈哈哈哈哈哈,还是你个小屁孩有点打破砂锅问到底的味道啊,和我年轻时候很像,罢了,还是给你们讲透下吧,来,再点根烟”。我乖乖地把打火机点出火苗让大爷狠狠地吐了一口烟圈。
GC老大爷说到,“说白了,要清理某个对象,我刚刚说是否有某个线程要用到它,说的更具体点就是有没有那么一根线,线程中的一根线指向它,这就叫引用。我有个小老弟,就是专门统计这些线的个数,当我们一个线程开始运行起来的时候,这个小老弟就吭哧吭哧去诸如虚拟机栈啊,方法区这些地方,问下总管人员,有没有产生的新的某个变量,指向了某个对象,有的话他就记录下来+1,同时也会问有没有某个变量的这根线断掉了,断掉的话就对某个对象-1;然后每次我要赶走这些小屁孩和老顽童的时候,我都会去问下我这个称作引用计数器的小老弟,把对象的引用为零的给我找出来,我去让他们准备卷铺盖走人了”
哈哈哈,还是GC老大爷牛逼,小弟也是个不省油的灯,“不过,大爷,如果某个变量a先是指向了小屁孩A, 然后在某个过程中又指向了小屁孩B;恰巧变量b也是先指向了小屁孩B,然后在某个过程中又指向了小屁孩A;然后小屁孩A和小屁孩B就手牵手做转圈运动了,这相互牵扯导致引用数大家都不为0,哈哈哈,达到了自救的目的!“
”孺子可教也,你说到了关键点,“,GC老大爷说到,“这样确实会存在互相循环,我的引用计数器小老弟给我汇报过来的这两个小屁孩一直为1,我就很奇怪了,它们又没有要在很多地方用到,所以为了避免这种情况的出现,仓困总监说出了一个办法”
“既然你们手牵手跳着舞成了一个小循环,那我就让所有的其他人撤到一边,从头开始排查,看看除了你们两个小屁孩,还有没有其他人还跟你们用线牵着手的,如果没有,不好意思,你们还是要出局,这就是另外一个方法,叫做可达法,明白没,还有疑问吗?”
明白明白,谢谢GC老大爷了!

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值