1. 程式人生 > >Java垃圾回收器的工作原理

Java垃圾回收器的工作原理

上課,老師照本宣科,實在難以理解,乾脆就看書裡的Java書,正好看了Java的垃圾回收器是如何工作的,覺得有必要記錄一下。

參考於 Java程式設計思想第四版(Thinking in Java)

1.垃圾回收器對於提高物件的建立速度,有明顯的效果

  問題來了,垃圾回收是釋放物件,而關建立物件什麼事?

  首先了解一下Java是如何在堆上分配記憶體的,Java使用“堆指標”每分配一個物件,指標就往後移一位,類似於堆疊,這樣就達到了高速建立物件,但這樣的方法帶來了弊端,在堆疊中還可以出棧來釋放,在堆裡你沒有出棧啊,不一會堆(記憶體)就滿了,就要放磁碟上去,非常浪費時間。那麼這時候垃圾回收裝置就介入了,他幫助我們回收空間,並處理因為釋放物件而產生的碎片(因為有的物件可能比較小,釋放後就空了一塊記憶體,比如大小為5,但是其他物件的大小都在10以上,那麼這塊記憶體就是碎片了,別的物件根本就放不進去)。

  有了垃圾回收器,所以java才能使用“堆指標”來建立物件,所以說垃圾回收器對建立速度有明顯的效果 

2.Java垃圾回收器的具體機制

  2.1 引用計數法

    就是每個物件都有一個標誌,每次被引用1次就加1,如果引用為0,那麼就會去回收,但會有特殊情況,如果兩個物件在堆裡,互相引用,那麼使用這種方法就失效了,所以java中不用這種方法。

  2.2停止-複製(stop-and-copy)  和  標記-清掃(mark-and-sweep)

    這兩個思想是相同的,不同具體實現略有不同。這兩種方式需要程式暫停才能工作

    首先從堆疊或靜態儲存區開始,遍歷所有的引用,根據引用找到物件,在遍歷檢視找到物件中的引用,依次下去,這樣就避免的互相引用的問題,因為如果互相引用,那麼在堆疊中根本就不會出現

    停止-複製就是在開闢一個堆,然後把“活”的引用複製到堆中,不過開闢堆實在太浪費,感覺就在把一個堆劃分成不同的塊,在塊中複製。

    標記-清掃就是“活”的物件給個標記,先找出打好標記,然後在回收。

    Java虛擬機器可以自適應切換兩種方法,因為如果在很少需要回收的物件時,如果還使用停止-複製未免也太浪費了,如果一直用標記-清掃,那麼就會產生很多的碎片,有很多碎片的時候就用停止-複製,因為複製到另一個塊中,程式自然會去把物件排列好。

    注:如果一個大型物件佔了一個單獨的塊,那麼使用停止-複製的時候就不會複製,因為複製了也是一個一摸一樣的塊毫無意義。