1. 程式人生 > >jvm垃圾回收是什麼時候觸發的? 垃圾回收演算法? 都有哪些垃圾回收器

jvm垃圾回收是什麼時候觸發的? 垃圾回收演算法? 都有哪些垃圾回收器

1.1。那究竟GC為我們做了什麼操作呢?

1 哪些記憶體需要回收?

2 什麼時候回收?

3 如何回收?

這時候有人就會疑惑了,既然GC 已經為我們解決了這個矛盾,我們還需要學習GC 麼?當然當然是肯定的,那究竟什麼時候我們還需要用到的呢

1 排查記憶體溢位

2 排查記憶體洩漏

3 效能調優,排查併發瓶頸

1.1.1。JVM怎麼判斷物件可以回收了?

我們知道,GC 主要處理的是物件的回收操作,那麼什麼時候會觸發一個物件的回收的呢?

1,物件沒有引用

2,作用域發生未捕獲異常

3,程式在作用域正常執行完畢

4,程式執行了System.exit()

5,程式發生意外終止(被殺程序等)

其實,我們最容易想到的就是當物件沒有引用的時候會將這個物件標記為可回收物件

,那麼現在就有一個問題,是不是這個物件被賦值為以後就一定被標記為可回收物件了呢

並不是這個物件被賦值為之後就一定被標記為可回收,有可能會發生逃逸!

1.2。下面我們來看一下幾種垃圾收集演算法

1.2.1。在JDK1.2之前,使用的是引用計數器演算法,

即當這個類被載入到記憶體以後,就會產生方法區,堆疊,程式計數器等一系列資訊,當建立物件的時候,為這個物件在堆疊空間中分配物件,同時會產生一個引用計數器,同時引用計數器1,當有新的引用的時候,引用計數器繼續1,而當其中一個引用銷燬的時候,引用計數器-1,當引用計數器被減為零的時候,標誌著這個物件已經沒有引用了,可以回收了!這種演算法在JDK1.2之前的版本被廣泛使用,但是隨著業務的發展,很快出現了一個問題

當我們的程式碼出現下面的情形時,該演算法將無法適應

a)ObjA.obj = ObjB

b)ObjB.obj - ObjA

這樣的程式碼會產生如下引用情形 objA 指向objB ,而objB 又指向objA ,這樣當其他所有的引用都消失了之後,objA objB 還有一個相互的引用,也就是說兩個物件的引用計數器各為1 ,而實際上這兩個物件都已經沒有額外的引用,已經是垃圾了。


1.2.2。根搜尋演算法

根搜尋演算法是從離散數學中的圖論引入的,程式把所有的引用關係看作一張圖,從一個節點GC ROOT 開始,尋找對應的引用節點,找到這個節點以後,繼續尋找這個節點的引用節點,當所有的引用節點尋找完畢之後,剩餘的節點則被認為是沒有被引用到的節點

,即無用的節點。


目前java 中可作為GC Root 的物件有

1,虛擬機器棧中引用的物件(本地變量表)

2,方法區中靜態屬性引用的物件

3,方法區中常量引用的物件

4,本地方法棧中引用的物件(Native Object)

1.2.3。        引用的分類

1,強引用

只要引用存在,垃圾回收器永遠不會回收

Objectobj = new Object();

// 可直接通過物鏡取得對應的物件obj.equels(NEWOBJECT());

而這樣 obj物件對後面newObject的一個強引用,只有當obj這個引用被釋放之後,物件才會被釋放掉,這也是我們經常所用到的編碼形式。

2、  軟引用

非必須引用,記憶體溢位之前進行回收,可以通過以下程式碼實現

Objectobj = new Object();

SoftReference<Object>sf = new SoftReference<Object>(obj);

obj =null;

sf.get();//有時候會返回null

