周一晚上下班,我高高兴兴回家,女朋友蹦蹦跳跳地朝我跑过来,手里拿着扫把和拖把。这会不会又打我?我又做错什么了吗?我的大脑在高速旋转。这时,女朋友打破了沉默。
嗨,我回来了。给您我知道你最近在学做家务。
对不起?我在学做家务?你在开玩笑吗?我无法隐藏。
别谦虚了。今天给大家带来了一份快递,是一本《垃圾回收的算法与实现》的书。
你误会了。我想学的垃圾收集并不意味着做家务。
包包系列,简称GC,中文名& # 8221;垃圾回收& # 8221;。它是一个与计算机内存管理相关的概念,其中垃圾指的是程序未使用的空内存。
不是吗?我说你怎么变得这么勤奋了,所以请顺便告诉我一些事情。
好,让我们从做家务开始。
什么是垃圾收集?
说到家务,我们必须扔掉一些东西。说得文明一点,叫舍命;简单来说,就是扔垃圾。
现实世界中,说到垃圾,指的是没有读过的书和衣服。在这种情况下& # 8221;垃圾& # 8221;指& # 8221;你不需要的东西& # 8221;。做家务的时候,我们通常要做两件事:找到家里不用的垃圾,扔掉,这样我们就可以放一些其他有用的东西。
映射到计算机系统也是如此。电脑内存有限,不可能一直把所有东西都放在内存里,需要定期释放空未使用的内存。而存储在这些未使用的内存空房间里的都是垃圾。在程序中,垃圾收集的过程就是在内存的空房间中找到垃圾,然后进行垃圾收集,这样程序员就可以重用这部分空房间了。
哦,你需要买本书来读吗?只要打开电脑,清理主人。
嗯,这种工具确实可以帮助清理内存,但是如何实现才是我们关心的。
什么样的东西是垃圾?
正如我们前面提到的,生活中的垃圾是没有用过的东西。但是,“不需要”的事情是怎么确定的呢?
当我们想要确定某样东西是否可以在日常家务中丢弃时,我们有很多方法。
参考计数算法
首先,当我们在房间里发现一根感觉无用的u*电缆时,我们这样判断它是否无用:
1.看看家里有没有可以用这个充电口的设备。
2.看看家里有没有可以适配这条USB线的适配器。
如果有,那么我们认为这条电缆是有用的,否则,这条USB电缆会被我们标记为垃圾。等待被丢弃。
上述方法在电脑的垃圾手机算法中被称为引用计数法,其算法过程如下:给对象添加一个引用计数器,每当有对它的引用时,计数器就会递增1,当引用失败时,计数器值就会递减1。执行垃圾收集时,只需要判断这个对象的引用计数器的值是否为0。如果参考计数器值为0,则表示可以回收。
这是一个比较简单的算法,这种垃圾收集方法也比较简单。
但是这种扔垃圾的方式有一个缺点,那就是可能不太明显,就像我们想扔掉一根USB线的时候,发现只有一个MP3可以用,然后就留着USB线。当我们想丢弃MP3的时候,发现家里还有一根可以用的USB线,所以就保留了MP3。
但是如果根本没人想用这个MP3和USB线怎么办?比如这个USB线和MP3是一个客人留在家里的,他说已经不需要了。
这就是引用计数法的缺点,即如果有循环引用对象,会导致无法回收。
嗯,这种方式真的很蠢,但是谁能想到MP3已经不用了呢?
哈哈,这只是一个比喻。如果要思考MP3是否还在使用,那就是另一种算法了。
可达性分析算法
当然,在日常生活中,我们可以判断某样东西是否有用,不能只看某样东西是否和他在一起& # 8221;匹配& # 8221;,还是要看家人是否还需要它。
所以,在判断一个东西是不是垃圾的时候,比较靠谱的是,我们会拿着一个东西,再问一遍家里所有的人:你还需要这个东西吗?
如果所有的答案都是不必要的,那就证明这个东西是可以丢弃的。这样就避免了MP3和USB线缆被错误预留的尴尬。
这样,我们就可以从家庭成员那里判断某样东西是否有用。而不是从文章之间的相关性来判断。
上述垃圾判断方法在计算机中被称为可达性分析算法,该算法的基本思想是通过一系列& # 8221;GC根& # 8221;作为起点,从这些节点往下搜索,搜索的路径就变成了一条参考链。当一个对象没有通过任何引用链连接到GC根时,证明该对象不可用。
一件物品将继续使用,没有任何家庭成员声明它是必要的。就像一个物体,它触及所有& # 8221;GC根& # 8221;没有参考链是相同的。
在Java语言中,可以用作垃圾回收根的对象包括:
1.虚拟机堆栈中引用的对象。
2.方法区域中类静态属性引用的对象。
3.方法区域中常量引用的对象。
4.JNI在本地方法堆栈中引用的对象。
嗯,相比之下,后一种方法更可靠。
是
如果你知道你不需要什么,你能把它扔掉吗?
情况未必如此。
垃圾的命运。
在正常情况下,我们不太可能果断地扔掉家里无用的东西。有些时候,有一定纪念意义或者比较有价值的东西会保留一段时间。经过几次清洗,感觉还是没用,才会彻底扔掉。
其实电脑的垃圾收集也是一样的。即使通过可达性分析算法分析后发现一个对象是“不可达”的,也不需要回收。
一般来说,要宣布一个物体死亡,它必须经过至少两个标记过程:
1.可达性分析后,对象没有与GC Root关联的引用链,将被首次标记和过滤。筛选条件是此对象是否有必要执行finalize()方法。如果对象没有重写finalize()方法,或者它已经被执行。然后认为他可以回收它。如果需要执行finalize()方法,对象将被放在F-Queue的队列中,等待执行。
2.虚拟机建立一个低优先级的Finalizer线程来执行F-Queue中对象的finalize()方法。如果对象可以在finalize()方法中“保存”自己,它将不会被回收,否则,它将被移动到要回收的对象**中。
对象如何在finalize()中“保存”自己?
最简单的方法是重新建立引用,例如将自己分配给类变量或对象的成员变量。
好吧。我终于明白了。
很高兴知道。我不用收集垃圾。
不,不,我已经通过算法给你分析过了。门口堆的都是可回收物。请处理一下。
良好的..