程序計數器、Java虛擬機棧、本地方法棧分配的內存是肯定的,生命週期與線程一樣。因此不需要過多考慮回收問題。算法
而Java堆和方法區僅僅有運行時才知道有哪些對象被建立,需要多少內存,這部分的內存分配和回收是動態的。數組
給對象加入引用計數器,有地方引用時+1,引用失效時-1。不論什麼時刻計數器爲0的對象就是不可能在被使用的。但是!markdown
不能解決對象間互相引用的問題,因此主流虛擬機不用這種方法。post
經過一系列稱爲「GCRoots」的對象做爲起始點,開始向下搜索,走過的路徑稱爲引用鏈,當一個對象到GCRoots沒有不論什麼引用鏈相連時,則該對象不可用。
可做爲GCRoots的對象包含:線程
至少要經歷兩次標記過程:指針
不論什麼對象的finalize()方法僅僅能被調用一次,因此第一次逃脫後第二次將沒法逃脫。對象
主要回收廢棄常量和沒用的類。生命週期
不足:隊列
將內存分爲相等大小的兩塊。每次僅僅使用當中一塊。當一塊用完時將活着的對象拷貝到還有一塊上面。而後一次清除使用過的那塊內存。圖片
長處:僅僅要移動堆頂指針。按順序分配內存就能夠。實現簡單。運行高效。
缺點:內存縮小爲原來的一半。在對象存活率高的時候不適用,適合新生代。
IBM策略:採用一個較大的Eden空間(80%)和兩個較小的Survivor空間(10%),每次使用Eden和一個Survivor。
適用於老年代,標記後讓所有存活的對象都向一端移動。而後直接清理掉端邊界之外的內存。
將Java堆分爲新生代和老年代。依據各個年代的特色採用最適合的收集算法。