深入研究javagc

2019/4/2 星期二
深入研究java gc
引出問(wèn)題和小結(jié)!
應(yīng)該是全網(wǎng)最全的JVM知識(shí)點(diǎn)總結(jié) https://www.toutiao.com/i6717184983829578254/
//此鏈接很重要 推薦收藏
你解釋一下什么是JVM?什么是JDK?什么是JRE?我懵了
https://www.toutiao.com/i6714156440199627276/
小結(jié):
1、為什么使用CMS gc回收算法?
//答:
因?yàn)樵贑MS gc算法執(zhí)行的6個(gè)步驟中,只有在第一步(初始標(biāo)記(STW Initial Mark))和第四步重新標(biāo)記階段(STW REMARK)才會(huì)暫停整個(gè)應(yīng)用,這樣對(duì)應(yīng)用程序所帶來(lái)的影響非常小,缺點(diǎn)是產(chǎn)生內(nèi)存碎片過(guò)多
2、那CMS GC策略如何導(dǎo)致內(nèi)存碎片過(guò)多?
//答:是因?yàn)榈诙讲l(fā)標(biāo)記(concurrent marking)與回收線程會(huì)與應(yīng)用程序爭(zhēng)搶CPU資源,容易產(chǎn)生內(nèi)存碎片,其二:CMS算法在標(biāo)記清理之后并沒(méi)有重新壓縮分配存活對(duì)象,因此整個(gè)老生代會(huì)產(chǎn)生很多的內(nèi)存碎片。
3、那為什么CMS gc策略會(huì)耗時(shí)比較長(zhǎng)呢?
//答:
‘stop-the-world’暫停時(shí)間也很短暫,耗時(shí)較長(zhǎng)的(第二步并發(fā)標(biāo)記)標(biāo)記和(第三步并發(fā)預(yù)清理)清理都是并發(fā)執(zhí)行的。

在玉龍等地區(qū),都構(gòu)建了全面的區(qū)域性戰(zhàn)略布局,加強(qiáng)發(fā)展的系統(tǒng)性、市場(chǎng)前瞻性、產(chǎn)品創(chuàng)新能力,以專注、極致的服務(wù)理念,為客戶提供網(wǎng)站建設(shè)、成都網(wǎng)站建設(shè) 網(wǎng)站設(shè)計(jì)制作定制網(wǎng)站,公司網(wǎng)站建設(shè),企業(yè)網(wǎng)站建設(shè),品牌網(wǎng)站設(shè)計(jì),全網(wǎng)營(yíng)銷推廣,成都外貿(mào)網(wǎng)站制作,玉龍網(wǎng)站建設(shè)費(fèi)用合理。

內(nèi)存碎片過(guò)多如何觸發(fā)Full GC?
//答:
CMS并不是很完美,它會(huì)在兩種場(chǎng)景下產(chǎn)生嚴(yán)重的Full GC(Concurrent Failure(并發(fā)失敗),Promotion Failure (促銷失?。?br/>具體見(jiàn):老年代 CMS gc回收算法 對(duì)hbase的影響 https://blog.51cto.com/12445535/2373206

HBase在演進(jìn)的道路上又如何不斷優(yōu)化CMS GC?

具體內(nèi)容見(jiàn)下詳細(xì)介紹:


題外話:什么是java程序的執(zhí)行流程;java運(yùn)行時(shí)數(shù)據(jù)區(qū);java的內(nèi)存管理 見(jiàn)如下圖:
java程序執(zhí)行流程:
深入研究java gc

java運(yùn)行時(shí)數(shù)據(jù)區(qū):
深入研究java gc

java的內(nèi)存管理:
深入研究java gc

在我們(運(yùn)行時(shí)數(shù)據(jù)區(qū))之中,內(nèi)存的分配一共有五塊:
1、堆內(nèi)存(Heap):保存真正的程序的數(shù)據(jù)的部分;
2、&&&棧內(nèi)存(Stack):保存堆內(nèi)存地址、還保存基本數(shù)據(jù)、方法的執(zhí)行;(所有的數(shù)據(jù)都在棧內(nèi)存之中)
3、方法區(qū):保存所有方法的具體的操作,該區(qū)域?qū)儆诠蚕恚?br/>4、程序計(jì)數(shù)器:這是一塊很小的內(nèi)存,小到幾乎可以忽略的地步,只是做一個(gè)程序執(zhí)行順序的記錄,只是為了標(biāo)記我們下一步要執(zhí)行的代碼的順序號(hào);
5、本地方法棧:該棧之中所保存的都是操作系統(tǒng)的原生函數(shù)。
我們關(guān)心的主要是堆內(nèi)存、棧內(nèi)存、方法區(qū)

在整個(gè)的JVM內(nèi)存組成過(guò)程之中,(棧內(nèi)存)是一個(gè)非常重要的概念,因?yàn)樵谠搩?nèi)存之中,他需要保存的數(shù)據(jù)是一組內(nèi)容,

