漫话:给女朋友解释GC如何判断什么东西可以回收?

漫小画

擅长漫话

程小员

擅长编程

周一晚上下班,我高高兴兴的回到家里面,女朋友蹦蹦跳跳的朝我跑过来,手里拿着扫把和拖布。这是又要打我么?我又做错了什么事情么?我大脑在高速旋转。这时,女朋友打破了沉默。

嗨,回来啦。诺,给你,我知道你最近在学习做家务。

《漫话:给女朋友解释GC如何判断什么东西可以回收?》

Execuse Me?我在学习做家务?开什么玩笑,我躲还来不及呢。

《漫话:给女朋友解释GC如何判断什么东西可以回收?》

唉,你就别谦虚啦。我今天帮你拿了一份快递,是一本书《垃圾回收的算法与实现》。

《漫话:给女朋友解释GC如何判断什么东西可以回收?》

额、你误会了,我要学的垃圾回收不是要做家务的意思。

《漫话:给女朋友解释GC如何判断什么东西可以回收?》

Garbage Collection,简称GC,中文名”垃圾回收”。是和计算机内存管理有关的概念,这里面的垃圾指的是程序不用的内存空间。

难道不是么?我说你怎么变得这么勤快了,那你顺便给我讲讲吧。

《漫话:给女朋友解释GC如何判断什么东西可以回收?》

好吧,那我们就从做家务开始说起吧。

《漫话:给女朋友解释GC如何判断什么东西可以回收?》

什么是垃圾回收

说到做家务,我们肯定不免要丢弃一些东西,说的文明一点叫断舍离,说的简单一点就是丢垃圾。

在现实世界中,说到垃圾,指的就是那些不读的书、不穿的衣服等。这种情况下的”垃圾”指的就是”自己不用的东西”。我们在整理家务的时候,一般是要做两件事,找到家里不用的垃圾,把这些垃圾丢弃,以便放一些其他的有用的东西。

映射到计算机系统中也一样,计算机的内存也是有限的,不可能把所有东西都一直存放在内存中,也需要定期释放不用的内存空间。而这些不用的内存空间中存放的东西就是垃圾了。在程序中,垃圾回收的过程就是找到内存空间中的垃圾,然后进行垃圾回收,让程序员能够再次利用这部分空间。

呵,这还需要专门买一本书来看么?直接打开电脑清理大师不就解决了么?

《漫话:给女朋友解释GC如何判断什么东西可以回收?》

额,这种工具确实可以帮助清理内存,但是他们是如何实现的才是我们关心的呀。

《漫话:给女朋友解释GC如何判断什么东西可以回收?》

什么样的东西算是垃圾

前面我们提到过,生活中的垃圾就是那些不用的东西。但是,『不用』这件事是如何确定的呢?

在日常做家务的时候,我们想要确定一个东西是否可以丢弃的时候,我们会有很多方法。

引用计数算法

第一种,我们在房间内找到一个感觉没什么用的usb线的时候,我们是这样判断他有没有用的:

1、看家里有没有可以用得上这个充电口的设备。

2、看家里有没有可以适配这个USB线的适配器。

如果有的话,那么我们就认为这根线是有用的,否则,这根USB线就会被我们标记为垃圾。等待被丢弃。

上面这种方式,在计算机的垃圾手机算法中叫做引用计数法,其算法过程是这样的:给对象中增加一个引用计数器,每当有一个地方引用他时,计数器就加1,当引用失效时,计数器值就减1。当执行垃圾回收时,只需要判断这个对象的引用计数器的数值是不是0就可以了。如果引用计数器数值为0,则表示可以回收。

这是一种比较简单的算法了,这种垃圾回收方式比较简单。

但是,这种丢垃圾的方式有一个缺点,那就是有可能效果不明显,就像我们想要丢弃一个USB线的时候,发现只有一个MP3可以使用他,然后,我们就把USB线保留下来了。当我们想要丢弃MP3的时候,发现家里还有一根USB线可以用到他,这样,MP3也被保留下来了。

但是,如果这个MP3和USB线根本就没有人想要用了呢?比如这个USB线和MP3是家里的某个客人留下的,他表示已经不需要了呢?

