一、首先什么是垃圾(garbage)?
沒有引用指向的一個或多個對象叫做垃圾;
二、如何找到這些垃圾
一般有兩種方法:
-
- 引用計數
- 根可達算法
1、第一種叫做引用計數法(reference count),有一個引用指向一個對象,計數就加1 ,直到這個數為0,就會被當作垃圾。
2、引用計數 不能解決一個問題(循環引用),如果根據引用計數法,這些都不是垃圾,可是沒有其他引用指向這一團,那他們就是一團垃圾;那么根可達算法就能夠解決,根可達算法的意思就是從根上開始搜索,
當一個程序啟動之后馬上需要的那些對象就叫做根對象,所謂的Root Searching是首先找到根對象,然后從根對象往下一直找,找到那些被引用的對象。
名詞解釋:
-
- 根可達算法:從根上對象開始搜索;
- 線程棧變量:一個main方法開始運行,main線程棧中的變量調用了其他方法,main棧中的方法訪問到的對象叫根對象;
- 靜態變量:T.class對靜態變量初始化能夠訪問到的對象叫做根對象;
- 常量池:如果一個class能夠用到其他class對象叫做根對象;
- JNI指針:如果調用了本地方法,本地的對象就叫做根對象;
- 根對象:一個程序啟動馬上用到的對象叫做根對象
三、GC Algorithms(常見的垃圾回收算法)
GC常用的算法有三個:
-
- Mark-Sweep(標記清除)
- Copying(拷貝)
- Mark-Compact(標記整理)
1、第一個是標記清除,就是把垃圾標記出來,然后把回收對象清理掉,就這么簡單,首先找到那些有用的,沒有用的標記出來然后清理掉。
標記清除算法有它自己的問題存在,我們從根找到了那些在用不可回收的,然后標記出可以回收的,清除之后就變成了空閑的,這種算法相對簡單,在存活對象較多的時候效率比較高,這種算法需要掃描兩遍,第一遍是找到那些有用的,第二遍是把那些沒有用的找出來然后清理掉,執行效率偏低,容易產生碎片。
2、第二個是復制(Copying)算法,非常簡單,就是把內容一分為二,把有用的拷貝到沒用的一邊,然后把剩下的全部清除,適用於存活對象較少的情況,只掃描一次,效率提高了很多而且沒有碎片產生,但是浪費空間,移動復制對象要調整對象的引用。
3、第三個是標記整理(標記壓縮)Mark-Compact 就是把所有對象整理的過程,清理的過程同時壓縮,有用的全部往前走,剩下的大片空間就清理出來了,空間連續而且沒有碎片。
標記整理算法依然有他的問題,在此過程中掃描兩次而且還需要移動對象,第一次先找出有用的 第二遍才開始移動,移動過程中如果是多線程還需要進行同步,效率上肯定是降低很多,但是不會產生碎片,方便對象分配,不會產生內存減半。