淺談對java-GC的理解
前段時間,一個線上專案忽然很卡,通過監控,發現記憶體很高,果不其然在幾個小時後,OOM。雖說有人很快處理好了。但我還是想站在我的角度,對這件事發表一下自己的觀點。
記憶體溢位,多發生在專案上線後,而且在系統開發階段和單元測試階段幾乎不被發現。這其實是和開發者習慣有關。譬如一些空的引用,就會佔著茅廁不拉屎等等
而要搞明白這個過程,不得不提一下java是如何管理記憶體的。主要涉及到物件的分配和釋放。
在java中,記憶體分配是由程式完成的,而釋放,是由垃圾回收機制自動完成的。
記憶體分配扯到各種new 物件,此處不多寫,主要談談GC過程 。
我用idea裝了Java VisualVM外掛 ,用自己的測試工程啟動後,可以看到這樣一個介面,說明外掛安裝成功,已經成功監視到我的工程
我不是來講這個外掛如何使用的,我本人也在學習階段,所以直接看本文重點
在我第一次看到這個圖的時候,恍然大明白,原來之前看的GC分割槽,就是這麼回事。但是過程是什麼樣的呢,就這個圖我做下說明(其實是我自己在網上整理了一下,然後講出來,加上自己的一些理解)
希望能對和我一樣曾經徘徊在GC門口的人一點幫助。
圖示,在整個GC過程中,大概有3個歷程。
Eden Space:新生
Old Gen:老年
Metaspace:持久代。持久好啊^_^
新生代和老年代之間,有2個Survivor區,圖裡面為S0,S1.這兩個作用是什麼,彆著急,咱一步步來,要有前戲。
首先當物件被建立的時候,new一個女朋友,是每個程式猿的夢想。但是在這裡,女朋友需要從相親物件不斷的跨越山河大海,才能成為女朋友,持續在一起。我開闢一個主任務(系統棧):我要相親,媒婆給我找一些相親物件來。於是乎,很多相親物件被new了出來,要大面撒網嘛。所以很多各種模樣的相親物件就排著隊進到Eden區,高的,矮的,胖的,瘦的,瓜子臉,O型腿,什麼樣的都有。
護衛何在,在。去把這些矮的,胖的,長相怪異的,都給我趕出門外,還有媒婆你下次挑的時候,長點眼睛。Eden:S區預設大小是8:1
於是一些看了一眼,甚至看都沒看一眼的垃圾物件被清了出去。剩下的,都還看的過去。全部給我去S0房間待著啊,進行第一輪考核。此刻S1是空的。
此時Eden房間已經閒置了,但是在整個專案執行期間,只要有人進行任何操作,都會不斷的有新物件進來到記憶體中。
所以Eden很快又滿了,在經歷了S0房間的篩選後,一些人由於思想問題,也要被趕出去,同時呢Eden這一批也有留下的,於是,S0剩下的和Eden剩下的,全都給我去S1待著去,那裡會繼續審查。為什麼這批S0的已經審查過了,還有繼續審查呢,那是因為現在網路這麼發達,太多東西都可以作假,一次可能瞞混過關,需要進行多次選擇。注意此刻S0是空的。(複製、引用計數法。Scavenge GC)
當這批S1的檢查完後,去掉一些家底不乾淨的,還留了一部分,而新的Eden依舊有一批篩選後的,這兩部分人,又全部進去S0再次給我檢查,身上有胎記的,毛太長的,有狐臭的等等都給我趕出去。此刻S1是空的。(複製、引用計數法。Scavenge GC)
當如此迴圈多次後,篩選來篩選後,發現某次S0或者S1擠滿了,不能再和新的Eden區剩下的人去擠進一個S房間了,系統就認為這批相親物件,質量很高(物件的引用一直存在),全部移步到Old Gen。此刻S0和S1空了,繼續和Eden進行新的迴圈。
此刻我來到Old Gen,開始逐個進行洗腦,這是個漫長的過程:因為要成為我的女朋友,要心甘情願的洗衣做飯暖床等等。過了很長一段時間的試戀愛後,Old Gen房間太滿了,而且還有很多不同意以上條件的美女們,我不能白養著啊,不合適就走吧,我不是慈善家。都走後門出去啊,別太惹人注目。
此處對應GC中,Eden和S區調整不能騰出足夠的空間時,要進行的FULL GC,此時JVM GC停止所有在heap中 執行的執行緒並執行清除動作。(標記壓縮-清除)
而經歷了多次FULL GC還留下的,我要把你們納入後宮,都去Metaspace吧。我在那裡等著你們。那裡有我喜歡的生活用品,交通工具等。幾乎不會改變,只會把一些舊的更換成新的。只要我有肉吃,就少不了你們的湯喝。
有幾個點需要強調一下,如果Eden中有極品美女,是可以直接進入到Old Gen的。對應一些大的物件,直接進老年代。
以上只是一些總結,隨著學習的深入,我會繼續補充。有寫錯的,歡迎在評論區糾正。哈哈,第一次寫這麼長。自我鼓勵一下