这就是引用计数法的缺点,就是如果存在循环引用对象,将导致无法回收。

嗯,这种方式确实挺笨的,但是谁会想不到MP3已经没有人使用了呢?

《漫话:给女朋友解释GC如何判断什么东西可以回收?》

哈哈,这里只是比喻嘛。如果你要想到MP3是不是还有人用,那就是另外一种算法啦。

《漫话:给女朋友解释GC如何判断什么东西可以回收?》

可达性分析算法

当然,日常生活中,我们判断一个东西还有没有用,不能仅仅看是不是有东西和他”配套”,还是要看家里人到底还用不用得到。

所以,比较靠谱一点的判断一个东西是不是垃圾的时候,我们会拿着一个东西,问一遍家里的所有成员:这东西你还需要吗?

如果得到的答案都是不需要的话,那就证明这个东西可以丢弃了。这样就避免了MP3和USB线被误保留的尴尬。

这种方式,就是从家庭成员出发,去判断一个东西到底有没有用。而不是从物品之间的相关关联关系来判断。

上面这种垃圾判断的方法,在计算机中叫做可达性分析算法,这个算法的基本思路是通过一系列的”GC Root”的对象作为起始点,从这些节点开始向下搜索,搜索所走过的路径成为引用链,当一个对象到GC Root没有任何引用链相连时,则证明此对象是不可用的。

一个物品,没有任何家庭成员宣布需要还要继续使用。就像一个对象,到达所有的”GC Root”都没有引用链是一样的。

在Java语言中,可以作为GC Root的对象包括以下几种:

1、虚拟机栈中引用的对象。

2、方法区中类静态属性引用的对象。

3、方法区中常量引用的对象。

4、本地方法栈中JNI引用的对象。

嗯,相比较来说,还是后面这种方法比较靠谱。

《漫话:给女朋友解释GC如何判断什么东西可以回收?》

是的。

《漫话:给女朋友解释GC如何判断什么东西可以回收?》

那知道哪些东西是不需要的了,是不是就可以直接扔了?

《漫话:给女朋友解释GC如何判断什么东西可以回收?》

这个倒也不一定呢。

《漫话:给女朋友解释GC如何判断什么东西可以回收?》

垃圾的宿命

一般情况下,我们对于一个家里面没用的东西处理,不太会果断的直接扔掉。有的时候对于一些有一定纪念意义的、或者比较贵重的东西会先保留一段时间,经过几次清理,还是觉得没用以后,才会被彻底扔掉。

其实,计算机的垃圾回收也是一样的。就算一个对象,通过可达性分析算法分析后,发现其是『不可达』的,也并不是非回收不可的。

一般情况下,要宣告一个对象死亡,至少要经过两次标记过程:

1、经过可达性分析后,一个对象并没有与GC Root关联的引用链,将会被第一次标记和筛选。筛选条件是此对象有没有必要执行finalize()方法。如果对象没有覆盖finalize()方法,或者已经执行过了。那就认为他可以回收了。如果有必要执行finalize()方法,那么将会把这个对象放置到F-Queue的队列中,等待执行。

2、虚拟机会建立一个低优先级的Finalizer线程执行F-Queue里面的对象的finalize()方法。如果对象在finalize()方法中可以『拯救』自己,那么将不会被回收,否则,他将被移入一个即将被回收的对象集合。

对象如何在finalize()中『拯救』自己呢?

最简单的方式就是重新简历引用,比如把自己赋值给某个类变量或者对象的成员变量。

好啦。我终于明白了。

《漫话:给女朋友解释GC如何判断什么东西可以回收?》

嗯,懂了就好,我不用收垃圾了吧。

《漫话:给女朋友解释GC如何判断什么东西可以回收?》

不不不,我已经帮你通过算法分析过了,门口那一堆都是可以回收的对象,你处理一下吧。

《漫话:给女朋友解释GC如何判断什么东西可以回收?》

额…

《漫话:给女朋友解释GC如何判断什么东西可以回收?》

漫话编程

微信:mhcoding

《漫话:给女朋友解释GC如何判断什么东西可以回收?》

让编程变得有乐趣

长按二维码关注

    原文作者:JVM
    原文地址: https://juejin.im/entry/5b70e0f0e51d456640284e1e
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