如何理解Java的垃圾回收機制

Android性能調優之垃圾回收機制

本篇文章大概按照以下邏輯來講述

1.什麼是垃圾回收(GC)

2.垃圾回收機制對於我們來說有什麼好處?又有什麼缺點?

3.什麼時候會發生垃圾回收

4.垃圾回收它是如何工作的?

5.具體的回收方式和回收算法

6.OOM時如何調整

7.JVM 的內存劃分

技術詳情

1.什麼是垃圾回收(GC)

垃圾回收或GC(Garbage Collection),是一種自動的存儲管理機制,它是Java語言的一大特性,方便了我們這些程序員編碼,把內存釋放工作的壓力都轉讓到了系統,故而是以消耗系統性能爲代價的。

2.垃圾回收機制對於我們來說有什麼好處?又會帶來哪些坑?

以下我列舉一下系統自動垃圾回收給我們帶來的一些好處:

1.讓作爲程序員的我們專注於邏輯實現,提高了我們的編碼效率
2.能夠保護程序的完整性,垃圾回收是Java語言的安全策略的一個重要部分

但是隨之的,也會到來一些缺點:
1.系統層面負責垃圾回收,明顯會加大系統資源的開銷,從而影響程序的性能
2.垃圾回收機制也存在不完備性,並不能百分百保證回收所有的垃圾內存

3.什麼時候會發生垃圾回收

1.應用進程空閒的時候,GC會回收空閒進程的內存資源。
2.應用進程繁忙的時候,當需要的內存資源不足時,GC會強制執行回收優先級較低的進程資源,如果還是不足,再回收兩次,還是不足,就會報OOM。

4.垃圾回收它是如何工作的?

主要流程:根據一定的算法判斷某個對象是否存活,然後把判定是垃圾的對象進行回收。

GC的流程主要分爲以下幾種:
1.可回收對象的判定
2.通過某些算法垃圾回收

1.可回收對象的判定

可通過以下兩種方法判定對象是否可以回收:

1.1 引用計數算法
這種算法的工作原理是:
首先給每一個對象添加一個計數器
當程序的某一個地方引用了這個對象,計數器的值就加1
當引用失效時,計數器的值就減1
當某一個對象的計數器值爲0,則判定這個對象不可能被引用
這種算法對於系統來說比較簡單,高效,垃圾回收器運行較快,不需要長時間中斷我們程序的運行,缺點是很難處理循環引用,這就導致互相引用的對象無法被回收。

 OC(Objective-C)中的垃圾判定就是用的引用計數方法

1.2 GC Root可達性分析算法
這種算法的工作原理是:
以稱作“”GC Root”對象作爲起點向下搜索
每走過一個對象,就生成一條引用鏈
當GC Root不可到達對象時,這個對象就是不可用的,可回收

程序中能夠被用來當做GC Root對象的有:

1.虛擬機棧(棧幀中的本地變量表)中引用的對象

2.方法區中靜態屬性引用的對象

3.方法區中常量引用的對象

4.本地方法棧中JNI引用的對象

2.通過某些算法垃圾回收

以上內容講述了系統如何去判定某一個對象是否是垃圾,是否應該被回收。接着,當判定了某一個對象爲垃圾對象後,系統就要開始進行回收了,那麼系統的垃圾回收算法以下幾種:

  1. 標記清除算法
  2. 複製算法
  3. 標記整理算法
  4. 分代回收算法

2.1標記清除算法

先進行標記,然後進行清除
這個算法優點易於理解,容易實現,只需將特定地址的空間進行處理。
缺點,把整個區域弄得非常不完整,形成很多碎片化的內存,對於分配大內存的對象,
無法申請足夠的空間,再次觸發GC。

2.2複製算法

複製算法是對標記清除算法導致內存的碎片化的一個優化方案。原理如下:
1.複製算法將內存分爲A和B兩個區域
2.將A中存活的對象複製到B區域中
3.將A區域的所有對象都清除,這樣A區域就是一個完整的內存塊了,避免內存碎片化。
缺點是內存減半

2.3標記整理算法

是對於標記清楚的一個優化,原理如下:
1. 需要進行存活對象的標記
2. 存活的對象向一端移動,
3. 然後把另一端的內存進行清理
這個也能避免內存碎片化問題,但效率不怎樣,畢竟相對於複製算法,多了一步效率同樣較低的標記過程,而與標記清除算法相比,多了一步內存整理過程,效率上明顯更低。
適用於存活對象多,回收對象少的情況。

2.4分代回收算法

根據不同對象的不同特性,使用不同的算法進行處理,所以嚴格來講並不是一個新的算法,而是屬於一種算法整合方案,我們知道:
1. 複製算法適用於存活對象少,回收對象多的情況。
2. 標記整理算法適用於存活對象多,回收對象少的情況。

具體使用方式:
根據jvm特性:年輕代每次gc回收大部分對象,存活量較少,故用複製算法
年老代存活對象較多,且沒有其他內存爲年老代分配擔保,推薦標記整理算法

之前說的複製算法是將內存均分爲二,但是在分代回收中,並不是這樣,而是根據Eden:Survivor A:Survivor B= 8:1:1,具體的過程是:

1.新創建一個對象,默認是分在Eden區域,當Eden區域內存不夠的時候,會觸發一次Min
or GC(新生代回收),這次回收將存活的對象放到Survivor A區域,然後新的對象繼續放在Eden區域

2.再創建一個新的對象,要是Eden區域又不夠了,再次觸發Minor GC,這個時候會把Eden區域的存活對象以及
Survivor A區域的存活的對象移動到Survivor B區域,然後清空Eden區域以及Survivor A區域

3.如果繼續有新的對象創建,不斷觸發Minor GC,有些對象就會不斷在Survivor A區域以及Survivor B區域
來回移動,但移動次數超過15次後,這些對象就會被移動到老年代區域

4.如果新的對象在Minor GC後還是放不下,就直接放到老年代

5.如果Survivor區域放不下該對象,這直接放到老年代

6.如果老年代也滿了,就會觸發一次Full GC(major gc)

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章