JVM学习日记⭐️垃圾收集算法之三种假说⭐️

545 阅读4分钟

“这是我参与8月更文挑战的第15天,活动详情查看:8月更文挑战

💗引言

写了好久的水文,终于能写点干的了,好开心,不知道干货在我手里能不能变成水货,没有开个玩笑,我讨论的不是算法的细节,而是介绍算法的思想和它的发展过程,从对象消亡的角度来说,垃圾搜集算法可以划分为:“引用技术式收集”和“追踪式垃圾收集”。我们主要讨论的是:追踪式垃圾收集。

💗分代搜集理论

💚强分代和弱分代

我们商业虚拟机的设计实现,绝大多数都是采用分代收集理论来进行设计,分代收集名为理论,实为程序运行的实际情况的经验,它是建立在以下两个假说中的:

  • 弱分代假说:绝大多数对象都是朝生夕灭的
  • 强分代假说:熬过越多次垃圾回收的对象就越难以消灭

这两种假说给我们提供了一种设计思想就是将java堆划分出不同的区域,别急我们慢慢来说明一下:根据弱分代理论呢,如果有专门一块区域的绝大多数对象都是“脆弱🍨”的,那每次回收时就只关注少量存活就好了,就可以以较少的代价回收到大量空间。那根据强理论呢,如果有专门一块区域的绝大多数对象都是“顽固🍎”的,那虚拟机就可以以较低的频率进行垃圾回收,这就提高了内存的利用率。

那因为有了堆区域的划分,才有了垃圾回收类型的区分,比如:“MinorGC,MajorGC,FullGC ,之后才有了针对不同堆区域的对象特征相匹配的垃圾收集算法,比如:标记复制、标记清除、标记整理等。

那根据上述理论,我们现在的商用虚拟机的设计者,至少会把java堆分成young(新生代)区和Old(老年代)区,每次垃圾回收的时候,新生代中都会有大量对象死去,少量存活的会进入老年代,但不知道大家有没有疑问?分代收集就是这么简单划分一下内存嘛?那我要是遇到跨代引用该怎么处理呢?毕竟对象不是孤立的,相互之间会有联系。

那根据上面的情况看,如果我们在老年代中引入了年轻代的对象,那我为了留住该区域中存活的对象,我就得去老年代挨个问一下,来确保可达性分析效果的准确性,这种遍历我们是能做到的,只不过会给性能提升上带来很大的麻烦。

💚跨代引用

那我们必须要在前两条假说中再加一条:跨代引用假说,针对这一问题:我们首先就应该干掉跨代,将跨代变为同代,那怎么干掉呢?打颗栗子:新生代有一引用在老年代,由于存在老年代的对象都是顽固对象,那新生代的对象也不可能被回收,但是如果新生代的对象随着年龄增长进入老年代那跨代就消除了。那我们能不能这么搞一下,我们可以用一种数据结构(Remembered Set)来记住到底老年代哪块区域是被新生代引用的,这样当发生MinorGC时,我们只需要把这块区域扔给GCRoots进行扫描就欧克了,不用把整个老年代都交给它遍历。

内容很长对不对?最后我们来学学一些专有名词,放松一下:

  • MinorGC/YoungGC:目标是新生代的收集
  • MajorGC/OldGC: 目标是老年代的收集
  • FullGC :目标是整个堆和方法区
  • MixedGC:目标是新生代和部分老年代的收集,G1独有哦
  • PartialGC : 部分收集

💗题外话

昨天是七夕,我想谈谈我对爱的理解和看法,很多人单身,似乎都在等一种感觉,一种什么感觉呢?一种怦然心动的感觉,其实爱并不一定是要这种感觉,它更多的时候是一种责任,是一种陪伴,如果爱只是一份感觉,那这份感觉你从别处也能获得,这就是为什么好多移情别恋的人最好的说辞就是:我没有感觉了!实际上,陪伴才是最长情的告白。

记得小时候看过一个故事:有个男孩爱上了一个女孩,这个男孩把他的大金表给卖了,就为了换一个很好看的发夹,因为这女孩子有一身漂亮的长头发,他觉得:她带上发夹一定很好看。但是当他兴奋地把这个发夹交给女孩时,却发现女孩已经是短头发了。原来是女孩把长发卖了,只为了给男孩换个表带。

真正的爱一定不是瞬间的感动,而是长久的一种承诺,彼此牺牲,彼此尊重,彼此成就,愿天下有情人终成眷属!