這時候sf是對obj的一個軟引用,通過sf.get()方法可以取到這個物件,當然,當這個物件被標記為需要回收的物件時,則返回null軟引用主要使用者實現類似快取的功能,在記憶體足夠的情況下直接通過軟引用取值,無需從繁忙的真實來源查詢資料,提升速度;當記憶體不足時,自動刪除這部分快取資料,從真正的來源查詢這些資料。

3、  弱引用

第二次垃圾回收時回收,可以通過如下程式碼實現

Objectobj = new Object();

WeakReference<Object>wf = new WeakReference<Object>(obj);

obj =null;

wf.get();//有時候會返回null

wf.isEnQueued();//返回是否被垃圾回收器標記為即將回收的垃圾

弱引用是在第二次垃圾回收時回收,短時間內通過弱引用取對應的資料,可以取到,當執行過第二次垃圾回收時,將返回null

弱引用主要用於監控物件是否已經被垃圾回收器標記為即將回收的垃圾,可以通過弱引用的isEnQueued方法返回物件是否被垃圾回收器

4、  虛引用(幽靈/幻影引用)

垃圾回收時回收,無法通過引用取到物件值,可以通過如下程式碼實現

Objectobj = new Object();

PhantomReference<Object>pf = new PhantomReference<Object>(obj);

obj=null;

pf.get();//永遠返回null

pf.isEnQueued();//返回從記憶體中已經刪除

虛引用是每次垃圾回收的時候都會被回收,通過虛引用的get方法永遠獲取到的資料為null,因此也被成為幽靈引用。

虛引用主要用於檢測物件是否已經從記憶體中刪除。

1.3.         方法區也是會被回收的

!但是方法區的回收條件非常苛刻,只有同時滿足以下三個條件才會被回收!

1、所有例項被回收

2、載入該類的ClassLoader被回收

3Class物件無法通過任何途徑訪問(包括反射)

好了,我們現在切入正題,Java1.2之前主要通過引用計數器來標記是否需要垃圾回收,而1.2之後都使用根搜尋演算法來收集垃圾,而收集後的垃圾是通過什麼演算法來回收的呢?

1、    標記-清除演算法

2、    複製演算法

複製演算法採用從根集合掃描,並將存活物件複製到一塊新的,沒有使用過的空間中,這種演算法當控制元件存活的物件比較少時,極為高效,但是帶來的成本是需要一塊記憶體交換空間用於進行物件的移動。也就是我們前面提到的

s0 s1等空間。


3、    標記-整理演算法

我們來逐一過一下

1、    標記-清除演算法

標記-清除演算法採用從根集合進行掃描,對存活的物件物件標記,標記完畢後,再掃描整個空間中未被標記的物件,進行回收,如上圖所示。

標記-清除演算法不需要進行物件的移動,並且僅對不存活的物件進行處理,在存活物件比較多的情況下極為高效,但由於標記-清除演算法直接回收不存活的物件,因此會造成記憶體碎片!

2、    複製演算法


 複製演算法採用從根集合掃描,並將存活物件複製到一塊新的,沒有使用過的空間中,這種演算法當控制元件存活的物件比較少時,極為高效,但是帶來的成本是需要一塊記憶體交換空間用於進行物件的移動。也就是我們前面提到的

s0 s1等空間。

3、    標記-整理演算法


 標記

-整理演算法採用標記-清除演算法一樣的方式進行物件的標記,但在清除時不同,在回收不存活的物件佔用的空間後,會將所有的存活物件往左端空閒空間移動,並更新對應的指標。標記-整理演算法是在標記-清除演算法的基礎上,又進行了物件的移動,因此成本更高,但是卻解決了記憶體碎片的問題。

我們知道,JVM為了優化記憶體的回收,進行了分代回收的方式,對於新生代記憶體的回收(minor GC)主要採用複製演算法,下圖展示了minor GC的執行過程。

1.4.         下面我們來逐一介紹一下每個垃圾回收器。

1.4.1.    1、    Serial收集器

