jvm之垃圾收集算法

感觉好像直接从书上简单整理上载会被csdn挂掉,可是jvm又没有啥代码敲得(脑壳疼)。
接下来关于理论复习的博客,我可能就大致表述一下需要注意的点。不会在详细的表述了,需要的同学可以根据我的整理的点,去书上看(jvm复习1中有对应的书籍,可以自己去看一看),进行一个有针对性的复习。
找到一个表述的很不错的一篇博客
https://xie.infoq.cn/article/9d4830f6c0c1e2df0753f9858
刚刚找的,写的非常详细,图画的还好看。额,开始怀疑我写这一篇的意义。

一,前言

垃圾回收是jvm中非常重要的一个部分,有之前说的jvm内存布局大致就可以知道gc(垃圾回收)的场所就是堆区了。
这里提一句,栈区是不存在垃圾回收的,因为出栈之后,对应的栈帧就直接清空,不需要去进行垃圾回收的操作。
简单类比一下,栈就是用完就丢,而堆就是再垃圾堆中先找到要留下来的东西,再把其他部分丢掉,所以这里需要垃圾收集器,垃圾收集算法来判断哪些可以丢,哪些不能丢啦。

二,判断对象是否应该回收

1,引用计数法

这个是很好理解的,简单来说,就是在对象中加一个引用计数器,有对象指向它,计数器就加一。如果计数器为0,就表明没有被引用,就会被销毁。
有大bug:聪明的同学都发现一个问题,如果有这么两个对象,你指我,我指你。好家伙,那不就神仙眷侣了,谁也不能奈何他们了。所以就有下一个算法可达性分析。

2,可达性分析

简单的聊一下思想吧,具体去书上看看吧。
当需要垃圾回收时,我们就从一个gc root中去不断引用对象,会形成一条链,那就是实际上会用到的对象,而堆中没有被引用的对象就是没有用的对象。
比如某一个方法,里面有n个对象,那么就有n个gc root 也就是gc roots,从gc roots去不断的衍生就好了。当然gc roots不只是在方法中有的,
比如常量,静态变量,jvmneib,锁中的对象,还有很多都是可以当作gc roots。

引用类型

强引用,软引用,弱引用,虚引用。强度递减

  • 强引用
    就是通常意义上的引用,如果一直被指向,是不会被垃圾回收的。所以如果有太多这样的引用,内存还不够,由于不会被回收,就溢出了。
  • 软引用
    简单意义上,通常不回收,但是内存不够,我们就会标记这些引用,在扫描一次内存,还是不够,就清除掉了
  • 弱引用
    不管内存够不够,到了gc时间,他们就被gc了
  • 虚引用
    唯一目的就是为了这个对象被回收收到一个通知。

垃圾回收过程

简单讲,就是进行两次标记,第一次是不直接回收的。第二次回收。
但是呢,有这么几种情况,第二次标记就不回收了,比如说在第二次标记时发现,它被引用了。或者是执行了finalize(),不过呢,finalize()只能执行一次,jvm会对finalize()的对象,再一次标记。如果这些对象没有和别的对象建立链接,那就被回收了。
注: finalize()只能执行一次。
讲述的非常的拉跨,强烈建议去看看书。或者看完之后,利用我的博客自己复习阐述一波。

垃圾回收算法

重点来啦!!!!!!

分代收集理论

这是由经验假说的理论。
理论是这样的:
弱分代假说:绝大多数对象都是朝生夕灭的。
强分代假说:熬过越多次垃圾收集过程的对象就越难以消 亡。
所以呢,把对象分为两类,一类就是新生代,一部分时老年代。将这两种对象放在俩块不同的区域。那么我们可以每次gc的主要目标就是新生代,对于老年代,我们可以不那么经常扫描。新生代中的对象随着gc次数不断增加,逐渐也会变成老年代。
问题来咯,为了对新生代进行一个收集,我们也是要进行可达性分析的,这里面完全是有可能从老年代指向新生代的,也就是有gc链的。
所以又有了另一个假说,跨代引用假说:跨代引用相对于同代引用来说仅占极少数。
由此,我们不必全盘扫描老年代,把老年代分成若干块,我们可以用某种数据结构来记录由老年代指向新生代的那一部分。毕竟只是极少数指向新生代,其实消耗也会少一些

标记清除算法

非常的好理解。就是标记需要回收(或者不需要回收的对象)的对象,然后回收(或者回收其余部分)。

问题来了,也就是内存碎片。由于对象回收地址不一定连续,往往空闲的区域也不连续,所以呢,万一需要分配大对象怎么办。这时候就需要标记整理算法了。

标记复制算法

简单来说,就是把新生代需要分配的空间划成两块。先用一块,只在这一块中分配对象,然后,gc时候,把存活的对象,复制到另一块,原先那块直接清空就好了。
问题: 太浪费空间了,如果是50%50%的划分,也就意味着就少了一半分配空间的区域。
所以: 我们可以吧新生代分为一块较大的Eden空间和两块较小的 Survivor空间,每次分配内存只使用Eden和其中一块Survivor。(默认Eden:Survivor=8:1)。这样就不会浪费太多空间了。
问题: 万一空间不够了怎么办,既然不是50%50%,完全有可能有超过一个Survivor的对象存活。
所以: 来一波分配担保吧,我就直接让这部分多出来的对象直接进入老年代。这不就没毛病了

标记整理算法

简单说,就是把存活的对象给标记下来。然后,垃圾回收后,把它们规整的移动在堆中的一块区域。
在这里插入图片描述
这样看起来很舒服,但是实际开销非常大。移动对象过程中,我们需要暂停用户线程(stop the world),以免出现其他问题。形象一点,当jvm gc的时候,你就卡住了,丝毫动弹不得,这还了得。所以说得慎用这个方式。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值