周一晚上,下班后,我高高兴兴地回到家,女朋友手里拿着扫把和拖把朝我跑过来。这是要再次打击我吗?我又做错什么了吗?我的大脑在高速旋转。这时,女朋友打破了沉默。
嗨,我回来了。给你,诺。我知道你最近在学做家务。

打扰一下。我在学做家务?你在开玩笑吗?对我来说藏起来已经太晚了。

好吧,别谦虚了。今天,我给你拿了一份快递。是一本书,垃圾收集的算法和实现。

你误会了。我想学的收垃圾,不是说做家务。

垃圾收集,简称GC,中文名& # 8221;垃圾收集& # 8221;。它是一个与计算机内存管理相关的概念。这里的垃圾是指程序未使用的内存空 room。
不是吗?说说你是怎么变得这么勤快的,那顺便说说吧。

好吧,先从家务说起。

什么是垃圾收集?
说到家务,我们肯定要扔掉一些东西。说文明点就是放弃自己的房子,说简单点就是扔掉垃圾。
在现实世界中,说到垃圾,指的是你不看的书,**的衣服。在这种情况下& # 8221;垃圾& # 8221;指& # 8221;你不需要的东西& # 8221;。我们做家务的时候,一般要做两件事,找到家里不用的垃圾,扔掉,以便放一些其他有用的东西。
映射到计算机系统也是一样。电脑的内存也是有限的。不可能一直把所有东西都存在内存里,不用的内存空 room需要定期释放。而这些不用的内存空 rooms里面存放的都是垃圾。在程序中,垃圾回收的过程是找到内存空中的垃圾,然后进行垃圾回收,这样程序员就可以重用空中的这部分。
哦,需要买专门的书看吗?你为什么不直接打开电脑清理一下主控?

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

什么样的东西是垃圾?
前面提到过,生活中的垃圾就是那些不用的东西。但是,“没用”这件事是怎么确定的呢?
当我们想要确定日常家务中某样东西是否可以丢弃时,我们有很多方法。
引用计数算法
首先,当我们在房间里发现一根感觉没用的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语言中,可以用作GC根的对象包括:
1.虚拟机堆栈中引用的对象。
2.方法区域中由类静态属性引用的对象。
3.方法区域中常量引用的对象。
4.JNI在本地方法堆栈中引用的对象。
嗯,相比较而言,后一种方法更可靠。

是

如果你知道你不需要什么,你能把它扔掉吗?

不一定是这样的。

垃圾的命运
一般情况下,我们不会果断扔掉家里没用的东西。有时候,一些有纪念意义或者有价值的东西,会保留一段时间,清洗几次,还是觉得没用之后,就彻底扔掉了。
其实电脑垃圾回收也是一样的。即使一个对象被可达性分析算法分析后发现“不可达”,也不一定要回收。
一般来说,要宣布一个物体死亡,至少要经过两个标记过程:
1.在可达性分析之后,一个对象没有与GC根相关联的引用链,并且将第一次被标记和过滤。过滤条件是该对象是否有必要执行finalize()方法。如果对象没有重写finalize()方法,或者它已经被执行。那我觉得他可以回收。如果需要执行finalize()方法,这个对象会放在F-Queue的队列中,等待执行。
2.虚拟机建立一个低优先级终结器线程来执行F队列中对象的Finalize()方法。如果对象能在finalize()方法中“保存”自己,就不会被回收;否则,它将被移动到要回收的对象**中。
对象如何在finalize()中“保存”自己?
最简单的方法是重新建立引用,比如将自己赋给一个类变量或者一个对象的成员变量。
好吧。我终于明白了。

很高兴知道。我不必收集垃圾。

不不不,我已经通过算法给你分析过了。门口那堆全是可回收的东西。请保管好它。

良好的..