看名字我們都可以看的出來,這個屬於序列收集器。其執行示意圖如下


 Serial

收集器是歷史最悠久的一個回收器,JDK1.3之前廣泛使用這個收集器,目前也是ClientVM ServerVM 44GB以下機器的預設垃圾回收器。序列收集器並不是只能使用一個CPU進行收集,而是當JVM需要進行垃圾回收的時候,需要中斷所有的使用者執行緒,知道它回收結束為止,因此又號稱“Stop The World”的垃圾回收器。注意,JVM中文名稱為java虛擬機器,因此它就像一臺虛擬的電腦一樣在工作,而其中的每一個執行緒就被認為是JVM的一個處理器,因此大家看到圖中的CPU0CPU1實際為使用者的執行緒,而不是真正機器的CPU,大家不要誤解哦。

序列回收方式適合低端機器,是Client模式下的預設收集器,對CPU和記憶體的消耗不高,適合使用者互動比較少,後臺任務較多的系統。

Serial收集器預設新舊生代的回收器搭配為Serial+SerialOld

1.4.2.    2、    ParNew收集器

ParNew收集器其實就是多執行緒版本的Serial收集器,其執行示意圖如下

 

 同樣有

Stop The World的問題,他是多CPU模式下的首選回收器(該回收器在單CPU的環境下回收效率遠遠低於Serial收集器,所以一定要注意場景哦),也是Server模式下的預設收集器。

1.4.3.    3、    ParallelScavenge

ParallelScavenge又被稱為是吞吐量優先的收集器,器執行示意圖如下

 

 ParallelScavenge

所提到的吞吐量=程式執行時間/(JVM執行回收的時間+程式執行時間),假設程式運行了100分鐘,JVM的垃圾回收佔用1分鐘,那麼吞吐量就是99%。在當今網路告訴發達的今天,良好的響應速度是提升使用者體驗的一個重要指標,多核並行雲端計算的發展要求程式儘可能的使用CPU和記憶體資源,儘快的計算出最終結果,因此在互動不多的雲端,比較適合使用該回收器。

1.4.4.    4、    ParallelOld

ParallelOld是老生代並行收集器的一種,使用標記整理演算法、是老生代吞吐量優先的一個收集器。這個收集器是JDK1.6之後剛引入的一款收集器,我們看之前那個圖之間的關聯關係可以看到,早期沒有ParallelOld之前,吞吐量優先的收集器老生代只能使用序列回收收集器,大大的拖累了吞吐量優先的效能,自從JDK1.6之後,才能真正做到較高效率的吞吐量優先。其執行示意圖如下

 

1.4.5.     5、   SerialOld

SerialOld是舊生代Client模式下的預設收集器,單執行緒執行;在JDK1.6之前也是ParallelScvenge回收新生代模式下舊生代的預設收集器,同時也是併發收集器CMS回收失敗後的備用收集器。其執行示意圖如下

 

1.4.6.        6、CMS

CMS又稱響應時間優先(最短回收停頓)的回收器,使用併發模式回收垃圾,使用標記-清除演算法,CMSCPU是非常敏感的,它的回收執行緒數=CPU+3/4,因此當CPU2核的實惠,回收執行緒將佔用的CPU資源的50%,而當CPU核心數為4時僅佔用25%。他的執行示意圖如下


 CMS

模式主要分為4個過程


 在初始標記的時候,需要中斷所有使用者執行緒,在併發標記階段,使用者執行緒和標記執行緒

併發執行,而在這個過程中,隨著記憶體引用關係的變化,可能會發生原來標記的物件被釋放,進而引發新的垃圾,因此可能會產生一系列的浮動垃圾,不能被回收。

CMS 為了確保能夠掃描到所有的物件,避免在InitialMarking 中還有未標識到的物件,採用的方法為找到標記了的物件,並將這些物件放入Stack 中,掃描時尋找此物件依賴的物件,如果依賴的物件的地址在其之前,則將此物件進行標記,並同時放入Stack 中,如依賴的物件地址在其之後,則僅標記該物件。

在進行ConcurrentMarking minor GC 也可能會同時進行,這個時候很容易造成舊生代物件引用關係改變,CMS 為了應對這樣的並發現象,提供了一個Mod UnionTable 來進行記錄,在這個Mod Union Table中記錄每次minor GC 後修改了的Card 的資訊。這也是ParallelScavenge不能和CMS一起使用的原因。

CMS產生浮動垃圾的情況請見如下示意圖

 

在執行回收過後,c就變成了浮動垃圾。

由於CMS會產生浮動垃圾,當回收過後,浮動垃圾如果產生過多,同時因為使用標記-清除演算法會產生碎片,可能會導致回收過後的連續空間仍然不能容納新生代移動過來或者新建立的大資源,因此會導致CMS回收失敗,進而觸發另外一次FULL GC,而這時候則採用SerialOld進行二次回收。

同時CMS因為可能產生浮動垃圾,而CMS在執行回收的同時新生代也有可能在進行回收操作,為了保證舊生代能夠存放新生代轉移過來的資料,CMS在舊生代記憶體到達全部容量的68%就觸發了CMS的回收!

1.4.7.    7、    GarbageFirst(G1 )

我們再來看垃圾回收器的總圖,剛才我們可以看到,我在圖上標記了一個?,其實這是一個新的垃圾回收器,既可以回收新生代也可以回收舊生代,SunHotSpot1.6u14以上EarlyAccess版本加入了這個回收器,sun公司預期SunHotSpot1.7釋出正式版,他是商用高效能垃圾回收器,通過重新劃分記憶體區域,整合優化CMS,同時注重吞吐量和響應時間,但是杯具的是被oracle收購之後這個收集器屬於商用收費收集器,因此目前基本上沒有人使用,我們在這裡也就不多介紹,更多資訊可以參考oracle新版本JDK說明。

下面我們再來看下JVM的一些記憶體分配與回收策略

1、    優先在Edon上分配物件

 

 對於新生代和舊生代,

JVM可使用很多種垃圾回收器進行垃圾回收,下圖展示了不同生代不通垃圾回收器,其中兩個回收器之間有連線表示這兩個回收器可以同時使用。
 

 而這些垃圾回收器又分為序列回收方式、並行回收方式合併發回收方式執行,分別運用於不同的場景。如下圖所示

 

2    大物件直接進入老生代

3、    年長者(長期存活物件)進入老生代

4、    群體效應(大批中年物件進入老生代)

5、    擔保GC(擔保minorGC)

擔保GC 就是擔保minorGC 能夠滿足當前的儲存空間,而無需觸發老生代的回收,由於大部分物件都是朝生夕死的,因此,在實際開發中這種很起效,但是也有可能會發生擔保失敗的情況,當擔保失敗的時候會觸發FullGC ,但是失敗畢竟是少數,因此這種一般是很划算的
  

相關推薦

jvm垃圾回收是什麼時候觸發的? 垃圾回收演算法哪些垃圾回收

1.1。那究竟GC為我們做了什麼操作呢?1 ,哪些記憶體需要回收?2 ,什麼時候回收?3 ,如何回收?這時候有人就會疑惑了,既然GC 已經為我們解決了這個矛盾,我們還需要學習GC 麼?當然當然是肯定的,那究竟什麼時候我們還需要用到的呢?1 ,排查記憶體溢位2 ,排查記憶體洩漏

JVM哪些垃圾回收

# JVM 的垃圾回收器 [TOC] ## 經典垃圾收集器 > 如果說收集演算法是記憶體回收的方法論,那垃圾收集器就是記憶體回收的實踐者。 > 這些經典的收集器儘管已經算不上是最先進的技術,但他們曾在實踐中千錘百煉,足夠成熟。 ![HotSpot虛擬機器的垃圾收集器](h

