成人国产在线小视频_日韩寡妇人妻调教在线播放_色成人www永久在线观看_2018国产精品久久_亚洲欧美高清在线30p_亚洲少妇综合一区_黄色在线播放国产_亚洲另类技巧小说校园_国产主播xx日韩_a级毛片在线免费

資訊專欄INFORMATION COLUMN

《深入理解Java虛擬機(jī)》(三)垃圾收集器與內(nèi)存分配策略

Edison / 1606人閱讀

摘要:當(dāng)兩個(gè)對(duì)象相互引用時(shí),這兩個(gè)對(duì)象就不會(huì)被回收引用計(jì)數(shù)算法不被主流虛擬機(jī)采用,主要原因是它很難解決對(duì)象之間相互循環(huán)引用的問題。

垃圾收集器與內(nèi)存分配策略 詳解 3.1 概述

本文參考的是周志明的 《深入理解Java虛擬機(jī)》第三章 ,為了整理思路,簡(jiǎn)單記錄一下,方便后期查閱。

3.2 對(duì)象已死嗎

在垃圾收集器進(jìn)行回收前,第一件事就是確定這些對(duì)象哪些還存活,哪些已經(jīng)死去。

3.2.1 引用計(jì)數(shù)算法

在對(duì)象中添加一個(gè)引用計(jì)數(shù)器,每當(dāng)有一個(gè)地方引用它時(shí),計(jì)數(shù)器就加1;當(dāng)引用失效時(shí),計(jì)數(shù)器減1;其中計(jì)數(shù)器為0的對(duì)象是不可能再被使用的已死對(duì)象。

當(dāng)兩個(gè)對(duì)象相互引用時(shí),這兩個(gè)對(duì)象就不會(huì)被回收

引用計(jì)數(shù)算法,不被主流虛擬機(jī)采用,主要原因是它很難解決對(duì)象之間相互循環(huán)引用的問題。

3.2.2 可達(dá)性分析算法

通過一系列的稱為GC Roots的對(duì)象作為起始點(diǎn),從這些節(jié)點(diǎn)開始向下搜索,搜索所經(jīng)過
的路徑稱為引用鏈(Reference Chain),當(dāng)一個(gè)對(duì)象到GC Roots沒有任何引用鏈相連(在圖論中稱為對(duì)象不可達(dá))時(shí),這個(gè)對(duì)象就是不可用的。

圖片來源于網(wǎng)絡(luò)如有侵權(quán)請(qǐng)私信刪除

在java語言中,可作為GC Roots的對(duì)象包括:

虛擬機(jī)棧(棧幀中的本地變量表)中引用的對(duì)象

方法區(qū)中類靜態(tài)屬性引用的對(duì)象

方法區(qū)中常量引用的對(duì)象

本地方法棧中JNI引用的對(duì)象

3.2.3 引用的分類

java的引用可以分為強(qiáng)引用、軟引用、弱引用、虛引用:

強(qiáng)引用:是指在程序代碼中直接存在的引用,譬如引用new操作符創(chuàng)建的對(duì)象。只要強(qiáng)引用還存在,垃圾收集器就永遠(yuǎn)不會(huì)回收掉被引用的對(duì)象。

軟引用:還有用但是并非必需的引用,早系統(tǒng)將要發(fā)生內(nèi)存溢出異常之前會(huì)把這些對(duì)象列進(jìn)回收范圍中進(jìn)行二次回收,若還是沒有足夠的內(nèi)存,才會(huì)拋出內(nèi)存溢出異常。

弱引用:非必需的對(duì)象,只能生存到下一次垃圾收集發(fā)生之前。當(dāng)垃圾收集器工作時(shí),無論內(nèi)存是否夠用都將回收這些對(duì)象。

虛引用:一個(gè)對(duì)象是否有虛引用的存在完全不會(huì)對(duì)他的生存時(shí)間構(gòu)成影響,也無法通過虛引用來取得一個(gè)對(duì)象實(shí)例。

圖片來源于網(wǎng)絡(luò)如有侵權(quán)請(qǐng)私信刪除
3.2.4 宣告一個(gè)對(duì)象死亡的過程

要真正宣告一個(gè)對(duì)象死亡,至少要經(jīng)歷兩次標(biāo)記過程:

若對(duì)象在進(jìn)行可達(dá)性分析后發(fā)現(xiàn)沒有與GC Roots相連接的引用鏈,會(huì)被 第一次標(biāo)記 并且進(jìn)行一次篩選。篩選的條件是此對(duì)象是否有必要執(zhí)行finalize()方法(如當(dāng)對(duì)象沒有重寫finalize()方法或者finalize()方法已經(jīng)被虛擬機(jī)調(diào)用過則認(rèn)為沒有必要執(zhí)行)。

如果有必要執(zhí)行則將該對(duì)象放置在F-Queue隊(duì)列中,并在稍后由一個(gè)由虛擬機(jī)自己建立的、低優(yōu)先級(jí)的Finalizer線程去執(zhí)行它;稍后GC對(duì)F-Queue中的對(duì)象進(jìn)行第二次標(biāo)記,如果對(duì)象還是沒有被引用,則會(huì)被回收。

但是作者不建議通過finalize()方法“拯救”對(duì)象,因?yàn)樗\(yùn)行代價(jià)高、不確定性大、無法保證各個(gè)對(duì)象的調(diào)用順序。

圖片來源于網(wǎng)絡(luò)如有侵權(quán)請(qǐng)私信刪除

3.2.5 回收方法區(qū)

很多人認(rèn)為方法區(qū)(HotSopt中的永久代)是沒有垃圾收集的,java虛擬機(jī)規(guī)范中也沒有要求需要對(duì)方法區(qū)實(shí)現(xiàn)垃圾收集。

永久代(方法區(qū))的垃圾收集主要回收兩部分內(nèi)容:廢棄常量和無用的類

廢棄常量:假如一個(gè)字符串“abc”已經(jīng)進(jìn)入了常量池中,但是當(dāng)前系統(tǒng)沒有任何一個(gè)String對(duì)象是叫 做“abc”的,換句話說,就是沒有任何String對(duì)象引用常量池中的“abc”常量,也沒有其他 - 地方引用了這個(gè)字面量,如果這時(shí)發(fā)生內(nèi)存回收,而且必要的話,這個(gè)“abc”常量就會(huì)被系 - 統(tǒng)清理出常量池。

無用的類:同時(shí)滿足下面3個(gè)條件的類(實(shí)例、類加載器被回收,java.lang.Class對(duì)象沒有被引用)。

該類所有的實(shí)例都已經(jīng)被回收,也就是Java堆中不存在該類的任何實(shí)例。

加載該類的ClassLoader已經(jīng)被回收。

該類對(duì)應(yīng)的java.lang.Class對(duì)象沒有在任何地方被引用,無法在任何地方通過反射訪問該類的方法。

3.3 垃圾收集算法 3.3.1 標(biāo)記-清除算法 (Mark-Sweep)

算法分為兩個(gè)階段:標(biāo)記和清除

標(biāo)記:首先標(biāo)記所有需要回收的對(duì)象
清除:在標(biāo)記完成后統(tǒng)一回收所有被標(biāo)記的對(duì)象

標(biāo)記過程在上文宣告一個(gè)對(duì)象死亡過程中提及

缺點(diǎn)

效率問題,標(biāo)記和清除兩個(gè)過程的效率都不高(回收后空間碎片過多,再次回收(即可達(dá)性分析時(shí))有時(shí)需要遍歷整個(gè)內(nèi)存區(qū)域)。

空間問題,標(biāo)記清除之后會(huì)產(chǎn)生大量不連續(xù)的內(nèi)存碎片,空間碎片太多可能會(huì)導(dǎo)致以后在程序運(yùn)行過程中需要分配較大對(duì)象時(shí),無法找到足夠的連續(xù)內(nèi)存,而不得不提前觸發(fā)另一次垃圾收集動(dòng)作。

圖片來源于網(wǎng)絡(luò)如有侵權(quán)請(qǐng)私信刪除
3.3.2 復(fù)制算法(新生代算法)(Copying)

思路:將可用內(nèi)存按容量分為兩個(gè)塊,每次只用其中之一。當(dāng)這一塊內(nèi)存用完之后,將還存活的對(duì)象復(fù)制到另一邊去,然后清除所有已經(jīng)使用過的部分。

優(yōu)點(diǎn)

每次都是對(duì)整個(gè)半?yún)^(qū)進(jìn)行內(nèi)存回收,內(nèi)存分配時(shí)也就不用考慮內(nèi)存碎片等復(fù)雜情況,只要移動(dòng)堆頂指針,按順序分配內(nèi)存即可,實(shí)現(xiàn)簡(jiǎn)單,運(yùn)行高效。

缺點(diǎn)

代價(jià)是將內(nèi)存縮小為了原來的一半,未免太高了一點(diǎn)。

解決方法

新生代中的對(duì)象98%是“朝生夕死”的,所以并不需要按照1:1的比例來劃分內(nèi)存空間,而是將內(nèi)存分為一塊較大的Eden空間和兩塊較小的Survivor空間,每次使用Eden和其中一塊Survivor。

在HotSpot里,考慮到大部分對(duì)象存活時(shí)間很短將內(nèi)存分為Eden和兩塊Survivor,默認(rèn)比例為8:1:1。代價(jià)是存在部分內(nèi)存空間浪費(fèi),適合在新生代使用。

圖片來源于網(wǎng)絡(luò)如有侵權(quán)請(qǐng)私信刪除
3.3.3 標(biāo)記-整理算法(老年代算法)(Mark-Compact)

標(biāo)記過程仍然與“標(biāo)記-清除”算法一樣,但后續(xù)步驟不是直接對(duì)可回收對(duì)象進(jìn)行清理,而是讓所有存活的對(duì)象都向一端移動(dòng),然后直接清理掉端邊界以外的內(nèi)存。

圖片來源于網(wǎng)絡(luò)如有侵權(quán)請(qǐng)私信刪除

3.3.4 分代收集算法

當(dāng)前商用虛擬機(jī)都采用了這種算法,根據(jù)對(duì)象的存活周期將內(nèi)存劃分為幾塊,一般是把Java堆分為新生代和老生代,根據(jù)各個(gè)年代采用適當(dāng)?shù)氖占惴?/strong>。

新生代一般采用復(fù)制算法(Copying)

老生代一搬采用 標(biāo)記-清理(Mark-Sweep) 或者標(biāo)記-整理(Mark-Compact) 進(jìn)行回收。

3.4 hotspot的算法實(shí)現(xiàn) 3.4.1 枚舉根節(jié)點(diǎn)

可達(dá)性分析的缺點(diǎn)

GC Roots節(jié)點(diǎn)找引用鏈這個(gè)操作為例,可作為GC Roots的節(jié)點(diǎn)主要在全局性的引用(例如常量或類靜態(tài)屬性)與執(zhí)行上下文(例如棧幀中的本地變量表)中,現(xiàn)在很多應(yīng)用僅僅方法區(qū)就有數(shù)百兆,如果要逐個(gè)檢查這里面的引用,那么必然會(huì)消耗很多時(shí)間。

由于要確保在一致性的快照中進(jìn)行可達(dá)性分析,從而導(dǎo)致GC進(jìn)行時(shí)必須要停頓所有Java執(zhí)行線程;

目前主流的Java虛擬機(jī)使用的都是準(zhǔn)確式GC,當(dāng)執(zhí)行系統(tǒng)停頓下來后并不需要一個(gè)不漏的檢查完所有執(zhí)行上下文和全局的引用變量,虛擬機(jī)應(yīng)當(dāng)有辦法直接得知哪些地方存著對(duì)象的引用

HotSpot使用一組稱為OopMap的數(shù)據(jù)結(jié)構(gòu)**來記錄哪些地方存著對(duì)象的引用

在類加載過程中,HotSpot就把對(duì)象內(nèi)什么偏移量上是什么類型的數(shù)據(jù)計(jì)算出來,在JIT編譯過程中會(huì)在特定的位置記錄下棧和寄存器中哪些位置是引用

判斷對(duì)象引用

類加載時(shí),使用OopMap的數(shù)據(jù)結(jié)構(gòu)

JIT編譯時(shí)特定記錄

3.4.2 安全點(diǎn)

HotSpot沒有為每條指令都生成OopMap,只是在特定位置記錄了這些信息,這些位置稱為安全點(diǎn)。

即程序執(zhí)行時(shí)并非在所有地方都能停頓下來開始GC,只有到達(dá)安全點(diǎn)時(shí)才能暫停。

對(duì)于安全點(diǎn)基本上是以程序是否具有讓程序長時(shí)間執(zhí)行的特征(比如方法調(diào)用、循環(huán)跳轉(zhuǎn)、異常跳轉(zhuǎn)等)為標(biāo)準(zhǔn)進(jìn)行選定的。

另外還需要考慮如果在GC時(shí)讓所有線程都跑到最近的安全點(diǎn)上,有兩種方案:搶先式中斷和主動(dòng)式中斷;

搶先式中斷

不需要線程的執(zhí)行代碼主動(dòng)去配合,在GC發(fā)生時(shí),首先把所有線程全部中斷,如果發(fā)現(xiàn)有線程中斷的地方不在安全點(diǎn)上,就恢復(fù)線程,讓它“跑”到安全點(diǎn)上。 現(xiàn)在幾乎沒有虛擬機(jī)實(shí)現(xiàn)采用搶先式中斷來暫停線程從而響應(yīng)GC事件。

主動(dòng)式中斷

當(dāng)GC需要中斷線程的時(shí)候,不直接對(duì)線程操作,僅僅簡(jiǎn)單地設(shè)置一個(gè)標(biāo)志,各個(gè)線程執(zhí)行時(shí)主動(dòng)去輪詢這個(gè)標(biāo)志,發(fā)現(xiàn)中斷標(biāo)志為真時(shí)就自己中斷掛起。輪詢標(biāo)志的地方和安全點(diǎn)是重合的,另外再加上創(chuàng)建對(duì)象需要分配內(nèi)存的地方。

兩者的區(qū)別在于,搶先式中斷是無論如何都進(jìn)行中斷,而主動(dòng)式中斷則是線程執(zhí)行輪詢標(biāo)志查看是否中斷

3.4.3 安全區(qū)域

為了處理不執(zhí)行的程序的安全點(diǎn)問題,提出了安全區(qū)域來解決問題。

安全區(qū)域是指在一段代碼片段之中,引用關(guān)系不會(huì)發(fā)生變化,在這個(gè)區(qū)域內(nèi)的任何地方進(jìn)行GC都是安全的。

虛擬機(jī)如個(gè)具體的進(jìn)行內(nèi)存回收是由虛擬機(jī)所采用的GC收集器決定的,而通常虛擬機(jī)中往往不止有一種GC收集器。

線程執(zhí)行到安全區(qū)域時(shí),首先標(biāo)識(shí)自己已經(jīng)進(jìn)入了安全區(qū)域,這樣JVMGC時(shí)就不管這些線程了。

3.5 垃圾收集器

如果說收集算法是內(nèi)存回收的方法論,那么垃圾收集器就是內(nèi)存回收的具體實(shí)現(xiàn)。

不同的收集器應(yīng)用的區(qū)域不同,到現(xiàn)在為止沒有最好的收集器,也沒有萬能的收集器。

3.5.1 serial收集器

Serail 收集器是單線程的,他在進(jìn)行垃圾收集時(shí)必須暫停其他的所有線程,直到收集結(jié)束。

隨著收集器的發(fā)展,用戶線程的停頓時(shí)間越來越段,但任然無法消除。

Serial收集器是虛擬機(jī)運(yùn)行在Client模式下默認(rèn)的新生代收集器

對(duì)于單個(gè)CPU壞境來說,Serial收集器**由于沒有線程交互的開銷,專心做垃圾收集,可以獲得很高的單線程收集效率。

圖片來源于網(wǎng)絡(luò)如有侵權(quán)請(qǐng)私信刪除
3.5.2 parnew收集器

ParNew收集器是Serial收集器的多線程版本

ParNew收集器是運(yùn)行在Server模式下虛擬機(jī)中首選的新生代收集器

在垃圾收集器中并發(fā)并行的概念:

并行:多條垃圾收集線程并行工作,但此時(shí)用戶線程仍然處于等待狀態(tài)。

并發(fā):用戶線程與垃圾收集線程同時(shí)執(zhí)行(但不一定是并行的,可能會(huì)交替執(zhí)行),用戶程序在繼續(xù)運(yùn)行,而垃圾收集程序運(yùn)行在另一個(gè)CPU上。

圖片來源于網(wǎng)絡(luò)如有侵權(quán)請(qǐng)私信刪除
3.5.3 parallel scavenge收集器

新生代收集器,使用復(fù)制算法,并行的多線程收集器;

與其他收集器關(guān)注于盡可能縮短垃圾收集時(shí)用戶線程停頓時(shí)間不同,它的目標(biāo)是達(dá)到一個(gè)可控制的吞吐量。

吞吐量就是CPU用于運(yùn)行用戶代碼的時(shí)間與CPU總消耗時(shí)間的比值,即吞吐量=運(yùn)行用戶代碼時(shí)間/(運(yùn)行用戶代碼時(shí)間+垃圾收集時(shí)間),虛擬機(jī)總共運(yùn)行了100分鐘,其中垃圾收集花掉1分鐘,那吞吐量就是99%。

高吞吐量可以高效的利用CPU時(shí)間,盡快得完成程序的運(yùn)算任務(wù),主要適合在后臺(tái)運(yùn)算而不需要太多交互的任務(wù)。

GC停頓時(shí)間的縮短是以犧牲吞吐量和新生代空間來換取的。

Parallel Scavenge收集器也經(jīng)常被稱為吞吐量?jī)?yōu)先收集器。

Parallel Scavenge收集器提供了兩個(gè)參數(shù)用于精確控制吞吐量

控制最大垃圾收集停頓時(shí)間的-XX:MaxGCPauseMillis參數(shù)。

直接設(shè)置吞吐量大小的-XX:GCTimeRatio參數(shù)。

3.5.4 serial old收集器

Serial Old是Serial收集器的老年代版本,它同樣是一個(gè)單線程收集器,使用“標(biāo)記-整理”算法。

圖片來源于網(wǎng)絡(luò)如有侵權(quán)請(qǐng)私信刪除
3.5.5 parallel old收集器

Serial Old收集器是Serail收集器的老年代版本,是一個(gè)單線程收集器,使用標(biāo)記-整理算法。

圖片來源于網(wǎng)絡(luò)如有侵權(quán)請(qǐng)私信刪除

Serail Old收集器主要用于Clinet模式下。

Serail Old收集器另一種用途是作為CMS收集器的后備預(yù)案。

Parallel Old是Parallel Scavenge收集器的老年代版本,使用多線程“標(biāo)記-整理”算法。

圖片來源于網(wǎng)絡(luò)如有侵權(quán)請(qǐng)私信刪除
3.5.6 cms收集器

CMS收集器是一種以獲取最短的回收停頓時(shí)間為目標(biāo)的收集器。

CMS收集器基于標(biāo)記-清楚算法實(shí)現(xiàn),分為四個(gè)步驟:初始標(biāo)記、并發(fā)標(biāo)記、重新標(biāo)記、并發(fā)清除

步驟詳解

初始標(biāo)記:標(biāo)記一下GC Roots能直接關(guān)聯(lián)到的對(duì)象,速度很快。

并發(fā)標(biāo)記:進(jìn)行GC Roots Tracing

重新標(biāo)記:是為了修正那些在并發(fā)標(biāo)記期間因用戶程序繼續(xù)運(yùn)作而導(dǎo)致標(biāo)記產(chǎn)生變動(dòng)的那一部分對(duì)象的標(biāo)記記錄,在這一階段的停頓時(shí)間會(huì)比初始標(biāo)記階段稍長一點(diǎn)。

并發(fā)清除(CMS concurrent sweep)。

圖片來源于網(wǎng)絡(luò)如有侵權(quán)請(qǐng)私信刪除
3.5.7 g1收集器

G1收集器是一款面向服務(wù)端應(yīng)用的垃圾收集器。
G1收集器具備以下特點(diǎn):

并行與并發(fā)

G1能充分利用多CPU、 多核環(huán)境下的硬件優(yōu)勢(shì),使用多個(gè)CPU(CPU或者CPU核心)來縮短Stop-The-World停頓的時(shí)間,部分其他收集器原本需要停頓Java線程執(zhí)行的GC動(dòng)作,G1收集器仍然可以通過并發(fā)的方式讓Java程序繼續(xù)執(zhí)行。

分代收集

與其他收集器一樣,分代概念在G1中依然得以保留。 雖然G1可以不需要其他收集器配合就能獨(dú)立管理整個(gè)GC堆,但它能夠采用不同的方式去處理新創(chuàng)建的對(duì)象和已經(jīng)存活了一段時(shí)間、 熬過多次GC的舊對(duì)象以獲取更好的收集效果。

空間整合

從整體上來看是基于“標(biāo)記-整理”算法實(shí)現(xiàn)的,在局部上是基于復(fù)制算法實(shí)現(xiàn)的,但無論如何,這兩種算法都意味著G1運(yùn)作期間不會(huì)產(chǎn)生內(nèi)存空間碎片,收集后能提供規(guī)整的可用內(nèi)存。 這種特性有利于程序長時(shí)間運(yùn)行,分配大對(duì)象時(shí)不會(huì)因?yàn)闊o法找到連續(xù)內(nèi)存空間而提前觸發(fā)下一次GC。

可預(yù)測(cè)的停頓

這是G1相對(duì)于CMS的另一大優(yōu)勢(shì),降低停頓時(shí)間是G1CMS共同的關(guān)注點(diǎn),但G1除了追求低停頓外,還能建立可預(yù)測(cè)的停頓時(shí)間模型,能讓使用者明確指定在一個(gè)長度為M毫秒的時(shí)間片段內(nèi),消耗在垃圾收集上的時(shí)間不得超過N毫秒,這幾乎已經(jīng)是實(shí)時(shí)Java(RTSJ)的垃圾收集器的特征了。

G1收集器將整個(gè)Java堆劃分為多個(gè)大小相等的獨(dú)立區(qū)域,雖然還保留有新生代和老生代的概念,但新生代和老生代不再是物理隔的了,他們是一部分Region的集合。

G1收集器可以有計(jì)劃地避免在整個(gè)Java堆中進(jìn)行全區(qū)域的垃圾收集:跟蹤各個(gè)Region里面的垃圾堆積的價(jià)值大小,在后臺(tái)維護(hù)一個(gè)優(yōu)先列表,每次根據(jù)允許的收集時(shí)間,優(yōu)先回收價(jià)值最大的Region。

G1收集器中,使用Remembered Set來避免全堆掃描

G1收集器的運(yùn)作大致可劃分為以下幾個(gè)步驟:

初始標(biāo)記(Initial Marking)

僅僅只是標(biāo)記一下GC Roots能直接關(guān)聯(lián)到的對(duì)象,并且修改TAMS(Next Top at Mark Start)的值,讓下一階段用戶程序并發(fā)運(yùn)行時(shí),能在正確可用的Region中創(chuàng)建新對(duì)象,這階段需要停頓線程,但耗時(shí)很短。

并發(fā)標(biāo)記(Concurrent Marking)

GC Root開始對(duì)堆中對(duì)象進(jìn)行可達(dá)性分析,找出存活的對(duì)象,這階段耗時(shí)較長,但可與用戶程序并發(fā)執(zhí)行。

最終標(biāo)記(Final Marking)

為了修正在并發(fā)標(biāo)記期間因用戶程序繼續(xù)運(yùn)作而導(dǎo)致標(biāo)記產(chǎn)生變動(dòng)的那一部分標(biāo)記記錄,虛擬機(jī)將這段時(shí)間對(duì)象變化記錄在線Remembered Set Logs里面,最終標(biāo)記階段需要把Remembered Set Logs的數(shù)據(jù)合并到Remembered Set中,這階段需要停頓線程,但是可并行執(zhí)行。

篩選回收(Live Data Counting and Evacuation)

首先對(duì)各個(gè)Region的回收價(jià)值和成本進(jìn)行排序,根據(jù)用戶所期望的GC停頓時(shí)間來制定回收計(jì)劃

圖片來源于網(wǎng)絡(luò)如有侵權(quán)請(qǐng)私信刪除
3.5.8 理解gc日志
圖片來源于網(wǎng)絡(luò)如有侵權(quán)請(qǐng)私信刪除

最前面的數(shù)字代表GC發(fā)生的時(shí)間(虛擬機(jī)啟動(dòng)以后的秒殺)

“[GC”“[Full GC”說明停頓類型,有Full代表的是Stop-The-World的;

“[DefNew”“[Tenured”“[Perm”表示GC發(fā)生的區(qū)域;

方括號(hào)內(nèi)部的“3324K -> 152K(3712K)” 含義是 “GC前該內(nèi)存已使用容量 -> GC后該內(nèi)存區(qū)域已使用容量(該區(qū)域總?cè)萘?”;

方括號(hào)之外的“3324K -> 152K(11904)” 含義是 “GC前Java堆已使用容量 -> GC后Java堆已使用容量(Java堆總?cè)萘?”;

再往后“0.0025925 secs”表示該內(nèi)存區(qū)域GC所占用的時(shí)間;

3.5.9 垃圾收集器參數(shù)總結(jié)

垃圾收集器參數(shù)總結(jié)

-XX:+啟用選項(xiàng)
-XX:- 不啟用選項(xiàng)
-XX:
-XX:

參數(shù) 描述
UserSerialGC 虛擬機(jī)在client模式下的默認(rèn)值,打開此開關(guān)后,用于Serial+Serial Old的收集器組合進(jìn)行內(nèi)存回收
UserParNewGC 打開此開關(guān) 使用ParNew + Serial Old收集器組合進(jìn)行內(nèi)存回收
UseConcMarkSweepGC 打開此開關(guān),使用ParNew+CMS+Serial Old收集器組合進(jìn)行內(nèi)存回收。Serial Old在CMS收集器出現(xiàn)concurrent Mode Failure 失敗后的后備收集器
UseParallelGC 在server模式下的默認(rèn)值,打開此開關(guān)后使用Scavenge+Serial Old收集器組合進(jìn)行回收
UseParallelOldGC 打開此開關(guān)后使用 Parallel Scavenge+Parallel Old收集器組合進(jìn)行內(nèi)存回收
SurvivorRatio 新生代中Eden區(qū)域與Survivor區(qū)域的比值,默認(rèn)為8,表示Eden:Survivor=8:1
PretenureSizeThreshold 直接晉升到老年代對(duì)象的大小,設(shè)置這個(gè)參數(shù)后大于這個(gè)參數(shù)的對(duì)象直接在老年代中分配
MaxTenuringThreshold 晉升老年代對(duì)象的年齡,每個(gè)對(duì)象堅(jiān)持一次MnorGC年齡就加一,當(dāng)超過這個(gè)參數(shù)值就進(jìn)入老年代
UseAdaptiveSizePolicy 動(dòng)態(tài)調(diào)整java堆各個(gè)區(qū)域的大小以及進(jìn)入老年代的年齡
HandlePromotionFailure 是否允許分配擔(dān)保失敗,即老年代剩余空間不足以應(yīng)付新生代整個(gè)對(duì)象都存活的特殊情況
ParalleGCThreads 設(shè)置并行GC時(shí)進(jìn)行內(nèi)存回收的線程數(shù)
GCTimeratio GC時(shí)間占總時(shí)間比率,默認(rèn)值為99,允許1%的GC時(shí)間。只在Parallel Seavenge收集器時(shí)生效
MaxGCPauseMillis 設(shè)置GC的最大停頓時(shí)間,只在Parallel Seavenge收集器時(shí)生效
CMSInitiatingOccupancyFration 設(shè)置CMS老年代空間被使用多少后觸發(fā)GC,默認(rèn)值為68%,只在CMS收集器時(shí)生效
UseCMSCompactAtFullCollection 設(shè)置CMS收集器完成垃圾收集后是否需要進(jìn)行一次碎片整理,只在CMS垃圾收集器時(shí)生效
CMSFullGCBeforeCompaction 設(shè)置CMS收集器進(jìn)行若干次垃圾收集后再啟動(dòng)一次內(nèi)存碎片整理,只在CMS垃圾收集器時(shí)生效
3.6 內(nèi)存分配與回收策略

對(duì)象優(yōu)先在新生代分配
大對(duì)象直接進(jìn)入老年代
長期存活的對(duì)象將進(jìn)入老年代

動(dòng)態(tài)對(duì)象年齡判斷:如果在Survivor空間中相同年齡所有對(duì)象大小總和大于Survivor空間的一半,大于或等于該年齡的對(duì)象直接進(jìn)入老年代。

空間分配擔(dān)保:發(fā)生Minor GC前,虛擬機(jī)會(huì)先檢查老年代最大可用連續(xù)空間是否大于新生代所有對(duì)象總空間,如果不成立,虛擬機(jī)會(huì)查看HandlePromotionFailure設(shè)置值是否允許擔(dān)保失敗,如果允許繼續(xù)檢查老年代最大可用的連續(xù)空間是否大于歷次晉升到老年代的平均大小,如果大于會(huì)嘗試進(jìn)行一次Minor GC;如果小于或者不允許冒險(xiǎn),會(huì)進(jìn)行一次Full GC。

3.6.1 對(duì)象優(yōu)先在eden分配

大多數(shù)情況下,對(duì)象優(yōu)先在新生代的Eden區(qū)分配。
當(dāng)Eden區(qū)沒有足夠的空間時(shí),虛擬機(jī)將發(fā)起一次Minor GC。
Minor GC與Full GC。

Minor GC:新生代GC,非常頻繁,回收速度快。

Fulll GC:老年代GC,又稱為Major GC,經(jīng)常會(huì)伴隨一次Minor GC,速度比較慢。

3.6.2 大對(duì)象直接進(jìn)入老年代

大對(duì)象是指需要大量連續(xù)的內(nèi)存空間的Java對(duì)象,最典型的大對(duì)象就是那種很長的字符串以及數(shù)組。

虛擬機(jī)提供了一個(gè)參數(shù):PretenureSizeThreshold,大于這個(gè)參數(shù)的對(duì)象將直接在老年代分配。

3.6.3 長期存活的對(duì)象將進(jìn)入老年代

虛擬機(jī)給每個(gè)對(duì)象定義了一個(gè)對(duì)象年齡計(jì)數(shù)器(Age),對(duì)象每經(jīng)過一次Minor GC后仍然存活,且能被Survivor容納的話,年齡就 +1 ,當(dāng)年齡增加到一定程度(默認(rèn)為15),就會(huì)被晉升到老年代中,這個(gè)閾值可以通過參數(shù) MaxTenuringThreshold 來設(shè)置。

4.動(dòng)態(tài)對(duì)象年齡的判定

3.6.4 動(dòng)態(tài)對(duì)象年齡判定

如果在Survivor空間中相同年齡所有對(duì)象大小的總和大于Survivor空間的一半,年齡大于或等于該年齡的對(duì)象就可以直接進(jìn)入老年代。

3.6.5 空間分配擔(dān)保

為了更好的適應(yīng)不同程序的內(nèi)存狀況,對(duì)象年齡不是必須到達(dá)閾值才會(huì)進(jìn)入老年代。

只要老年代的連續(xù)空間大于新生代對(duì)象總大小或者歷次晉升的平均大小就會(huì)進(jìn)行Minor GC,否則將進(jìn)行Full GC。

問題

為什么程序要跑到安全點(diǎn)時(shí)停下來?

不設(shè)置安全點(diǎn),而讓每一條指令都產(chǎn)生Oop(Ordinary Object Pointer)會(huì)需要大量的額外空間,增大GC的空間成本。設(shè)置了合適的安全點(diǎn),有助于虛擬機(jī)得知對(duì)象引用所在的地方,因此有利于GC對(duì)“即將回收”的對(duì)象進(jìn)行掃描。

最后上一張本章結(jié)構(gòu)圖

圖片來源于網(wǎng)絡(luò)如有侵權(quán)請(qǐng)私信刪除

《深入理解Java虛擬機(jī):JVM高級(jí)特性與最佳實(shí)踐_周志明.高清掃描版.pdf》

下載地址:鏈接:http://pan.baidu.com/s/1miBQCBY 密碼:9kbn

推薦閱讀

《深入理解Java虛擬機(jī)》(一)Java虛擬機(jī)發(fā)展史

《深入理解Java虛擬機(jī)》(二)Java虛擬機(jī)運(yùn)行時(shí)數(shù)據(jù)區(qū)

《深入理解Java虛擬機(jī)》(三)垃圾收集器與內(nèi)存分配策略

《深入理解Java虛擬機(jī)》(四)虛擬機(jī)性能監(jiān)控與故障處理工具

《深入理解Java虛擬機(jī)》(五)JVM調(diào)優(yōu) - 工具

《深入理解Java虛擬機(jī)》(六)堆內(nèi)存使用分析,GC 日志解讀

Contact

作者:鵬磊

出處:http://www.ymq.io

Email:[email protected]

版權(quán)歸作者所有,轉(zhuǎn)載請(qǐng)注明出處

Wechat:關(guān)注公眾號(hào),搜云庫,專注于開發(fā)技術(shù)的研究與知識(shí)分享

文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/67523.html

相關(guān)文章

  • 深入理解Java虛擬機(jī)第3版》垃圾集器內(nèi)存分配策略、虛擬機(jī)性能監(jiān)控故障處理工具

    摘要:目錄往期博客課堂篇初識(shí)常量池簡(jiǎn)單理解字符串常量池靜態(tài)常量池大整型常量池為什么要了解垃圾收集和內(nèi)存分配如何判斷對(duì)象已死引用計(jì)數(shù)算法可達(dá)性分析算法之后引用的擴(kuò)充回收方法區(qū)垃圾收集算法分代收集理論標(biāo)記清除標(biāo)記復(fù)制標(biāo)記整理對(duì)象分 ...

    Kerr1Gan 評(píng)論0 收藏0
  • 深入理解Java虛擬機(jī)(自動(dòng)內(nèi)存管理機(jī)制)

    摘要:看來還是功力不夠,索性拆成了六篇文章,分別從自動(dòng)內(nèi)存管理機(jī)制類文件結(jié)構(gòu)類加載機(jī)制字節(jié)碼執(zhí)行引擎程序編譯與代碼優(yōu)化高效并發(fā)六個(gè)方面來做更加細(xì)致的介紹。本文先說說虛擬機(jī)的自動(dòng)內(nèi)存管理機(jī)制。在類加載檢查通過后,虛擬機(jī)將為新生對(duì)象分配內(nèi)存。 歡迎關(guān)注微信公眾號(hào):BaronTalk,獲取更多精彩好文! 書籍真的是常讀常新,古人說「書讀百遍其義自見」還是蠻有道理的。周志明老師的這本《深入理解 Ja...

    yck 評(píng)論0 收藏0
  • 深入理解java虛擬機(jī)》學(xué)習(xí)筆記系列——垃圾集器&內(nèi)存分配策略

    摘要:虛擬機(jī)所處的區(qū)域,則表示它是屬于新生代收集器還是老年代收集器。虛擬機(jī)總共運(yùn)行了分鐘,其中垃圾收集花掉分鐘,那么吞吐量就是。收集器線程所占用的數(shù)量為。 本文主要從GC(垃圾回收)的角度試著對(duì)jvm中的內(nèi)存分配策略與相應(yīng)的垃圾收集器做一個(gè)介紹。 注:還是老規(guī)矩,本著能畫圖就不BB原則,盡量將各知識(shí)點(diǎn)通過思維導(dǎo)圖或者其他模型圖的方式進(jìn)行說明。文字僅記錄額外的思考與心得,以及其他特殊情況 內(nèi)存...

    calx 評(píng)論0 收藏0
  • 摘記《深入理解Java虛擬機(jī):JVM高級(jí)特性最佳實(shí)踐(第2版)》

    摘要:第章內(nèi)存區(qū)域與內(nèi)存溢出異常運(yùn)行時(shí)數(shù)據(jù)區(qū)域虛擬機(jī)在執(zhí)行程序的過程中會(huì)把它所管理的內(nèi)存劃分為若干個(gè)不同的數(shù)據(jù)區(qū)域。即對(duì)象指向它的類元數(shù)據(jù)的指針,虛擬機(jī)通過這個(gè)指針來確定這個(gè)對(duì)象是哪個(gè)類的實(shí)例。 第2章 Java內(nèi)存區(qū)域與內(nèi)存溢出異常 2.2 運(yùn)行時(shí)數(shù)據(jù)區(qū)域 Java虛擬機(jī)在執(zhí)行Java程序的過程中會(huì)把它所管理的內(nèi)存劃分為若干個(gè)不同的數(shù)據(jù)區(qū)域。根據(jù)《Java虛擬機(jī)規(guī)范(Java SE 7版)...

    zoomdong 評(píng)論0 收藏0
  • 深入理解Java虛擬機(jī)》(六)堆內(nèi)存使用分析,垃圾集器 GC 日志解讀

    摘要:堆內(nèi)存使用分析,垃圾收集器日志解讀重要的東東在中,對(duì)象實(shí)例都是在堆上創(chuàng)建。機(jī)制是由提供,用來清理需要清除的對(duì)象,回收堆內(nèi)存。在中,是由一個(gè)被稱為垃圾回收器的守護(hù)線程執(zhí)行的。 堆內(nèi)存使用分析,垃圾收集器 GC 日志解讀 重要的東東 在Java中,對(duì)象實(shí)例都是在堆上創(chuàng)建。一些類信息,常量,靜態(tài)變量等存儲(chǔ)在方法區(qū)。堆和方法區(qū)都是線程共享的。 GC機(jī)制是由JVM提供,用來清理需要清除的對(duì)象,...

    CODING 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

最新活動(dòng)
閱讀需要支付1元查看
<