因?yàn)樗械姆椒ㄔ谶M(jìn)行遞歸調(diào)用的時(shí)候都會(huì)采用棧的模式。觀察遞歸問(wèn)題中滿棧的原因取決于服務(wù)器內(nèi)存的大小。

內(nèi)存操作有關(guān)的兩類異常
stackOverFlowError(棧溢出):如果請(qǐng)求的棧的深度過(guò)大,虛擬機(jī)可能會(huì)拋處。
OutOfMemoryError(內(nèi)存溢出):如果虛擬機(jī)的實(shí)現(xiàn)中允許、虛擬機(jī)棧動(dòng)態(tài)擴(kuò)展,當(dāng)內(nèi)存不足以擴(kuò)展棧的時(shí)候,會(huì)拋出?!緝?nèi)存被沾滿,更多情況下表示堆也分配不了了】

實(shí)際上上面只是觀察到了兩類可能出現(xiàn)錯(cuò)誤的代碼,但是并不是意味著棧中只能夠保存一下基本的信息,實(shí)際上棧里面保存同樣是一組的數(shù)據(jù)。

總結(jié):
1、造成stackOverFlowError(棧溢出)OutOfMemoryError(內(nèi)存溢出)的原因是;
2、在JVM棧內(nèi)存中保存有棧幁的概念,所有的棧內(nèi)存采用先進(jìn)后出的數(shù)據(jù)結(jié)構(gòu)來(lái)進(jìn)行我們的存儲(chǔ)。

首先需要了解一下什么是java的堆內(nèi)內(nèi)存劃分
在實(shí)際情況下:java 堆內(nèi)存劃分分為了(jdk1.8以前和jdk1.8之后)【對(duì)于這2者的區(qū)別,我們后面介紹】
jvm堆內(nèi)存劃分(jdk1.8以前):
深入研究java gc

jvm堆內(nèi)存劃分(jdk1.8之后):
深入研究java gc

java堆內(nèi)存模型
java的垃圾收集主要指的是java堆內(nèi)存空間,那么在每一次執(zhí)行GC的時(shí)候需要區(qū)分出那些堆內(nèi)存空間需要被回收,那些不應(yīng)該被回收。 所以為了整個(gè)的回收處理方便,JVM將堆內(nèi)存分為如下的幾個(gè)組成部分。而這幾個(gè)組成部分你還需要去考慮JDK的版本,現(xiàn)在的JVM內(nèi)存劃分就必須考慮JDK1.8以前和JDK1.8之后的問(wèn)題了。
如果簡(jiǎn)化點(diǎn)來(lái)理解的話:
1、新生代:那些剛剛創(chuàng)建的對(duì)象,剛剛創(chuàng)建的對(duì)象有可能會(huì)存在有許多垃圾對(duì)象,那么這些對(duì)象應(yīng)該是被優(yōu)先回收的;
2、老年代:老不死的那類對(duì)象,經(jīng)過(guò)了很多次的清理之后你發(fā)現(xiàn)該對(duì)象依然有用,
3、永久代:intern()方法進(jìn)行入池的對(duì)象實(shí)際上就在永久代中,永久代不會(huì)被回收。因?yàn)槠浔旧韺儆谝粋€(gè)bug性的存在(也就是jdk崩潰了,死了永久代CIA能消失),所以在jdk1.8之后,將其更換為元空間(就是電腦的直接內(nèi)存)。
舉個(gè)例子:我電腦有100G內(nèi)存,80G給了堆內(nèi)存,那剩下的20G就可以給元空間。

在整個(gè)內(nèi)存的組成過(guò)程之中,每一代的內(nèi)存空間都會(huì)有一個(gè)伸縮區(qū),那么該區(qū)域就可以由JVM根據(jù)空間的使用情況,動(dòng)態(tài)擴(kuò)充。
當(dāng)我們適當(dāng)合理的設(shè)置了伸縮區(qū)的內(nèi)存大小之后,那么就可以得到良好的性能提升。也就是說(shuō)最容易的性能提升就是改變伸縮區(qū)的內(nèi)存大小。

首先什么是java gc 、java對(duì)象創(chuàng)建流程
java對(duì)象創(chuàng)建流程如圖:
深入研究java gc

1、大多數(shù)內(nèi)存對(duì)象要么生存周期比較短,很快就會(huì)沒(méi)人引用,比如處理RPC請(qǐng)求的buffer可能只會(huì)生存幾微秒;
2、要么生存周期比較長(zhǎng),比如Block Cache中的熱點(diǎn)Block,可能就會(huì)生存幾分鐘,甚至更長(zhǎng)時(shí)間。
3、基于這樣的事實(shí),JVM將整個(gè)堆內(nèi)存分為兩個(gè)部分:新生代(young generation)和老生代(tenured generation),除此之外,JVM還有一個(gè)非堆內(nèi)存區(qū)-Perm區(qū),主要存放class信息以及其他meta元信息,
4、其中Young區(qū)又分為Eden區(qū)和兩個(gè)Survivor 區(qū):S0和S1。
5、一個(gè)內(nèi)存對(duì)象在創(chuàng)建之后,首先會(huì)為其在新生代申請(qǐng)一塊內(nèi)存空間,如果這個(gè)對(duì)象在新生代存活了很長(zhǎng)時(shí)間,會(huì)將其遷移到老生代。
6、在大多數(shù)對(duì)延遲敏感的業(yè)務(wù)場(chǎng)景下(比如HBase),建議使用如下JVM參數(shù),-XX:+UseParNewGC和XX:+UseConcMarkSweepGC,其中前者表示對(duì)新生代執(zhí)行并行的垃圾回收機(jī)制,而后者表示對(duì)老生代執(zhí)行并行標(biāo)記-清除垃圾回收機(jī)制。
7、可見(jiàn),JVM允許針對(duì)不同內(nèi)存區(qū)執(zhí)行不同的GC策略。
//在 cdh中默認(rèn)是這樣設(shè)置的
-XX:+UseParNewGC -XX:+UseConcMarkSweepGC -XX:CMSInitiatingOccupancyFraction=70 -XX:+CMSParallelRemarkEnabled


接下來(lái)重點(diǎn)先討論一下年輕代

深入研究java gc

年輕代GC實(shí)現(xiàn)復(fù)制算法:(年輕代GC策略 – Parallel New Collector)
深入研究java gc

1、對(duì)象初始化之后會(huì)被放入Young區(qū),更具體的話應(yīng)該是Eden區(qū),當(dāng)Eden區(qū)滿了之后,會(huì)進(jìn)行一次GC。
2、GC算法會(huì)檢查所有對(duì)象的引用情況,如果某個(gè)對(duì)象還有被引用,表示該對(duì)象存活。
3、檢查完成之后,會(huì)將這些存活的對(duì)象移到S0區(qū),并且回收整個(gè)Eden區(qū)空間,稱為一次Minor GC;
4、接著新對(duì)象進(jìn)來(lái),又會(huì)放入Eden區(qū),滿了之后會(huì)檢查S0和Eden區(qū)存活的對(duì)象,將所有存活的對(duì)象移到S1區(qū),再回收整個(gè)S0和Eden區(qū)空間;
5、很容易理解,S0和S1兩個(gè)區(qū)總會(huì)有一個(gè)區(qū)是預(yù)留給下次存放存活對(duì)象用的。

