今天,我整理了下学习jvm时的笔记,可能对初学jvm的程序猿有些帮助,所以把这篇文章分享给大家。
本文作者:吴明
大家好,我是吴明。这节课我给大家讲下,垃圾收集器。
大家先看一张图,图中是现在所有的垃圾收集器。
有同学看到这肯定要问:十个收集器,怎么学? 吴明老师 快划重点, 把没用的都划掉。
对不起,在座的收集器都是重点。
你是不是有了一种从入门到放弃的感觉。
不要慌。吴明老师告诉你们本次课程的第一个定律
定律1:所有的收集器都很像。
不要笑,我知道你心里在想什么。其实定律不一定高大上。这个定律太重要了,他直接告诉了大家一件事:你学会了1,2个收集器。所有的收集器你都学会了。
听到这里,准备放弃的同学纷纷表示,既然这样有了定律1那我就不放弃了,毕竟不抛弃不放弃是我军光荣传统。
这时,爱问问题的小灰同学,看定律1直接发了灵魂一问: 收集器都很相似,为什么还要这么多收集器?难道开发jvm的大佬也是混日子的。
回答这个问题,我们需要引出定律2
定律2:收集器的思想都来源于一个理论三个算法
而算法没有好坏,只有合适不合适,于是就衍生出了不同的收集器让大家在不同的情况下使用。
那么,我们就先了解一下,这 一个理论和三个算法。
分代收集理论
- 大多数的对象,存活时间都很短。这个第一个。
- 活的越久的对象,越不容易被回收。
非常的简单,就这么 两句话。大家可以默默读两遍
分代理论带给了我们哪些思考?
- 对象与对象是不同的,一类对象很快就可以被回收,另一类对象很久也不能回收。
- 不同对象,可以分类处理:使用不同的回收机制,不同的回收频率。
好,这个理论带给我们的启示够多了,下面我们去看三个算法。
三个算法
讲算法之前,我们先回顾一个经典笑话,把大象放冰箱,总共分几步。 第一步:打开冰箱门,第二步,把大象放进去,第三步,关上冰箱门。 学完三个算法,你会发现这个笑话简直就是算法模板。
难道sun公司的员工也喜欢看本山大叔的小品?
算法1:标记-清除算法。
第一步:把失效对象标记上。
第二步:把失效对象清除掉。
就这么两个步骤。我们来画个图。
图1:一块内存
图2:分配了几个对象
图3:标记上失效对象
图4:清除掉标记的对象
优点:基础算法,后面算法由它演变。 缺点:内存空间碎片,碎片多,大对象没有连续空间分配。
问题:算法1碎片的问题,该怎么解决好呢?请看算法2
算法2:标记-复制算法
背景动作:一块内存,平分成两半A和B。 第一步:把失效对象标记上 第二步:把存活对象复制到另一半空间 第三步把标记对象清除
其实这个名称,叫标记-复制-清除 也合适
老规矩,我们还是画图。
图1:两块内存
图2:分配几个对象
图3:标记上失效对象
图4:存活对象,复制到另一块内存上
图5:清除掉已经标记好的对象
优点:没有碎片,内存排列很整齐 缺点:
- 浪费一半内存
- 如果存活对象多,他还有第二个缺点, 复制过程很耗时间。
问题:算法2浪费一半内存的问题该怎么解决呢?看算法3
算法3:标记-整理算法
第一步:把失效对象标记上 第二步:把存活对象移动到空间的另一侧
第三步:把垃圾对象清理掉
还是画图:
图1:一块内存
图2:分配几个对象
图3:标记上失效对象
图4:存活对象,整理到内存的另一端去
图5:清除掉已经标记好的对象
优点:没有碎片,也没有复制算法那么浪费空间
缺点:算法2 如果存活对象多,耗费时间的时间问题依然没有解决。
好的,一个理论三个算法就聊到这里,下面我们说点题外话。
题外话
经验值(魔术数字): 前面讲了一个理论三个算法那, 这个分代理论来自哪里?他的依据是什么? IBM曾经给过一个数据:新生代中的对象98%熬不过第一轮收集。
98%,这个数字是完全精准的吗?不可能的。 你可以说是他一个统计数据,是一个概率,或者说他是一个经验值。
举个例子:有一天,产品经理走到你面前,小明,你对这个模块熟悉,你估一下这次开发的时间。你想了下说纯开发时间大概一周,这就是你的经验值。
这种经验值往往体现在一个数字上。还有哪些是经验值呢?
Young区Eden和Suvivor比例默认是8:1:1
HashMap,默认的初始化容量=16,为什么不是8 ,为什么不是1024呢?
这也是一个经验值,它没有太强的科学依据,是大家工作中的经验积累来的,是权衡各种情况的得失后最合适的选择。 一般我们在jdk和中间件代码里看到的默认值,这些魔术数字都是经验值。大家遇到了不必钻死牛角尖,为什么就是它,不是其他数字。经验而已。
最后,复习下本节课的内容。
精彩持续不断,请大家关注微信公众号:无名岛上