給女朋友解釋GC如何判斷什麼東西可以回收

點擊上方"java全棧技術"關注,每天學習一個java知識點

週一晚上下班,我高高興興的回到家裡面,女朋友蹦蹦跳跳的朝我跑過來,手裡拿著掃把和拖布。這是又要打我麼?我又做錯了什麼事情麼?我大腦在高速旋轉。這時,女朋友打破了沉默。

嗨,回來啦。諾,給你,我知道你最近在學習做家務。

給女朋友解釋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如何判斷什麼東西可以回收


分享到:


相關文章: