麻豆小视频在线观看_中文黄色一级片_久久久成人精品_成片免费观看视频大全_午夜精品久久久久久久99热浪潮_成人一区二区三区四区

首頁(yè) > 編程 > Java > 正文

Java GC的那些事(2)

2019-11-11 06:55:48
字體:
供稿:網(wǎng)友

學(xué)習(xí)java的同學(xué)注意了?。?! 學(xué)習(xí)過程中遇到什么問題或者想獲取學(xué)習(xí)資源的話,歡迎加入Java學(xué)習(xí)交流群,群號(hào)碼:183993990  我們一起學(xué)Java!

收集算法

垃圾收集算法主要有:標(biāo)記-清除、復(fù)制和標(biāo)記-整理。

1、標(biāo)記-清除算法

對(duì)待回收的對(duì)象進(jìn)行標(biāo)記。算法缺點(diǎn):效率問題,標(biāo)記和清除過程效率都很低;空間問題,收集之后會(huì)產(chǎn)生大量的內(nèi)存碎片,不利于大對(duì)象的分配。

2、復(fù)制算法

復(fù)制算法將可用內(nèi)存劃分成大小相等的兩塊A和B,每次只使用其中一塊,當(dāng)A的內(nèi)存用完了,就把存活的對(duì)象復(fù)制到B,并清空A的內(nèi)存,不僅提高了標(biāo)記的效率,因?yàn)橹恍枰獦?biāo)記存活的對(duì)象,同時(shí)也避免了內(nèi)存碎片的問題,代價(jià)是可用內(nèi)存縮小為原來的一半。

3、標(biāo)記-整理算法

在老年代中,對(duì)象存活率較高,復(fù)制算法的效率很低。在標(biāo)記-整理算法中,標(biāo)記出所有存活的對(duì)象,并移動(dòng)到一端,然后直接清理邊界以外的內(nèi)存。

對(duì)象標(biāo)記過程

在可達(dá)性分析過程中,為了準(zhǔn)確找出與GC Roots相關(guān)聯(lián)的對(duì)象,必須要求整個(gè)執(zhí)行引擎看起來像是被凍結(jié)在某個(gè)時(shí)間點(diǎn)上,即暫停所有運(yùn)行中的線程,不可以出現(xiàn)對(duì)象的引用關(guān)系還在不斷變化的情況。

如何快速枚舉GC Roots?

GC Roots主要在全局性的引用(常量或類靜態(tài)屬性)與執(zhí)行上下文(本地變量表中的引用)中,很多應(yīng)用僅僅方法區(qū)就上百兆,如果進(jìn)行遍歷查找,效率會(huì)非常低下。

在HotSpot中,使用一組稱為OopMap的數(shù)據(jù)結(jié)構(gòu)進(jìn)行實(shí)現(xiàn)。類加載完成時(shí),HotSpot把對(duì)象內(nèi)什么偏移量上是什么類型的數(shù)據(jù)計(jì)算出來存儲(chǔ)到OopMap中,通過JIT編譯出來的本地代碼,也會(huì)記錄下棧和寄存器中哪些位置是引用。GC發(fā)生時(shí),通過掃描OopMap的數(shù)據(jù)就可以快速標(biāo)識(shí)出存活的對(duì)象。

如何安全的GC?

線程運(yùn)行時(shí),只有在到達(dá)安全點(diǎn)(Safe Point)才能停頓下來進(jìn)行GC。

基于OopMap數(shù)據(jù)結(jié)構(gòu),HotSpot可以快速完成GC Roots的遍歷,不過HotSpot并不會(huì)為每條指令都生成對(duì)應(yīng)的OopMap,只會(huì)在Safe Point處記錄這些信息。

所以Safe Point的選擇很重要,如果太少可能導(dǎo)致GC等待的時(shí)間太長(zhǎng),如果太頻繁可能導(dǎo)致運(yùn)行時(shí)的性能問題。大部分指令的執(zhí)行時(shí)間都非常短暫,通常會(huì)選擇一些執(zhí)行時(shí)間較長(zhǎng)的指令作為Safe Point,如方法調(diào)用、循環(huán)跳轉(zhuǎn)和異常跳轉(zhuǎn)等。

關(guān)于Safe Point更多的信息,可以看看這篇文章 JVM的Stop The World,安全點(diǎn),黑暗的地底世界

發(fā)生GC時(shí),如何讓所有線程跑到最近的Safe Point再暫停?

當(dāng)發(fā)生GC時(shí),不直接對(duì)線程進(jìn)行中斷操作,而是簡(jiǎn)單的設(shè)置一個(gè)中斷標(biāo)志,每個(gè)線程運(yùn)行到Safe Point的時(shí)候,主動(dòng)去輪詢這個(gè)中斷標(biāo)志,如果中斷標(biāo)志為真,則將自己進(jìn)行中斷掛起。

這里忽略了一個(gè)問題,當(dāng)發(fā)生GC時(shí),運(yùn)行中的線程可以跑到Safe Point后進(jìn)行掛起,而那些處于Sleep或Blocked狀態(tài)的線程在此時(shí)無(wú)法響應(yīng)JVM的中斷請(qǐng)求,無(wú)法到Safe Point處進(jìn)行掛起,針對(duì)這種情況,可以使用安全區(qū)域(Safe Region)進(jìn)行解決。

Safe Region是指在一段代碼片段中,對(duì)象的引用關(guān)系不會(huì)發(fā)生變化,在這個(gè)區(qū)域中的任何位置開始GC都是安全的。1、當(dāng)線程運(yùn)行到Safe Region的代碼時(shí),首先標(biāo)識(shí)已經(jīng)進(jìn)入了Safe Region,如果這段時(shí)間內(nèi)發(fā)生GC,JVM會(huì)忽略標(biāo)識(shí)為Safe Region狀態(tài)的線程;2、當(dāng)線程即將離開Safe Region時(shí),會(huì)檢查JVM是否已經(jīng)完成GC,如果完成了,則繼續(xù)運(yùn)行,否則線程必須等待直到收到可以安全離開Safe Region的信號(hào)為止;

垃圾收集器

Java虛擬機(jī)規(guī)范并沒有規(guī)定垃圾收集器應(yīng)該如何實(shí)現(xiàn),用戶可以根據(jù)系統(tǒng)特點(diǎn)對(duì)各個(gè)區(qū)域所使用的收集器進(jìn)行組合使用。

上圖展示了7種不同分代的收集器,如果兩兩之間存在連線,說明可以組合使用。

1、Serial收集器(串行GC)

Serial 是一個(gè)采用單個(gè)線程并基于復(fù)制算法工作在新生代的收集器,進(jìn)行垃圾收集時(shí),必須暫停其他所有的工作線程。對(duì)于單CPU環(huán)境來說,Serial由于沒有線程交互的開銷,可以很高效的進(jìn)行垃圾收集動(dòng)作,是Client模式下新生代默認(rèn)的收集器。

2、ParNew收集器(并行GC)

ParNew其實(shí)是serial的多線程版本,除了使用多條線程進(jìn)行垃圾收集之外,其余行為與Serial一樣。

3、Parallel Scavenge收集器(并行回收GC)

Parallel Scavenge是一個(gè)采用多線程基于復(fù)制算法并工作在新生代的收集器,其關(guān)注點(diǎn)在于達(dá)到一個(gè)可控的吞吐量,經(jīng)常被稱為“吞吐量?jī)?yōu)先”的收集器。

吞吐量 = 用戶代碼運(yùn)行時(shí)間 /(用戶代碼運(yùn)行時(shí)間 + 垃圾收集時(shí)間)

Parallel Scavenge提供了兩個(gè)參數(shù)用于精確控制吞吐量:1、-XX:MaxGCPauseMillis 設(shè)置垃圾收集的最大停頓時(shí)間2、-XX:GCTimeRatio 設(shè)置吞吐量大小

4、Serial Old收集器(串行GC)

Serial Old 是一個(gè)采用單線程基于標(biāo)記-整理算法并工作在老年代的收集器,是Client模式下老年代默認(rèn)的收集器。

5、Parallel Old收集器(并行GC)

Parallel Old是一個(gè)采用多線程基于標(biāo)記-整理算法并工作在老年代的收集器。在注重吞吐量以及CPU資源敏感的場(chǎng)合,可以優(yōu)先考慮Parallel Scavenge和Parallel Old的收集器組合。

6、CMS收集器(并發(fā)GC)

CMS(Concurrent Mark Sweep)是一種以獲取最短回收停頓時(shí)間為目標(biāo)的收集器,工作在老年代,基于“標(biāo)記-清除”算法實(shí)現(xiàn),整個(gè)過程分為以下4步:

1、初始標(biāo)記:這個(gè)過程只是標(biāo)記以下GC Roots能夠直接關(guān)聯(lián)的對(duì)象,但是仍然會(huì)Stop The World;2、并發(fā)標(biāo)記:進(jìn)行GC Roots Tracing的過程,可以和用戶線程一起工作。3、重新標(biāo)記:用于修正并發(fā)標(biāo)記期間由于用戶程序繼續(xù)運(yùn)行而導(dǎo)致標(biāo)記產(chǎn)生變動(dòng)的那部分記錄,這個(gè)過程會(huì)暫停所有線程,但其停頓時(shí)間遠(yuǎn)比并發(fā)標(biāo)記的時(shí)間短;4、并發(fā)清理:可以和用戶線程一起工作。

CMS收集器的缺點(diǎn):

1、對(duì)CPU資源比較敏感,在并發(fā)階段,雖然不會(huì)導(dǎo)致用戶線程停頓,但是會(huì)占用一部分線程資源,降低系統(tǒng)的總吞吐量。2、無(wú)法處理浮動(dòng)垃圾,在并發(fā)清理階段,用戶線程的運(yùn)行依然會(huì)產(chǎn)生新的垃圾對(duì)象,這部分垃圾只能在下一次GC時(shí)收集。3、CMS是基于標(biāo)記-清除算法實(shí)現(xiàn)的,意味著收集結(jié)束后會(huì)造成大量的內(nèi)存碎片,可能導(dǎo)致出現(xiàn)老年代剩余空間很大,卻無(wú)法找到足夠大的連續(xù)空間分配當(dāng)前對(duì)象,不得不提前觸發(fā)一次Full GC。

JDK1.5實(shí)現(xiàn)中,當(dāng)老年代空間使用率達(dá)到68%時(shí),就會(huì)觸發(fā)CMS收集器,如果應(yīng)用中老年代增長(zhǎng)不是太快,可以通過-XX:CMSInitiatingOccupancyFraction參數(shù)提高觸發(fā)百分比,從而降低內(nèi)存回收次數(shù)提高系統(tǒng)性能。

JDK1.6實(shí)現(xiàn)中,觸發(fā)CMS收集器的閾值已經(jīng)提升到92%,要是CMS運(yùn)行期間預(yù)留的內(nèi)存無(wú)法滿足用戶線程需要,會(huì)出現(xiàn)一次”Concurrent Mode Failure”失敗,這是虛擬機(jī)會(huì)啟動(dòng)Serial Old收集器對(duì)老年代進(jìn)行垃圾收集,當(dāng)然,這樣應(yīng)用的停頓時(shí)間就更長(zhǎng)了,所以這個(gè)閾值也不能設(shè)置的太高,如果導(dǎo)致了”Concurrent Mode Failure”失敗,反而會(huì)降低性能,至于如何設(shè)置這個(gè)閾值,還得長(zhǎng)時(shí)間的對(duì)老年代空間的使用情況進(jìn)行監(jiān)控。

7、G1收集器

G1(Garbage First)是JDK1.7提供的一個(gè)工作在新生代和老年代的收集器,基于“標(biāo)記-整理”算法實(shí)現(xiàn),在收集結(jié)束后可以避免內(nèi)存碎片問題。

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

1、并行與并發(fā):充分利用多CPU來縮短Stop The World的停頓時(shí)間;2、分代收集:不需要其他收集配合就可以管理整個(gè)Java堆,采用不同的方式處理新建的對(duì)象、已經(jīng)存活一段時(shí)間和經(jīng)歷過多次GC的對(duì)象獲取更好的收集效果;3、空間整合:與CMS的”標(biāo)記-清除”算法不同,G1在運(yùn)行期間不會(huì)產(chǎn)生內(nèi)存空間碎片,有利于應(yīng)用的長(zhǎng)時(shí)間運(yùn)行,且分配大對(duì)象時(shí),不會(huì)導(dǎo)致由于無(wú)法申請(qǐng)到足夠大的連續(xù)內(nèi)存而提前觸發(fā)一次Full GC;4、停頓預(yù)測(cè):G1中可以建立可預(yù)測(cè)的停頓時(shí)間模型,能讓使用者明確指定在M毫秒的時(shí)間片段內(nèi),消耗在垃圾收集上的時(shí)間不得超過N毫秒。

使用G1收集器時(shí),Java堆的內(nèi)存布局與其他收集器有很大區(qū)別,整個(gè)Java堆會(huì)被劃分為多個(gè)大小相等的獨(dú)立區(qū)域Region,新生代和老年代不再是物理隔離了,都是一部分Region(不需要連續(xù))的集合。G1會(huì)跟蹤各個(gè)Region的垃圾收集情況(回收空間大小和回收消耗的時(shí)間),維護(hù)一個(gè)優(yōu)先列表,根據(jù)允許的收集時(shí)間,優(yōu)先回收價(jià)值最大的Region,避免在整個(gè)Java堆上進(jìn)行全區(qū)域的垃圾回收,確保了G1收集器可以在有限的時(shí)間內(nèi)盡可能收集更多的垃圾。

不過問題來了:使用G1收集器,一個(gè)對(duì)象分配在某個(gè)Region中,可以和Java堆上任意的對(duì)象有引用關(guān)系,那么如何判定一個(gè)對(duì)象是否存活,是否需要掃描整個(gè)Java堆?其實(shí)這個(gè)問題在之前收集器中也存在,如果回收新生代的對(duì)象時(shí),不得不同時(shí)掃描老年代的話,會(huì)大大降低Minor GC的效率。

針對(duì)這種情況,虛擬機(jī)提供了一個(gè)解決方案:G1收集器中Region之間的對(duì)象引用關(guān)系和其他收集器中新生代與老年代之間的對(duì)象引用關(guān)系被保存在Remenbered Set數(shù)據(jù)結(jié)構(gòu)中,用來避免全堆掃描。G1中每個(gè)Region都有一個(gè)對(duì)應(yīng)的Remenbered Set,當(dāng)虛擬機(jī)發(fā)現(xiàn)程序?qū)eference類型的數(shù)據(jù)進(jìn)行寫操作時(shí),會(huì)產(chǎn)生一個(gè)Write Barrier暫時(shí)中斷寫操作,檢查Reference引用的對(duì)象是否處于相同的Region中,如果不是,則通過CardTable把相關(guān)引用信息記錄到被引用對(duì)象所屬Region的Remenbered Set中。

學(xué)習(xí)Java的同學(xué)注意了?。?! 學(xué)習(xí)過程中遇到什么問題或者想獲取學(xué)習(xí)資源的話,歡迎加入Java學(xué)習(xí)交流群,群號(hào)碼:183993990  我們一起學(xué)Java!


發(fā)表評(píng)論 共有條評(píng)論
用戶名: 密碼:
驗(yàn)證碼: 匿名發(fā)表
主站蜘蛛池模板: 色中色在线播放 | 天天草天天干天天射 | 一日本道久久久精品国产 | 精品一区二区三区免费视频 | 热99在线视频 | 毛片免费在线观看视频 | 久久久精品视频免费看 | 国产精品成人免费一区久久羞羞 | 国产亚洲在 | 国产亚洲精品视频中文字幕 | 7777在线视频免费播放 | 国产亚洲精品一区二区三区 | 欧美成人午夜影院 | 亚洲视频成人在线 | 黄视频免费在线观看 | 国产成人自拍视频在线 | 欧美1—12sexvideos| 热99re久久免费视精品频软件 | 九九视屏 | 久久免费视频一区二区三区 | 亚洲成人入口 | 黄网站在线免费 | 亚洲av一级毛片特黄大片 | 在线免费观看日韩视频 | 久久久久久亚洲综合影院红桃 | 国产一级性生活视频 | 国产成人自拍av | 色无极影院亚洲 | 九色p| 日韩视频高清 | 成人在线国产 | 福利免费在线观看 | av电影免费在线看 | 久久久久二区 | 亚洲骚妻 | 超碰97国产在线 | 在线视频 欧美日韩 | 一级黄色毛片a | 成人免费乱码大片a毛片视频网站 | 国产一区视频在线免费观看 | 亚州综合一区 |