小白学jvm系列-垃圾收集器前传

333 阅读5分钟

今天,我整理了下学习jvm时的笔记,可能对初学jvm的程序猿有些帮助,所以把这篇文章分享给大家。

本文作者:吴明

大家好,我是吴明。这节课我给大家讲下,垃圾收集器。

大家先看一张图,图中是现在所有的垃圾收集器。

有同学看到这肯定要问:十个收集器,怎么学? 吴明老师 快划重点, 把没用的都划掉。

对不起,在座的收集器都是重点

你是不是有了一种从入门到放弃的感觉。

不要慌。吴明老师告诉你们本次课程的第一个定律

定律1:所有的收集器都很像。

不要笑,我知道你心里在想什么。其实定律不一定高大上。这个定律太重要了,他直接告诉了大家一件事:你学会了1,2个收集器。所有的收集器你都学会了。

听到这里,准备放弃的同学纷纷表示,既然这样有了定律1那我就不放弃了,毕竟不抛弃不放弃是我军光荣传统。

这时,爱问问题的小灰同学,看定律1直接发了灵魂一问: 收集器都很相似,为什么还要这么多收集器?难道开发jvm的大佬也是混日子的。

回答这个问题,我们需要引出定律2

定律2:收集器的思想都来源于一个理论三个算法

而算法没有好坏,只有合适不合适,于是就衍生出了不同的收集器让大家在不同的情况下使用。

那么,我们就先了解一下,这 一个理论和三个算法。

分代收集理论

  1. 大多数的对象,存活时间都很短。这个第一个。
  2. 活的越久的对象,越不容易被回收。

非常的简单,就这么 两句话。大家可以默默读两遍

分代理论带给了我们哪些思考?

  • 对象与对象是不同的,一类对象很快就可以被回收,另一类对象很久也不能回收。
  • 不同对象,可以分类处理:使用不同的回收机制,不同的回收频率。

好,这个理论带给我们的启示够多了,下面我们去看三个算法。

三个算法

讲算法之前,我们先回顾一个经典笑话,把大象放冰箱,总共分几步。 第一步:打开冰箱门,第二步,把大象放进去,第三步,关上冰箱门。 学完三个算法,你会发现这个笑话简直就是算法模板。

难道sun公司的员工也喜欢看本山大叔的小品?

算法1:标记-清除算法。

第一步:把失效对象标记上。
第二步:把失效对象清除掉。

就这么两个步骤。我们来画个图。

图1:一块内存

图2:分配了几个对象

图3:标记上失效对象

图4:清除掉标记的对象

优点:基础算法,后面算法由它演变。 缺点:内存空间碎片,碎片多,大对象没有连续空间分配。

问题:算法1碎片的问题,该怎么解决好呢?请看算法2

算法2:标记-复制算法

背景动作:一块内存,平分成两半A和B。 第一步:把失效对象标记上 第二步:把存活对象复制到另一半空间 第三步把标记对象清除

其实这个名称,叫标记-复制-清除 也合适

老规矩,我们还是画图。

图1:两块内存

图2:分配几个对象

图3:标记上失效对象

图4:存活对象,复制到另一块内存上

图5:清除掉已经标记好的对象

优点:没有碎片,内存排列很整齐 缺点:

  1. 浪费一半内存
  2. 如果存活对象多,他还有第二个缺点, 复制过程很耗时间。

问题:算法2浪费一半内存的问题该怎么解决呢?看算法3

算法3:标记-整理算法

第一步:把失效对象标记上 第二步:把存活对象移动到空间的另一侧
第三步:把垃圾对象清理掉

还是画图:
图1:一块内存 图2:分配几个对象

图3:标记上失效对象

图4:存活对象,整理到内存的另一端去

图5:清除掉已经标记好的对象

优点:没有碎片,也没有复制算法那么浪费空间
缺点:算法2 如果存活对象多,耗费时间的时间问题依然没有解决。

好的,一个理论三个算法就聊到这里,下面我们说点题外话。

题外话

经验值(魔术数字): 前面讲了一个理论三个算法那, 这个分代理论来自哪里?他的依据是什么? IBM曾经给过一个数据:新生代中的对象98%熬不过第一轮收集。

98%,这个数字是完全精准的吗?不可能的。 你可以说是他一个统计数据,是一个概率,或者说他是一个经验值。

举个例子:有一天,产品经理走到你面前,小明,你对这个模块熟悉,你估一下这次开发的时间。你想了下说纯开发时间大概一周,这就是你的经验值。

这种经验值往往体现在一个数字上。还有哪些是经验值呢?
Young区Eden和Suvivor比例默认是8:1:1 HashMap,默认的初始化容量=16,为什么不是8 ,为什么不是1024呢?

这也是一个经验值,它没有太强的科学依据,是大家工作中的经验积累来的,是权衡各种情况的得失后最合适的选择。 一般我们在jdk和中间件代码里看到的默认值,这些魔术数字都是经验值。大家遇到了不必钻死牛角尖,为什么就是它,不是其他数字。经验而已。

最后,复习下本节课的内容。

精彩持续不断,请大家关注微信公众号:无名岛上