這種算法稱為復(fù)制算法,對(duì)于這種算法,有兩點(diǎn)需要關(guān)注:

  1. 算法會(huì)執(zhí)行’stop-the-world’暫停,但時(shí)間非常短。因?yàn)閅oung區(qū)通常會(huì)設(shè)置的比較?。ㄒ话悴唤ㄗh不超過(guò)512M),而且JVM會(huì)啟動(dòng)大量線程并發(fā)執(zhí)行,一次Minor GC一般都會(huì)在幾毫秒內(nèi)完成
  2. 不會(huì)產(chǎn)生碎片,每次GC之后都會(huì)將存活的對(duì)象放入連續(xù)的空間(S0或S1)
    內(nèi)存中所有對(duì)象都會(huì)維護(hù)一個(gè)計(jì)數(shù)器,每次Minor GC移動(dòng)一個(gè)對(duì)象之后,都會(huì)為這個(gè)對(duì)象的計(jì)數(shù)器加一。當(dāng)計(jì)數(shù)器增加到一定閾值之后,算法就會(huì)認(rèn)為該對(duì)象生命周期很長(zhǎng),會(huì)將其移入老生代。該閾值可以通過(guò)JVM參數(shù)XX:MaxTenuringThreshold指定。

提高了解篇
年輕代優(yōu)化算法

深入研究java gc

深入研究java gc

深入研究java gc

年輕代內(nèi)存調(diào)整參數(shù)(重要):
深入研究java gc


接下來(lái)深度研究老年代

什么是老年代 和老年代的full gc:
深入研究java gc

老生代GC策略 – Concurrent Mark-Sweep(CMS算法)
什么是CMS 為什么CMS?
1、每次執(zhí)行Minor GC之后,都會(huì)有部分生命周期較長(zhǎng)的對(duì)象被移入老生代,一段時(shí)間之后,老生代空間也會(huì)被占滿。
2、此時(shí)就需要針對(duì)老生代空間執(zhí)行GC操作,此處我們介紹Concurrent Mark-Sweep(CMS)算法。

CMS算法整個(gè)流程分為6個(gè)階段,其中部分階段會(huì)執(zhí)行 ‘stop-the-world’ 暫停,部分階段會(huì)和應(yīng)用線程一起并發(fā)執(zhí)行:
如圖:
深入研究java gc

老年代執(zhí)行CMS過(guò)程:
深入研究java gc
相應(yīng)的,對(duì)于CMS算法,也需要關(guān)注兩點(diǎn):

  1. ‘stop-the-world’暫停時(shí)間也很短暫,耗時(shí)較長(zhǎng)的標(biāo)記和清理都是并發(fā)執(zhí)行的。
  2. CMS算法在標(biāo)記清理之后并沒(méi)有重新壓縮分配存活對(duì)象,因此整個(gè)老生代會(huì)產(chǎn)生很多的內(nèi)存碎片。

提高篇
老年代標(biāo)記清除算法:
深入研究java gc

老年代標(biāo)記壓縮算法:
深入研究java gc

老年代內(nèi)存調(diào)整參數(shù):
深入研究java gc

永久代調(diào)整參數(shù):
深入研究java gc

元空間調(diào)整參數(shù):
深入研究java gc


可用gc方式小結(jié):
深入研究java gc

年輕代串行GC(copy)
深入研究java gc

年輕代并行回收GC
深入研究java gc

年輕代并行GC
深入研究java gc

老年代串行GC
深入研究java gc

老年代并行GC
深入研究java gc

常用gc策略:
深入研究java gc

GC調(diào)整策略、
深入研究java gc

收集器參數(shù)設(shè)置
深入研究java gc


G1收集器介紹:
深入研究java gc

深入研究java gc

深入研究java gc

深入研究java gc

深入研究java gc

深入研究java gc

參考鏈接:
http://hbasefly.com/2016/05/21/hbase-gc-1/

分享名稱:深入研究javagc
本文路徑:http://muchs.cn/article0/ijoioo.html

成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供App開發(fā)、網(wǎng)站設(shè)計(jì)公司、做網(wǎng)站、網(wǎng)站排名網(wǎng)站營(yíng)銷、搜索引擎優(yōu)化

廣告

聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請(qǐng)盡快告知,我們將會(huì)在第一時(shí)間刪除。文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如需處理請(qǐng)聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時(shí)需注明來(lái)源: 創(chuàng)新互聯(lián)

商城網(wǎng)站建設(shè)