jvm原始碼閱讀筆記[7]-從jstat -gccause命令談到jvm哪些GC cause

         大家都知道,當我們使用以下命令時,會打印出導致GC的原因 jstat -gccause pid 1000               可以看到最後2列分別列出了上次GC的原因和當前GC的原因。有一個”Heap Inspec

卸妝產品哪些

化妝品 卸妝油 植物油 苯甲醇 芝麻油 對於長期化妝的MM來說,粉底、眼影、唇彩等化妝品都含油脂成分,黏附於皮膚表面, 加上在外奔波一整天之後,臉上出現浮粉和卡粉,那是粉底顆粒混雜了空氣中的汙染物、細菌、黴菌、灰塵等等,所以卸妝不止是清潔步驟,更是護膚的重要環節,而卸妝需專用的卸妝用品、用

工傷保險待遇哪些類型

受傷 com 賬戶 2個 eba 自治區 想要 部門 .sh   工傷保險待遇都有哪些類型   工傷保險待遇包括:工傷醫療待遇、工傷津貼待遇、傷殘待遇、職業康復待遇、因工死亡待遇等。   1、 工傷醫療待遇——工傷職工在醫療期或醫療期滿仍需治療的,享受工傷醫療待遇工傷醫療待

SQL 查找存在某內容的存儲過程哪些

sys inf pro 哪些 存在 sch for object objects --查找存在某表名的存儲過程 SELECT distinct b.name from syscomments a,sysobjects b WHERE a.id=b.id and a.TEX

大公司的PMO哪些角色

很多大公司已經有了自己成熟的項目管理體系了。對應這些管理體系需要建立與其相適應的PMO,這樣子,才能讓企業在線新的管理模式更好的發展下去。那麽,大公司的PMO都有哪些角色呢?對於一些職能型大公司想要引入項目管理理念,不妨先了解清楚PMO都有哪些角色吧。 企業實施項目管理戰略規劃,建立項目管理

雲主機哪些參數?

文件 友好 選擇 比較 硬盤 下載 根據 體驗 而且 雲服務器因為其管理簡單、操作方便的特點,受到很多企業的青睞。購買雲服務器不需要提前購買硬件,而且在使用過程更穩定、更安全,但是也有一個問題,客戶在購買的時候,不知道該怎麽選擇雲主機的配置,下面我們就一起倆看一下如何選擇雲

申請 ISO9001認證的基本條件和材料 哪些

tex blog 機構 積極 創業 好處 條件 服務 col 對於ISO9001認證的好處有如下這些,今天呢,我就來說說申請ISO9001 的基本條件和申請材料。 1、通過認證使企業具有了走向市場的通行證。2、增進國際貿易,消除技術壁壘,與國際先進管理慣例接軌,融入一體化國

聚客優盟跟你講不起眼利潤高的行業哪些,

更多 營業額 們的 一次 時間 發現 好項目 好的 ref 現在市場上隱藏著很多比較低調的加盟項目,為什麽說他們低調。加盟費用低,利潤卻高的很。當然最常見的就是街邊的燒烤、臭豆腐、炸土豆的等等,一年的時間幹的好的話,估計買套房沒什麽大問題,就算幹得不好也有幾萬或者是幾萬保底

MySQL哪些日誌?分別代表什麽?

mysql日誌MySQL日誌:主要包含:錯誤日誌、查詢日誌、慢查詢日誌、事務日誌、二進制日誌、中繼日誌;日誌是mysql數據庫的重要組成部分。日誌文件中記錄著mysql數據庫運行期間發生的變化;也就是說用來記錄mysql數據庫的客戶端連接狀況、SQL語句的執行情況和錯誤信息等。當數據庫遭到意外的損壞時,可以通

Spring Boot 2.0(三):Spring Boot 開源軟件哪些

Spring Boot 開源 2016年 Spring Boot 還沒有被廣泛使用,在網上查找相關開源軟件的時候沒有發現幾個,到了現在經過2年的發展,很多互聯網公司已經將 Spring Boot 搬上了生產,而使用 Spring Boot 的開源軟件在 Github/碼雲 上面已有不少,這篇文章就給大

知識產權貫標對於企業和消費者哪些影響和好處?

知識產權貫標 高新技術企業 專利申請經濟全球化的快速推進,知識產權不再僅僅是激勵創新的一種工具,而已經成為了一個企業、一個國家的一種重要的戰略資源,全球化的市場環境倒閉意味著我們國內的企業必須更加重視對知識產權的有限管理。 知識產權管理體系的建立,有助於實現企業的可持續發展。知識產權管理有助於將組織中只可以

公交站臺哪些設計風格

公交站臺一、現代候車亭 現代,顧名思義就是時下、當下。現代候車亭,就是符合現在當代潮流、審美乃至需求的公共交通公交站臺。現代公交候車亭的款式多樣、規格均可定制、附加功能多有太陽能、智能、電子語音播報、LED 、滾動燈箱等。現代公交站臺隨著發展,隨著科技,逐漸切合並融入人們的生活。二、仿古候車亭 仿

Java代碼優化,哪些常用方法?

Java開發 Java學習 Java代碼優化 Java代碼優化是Java編程開發很重要的一個步驟,Java代碼優化要註重細節優化,一個兩個的細節的優化,產生的效果不大,但是如果處處都能註意代碼優化,對代碼減少體積、提高代碼運行效率是有巨大幫助的,還能在一定程度上避免未知錯誤,常用的Java代碼優化

中國化的 P2P 金融哪些特色?

中國化 P2P 金融 特色 P2P金融又叫P2P信貸,是互聯網金融(ITFIN)的一種。意思是:點對點。  P2P金融指不同的網絡節點之間的小額借貸交易,需要借助電子商務專業網絡平臺幫助借貸雙方確立借貸關系並完成相關交易手續。借款者可自行發布借款信息,包括金額、利息、還款方式和時間,自行決定借出金

Python的性能如何? 來看看全球哪些頂級的公司在使用Python

Python用途 Python的未來 Python就業前景 大家可以關註公眾號:Python從程序猿到程序員目前有超過500種編程語言,每天仍在新增更多新語言。雖然其中有大部分重疊的語言以及大量僅用於理論和試驗的編程語言。但你必須選擇一種作為日常工作生活常用的編程語言。你應該學習哪些語言,為什麽你

學物聯網和嵌入式好不好?哪些課程?

雲計算?學物聯網和嵌入式好不好?都有哪些課程?物聯網是嵌入式發展的一個方向但是個人覺得物聯網的前景發展要稍微好一些,畢竟現在智能家居、智能生活這麽受人追捧,而且也是今後生活的大方向建議題主可以考慮學習物聯網物聯網主要學習以下這些東西: 階段一 - 學前準備: 嵌入式C語言高級—語法概述 嵌入式C語言高級—內存

各大公司官網哪些顯而易見的Bug?

軟件測試 測試管理 Bug報告 缺陷報告 官網漏洞 備註:以下(一-五)均為PC端網站復現的問題~~(六)為移動客戶端問題~! 一.QQ郵箱-定時發送功能。選擇“年”時只能逐年選擇。如:不可以直接選擇到2028年。 操作步驟: 1.進入QQ郵箱,錄入好發件人、主題等信息 2.點擊“定時發送

準備從完美英傑學習VR開發哪些就業方向

同時 unit 理想 dsm 有理 教師 培養 code 入學 隨著VR的發展,越來越多人對VR感興趣,希望進入VR行業,VR成就一番夢想。想要成為一名有理想的VR從業者,有哪些選擇?通過VR培訓出來後,VR有哪些就業方向呢 如果你是一個技術型人才,還具