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

寫在前面:為了更加深入的了解java虛擬機(jī)榨汤,就看了一下《深入理解java虛擬機(jī)》這本書惶楼,一方面為了總結(jié)一下自己的認(rèn)識(shí),另一方面就是想與各位分享滔以,如果有什么不對的地方捉腥,歡迎指正

深入理解java虛擬機(jī)(一)java內(nèi)存區(qū)域與內(nèi)存溢出異常

垃圾收集器與內(nèi)存分配策略

垃圾收集,三個(gè)步驟
什么時(shí)候收集你画,收集那些抵碟,怎么收集

1、收集那些

我們會(huì)將一些不使用的對象進(jìn)行收集坏匪,進(jìn)行回收內(nèi)存空間拟逮,我們怎么知道呢

1、引用計(jì)數(shù)法

如果這個(gè)實(shí)例被其他地方引用适滓,那么計(jì)數(shù)器加一敦迄,如果解除引用那么就減一,當(dāng)計(jì)數(shù)器為0說明沒有地方使用凭迹,即可回收罚屋,但是缺點(diǎn)就是如果兩個(gè)對象互相引用,但是后續(xù)又用不到嗅绸,那么就不會(huì)被回收脾猛,內(nèi)存浪費(fèi)

2、可達(dá)性分析

通過GC Root向下尋找朽砰,形成一條引用鏈尖滚,如果對象不再這條鏈上,那么說明該對象不可達(dá)瞧柔,可回收漆弄,

什么是GC Root

  • 虛擬機(jī)棧中引用的對象
  • 方法區(qū)中靜態(tài)屬性引用的對象
  • 方法區(qū)常亮引用的對象
  • 本地方法棧中引用的對象

3、引用

我們不論是使用引用計(jì)數(shù)法造锅,還是使用可達(dá)性分析撼唾,都有引用這個(gè)詞,什么意思呢

jdk1.2之前的引用哥蔚,是reference類型的數(shù)據(jù)存儲(chǔ)的是另一塊內(nèi)存的起始地址倒谷,那么就稱這塊內(nèi)存代表著一個(gè)引用蛛蒙,這種情況下,一個(gè)對象只有被引用和沒有被引用兩種狀態(tài)渤愁,

我們希望有一些對象牵祟,在內(nèi)存空間足夠的時(shí)候,能夠保留在內(nèi)存中抖格,如果內(nèi)存空間在進(jìn)行垃圾收集之后還是很緊張诺苹,那么就拋棄這些對象,所以出現(xiàn) 強(qiáng)引用(Strong Reference)雹拄,軟引用(Soft Reference)收奔,弱引用(Weak Reference),虛引用(Phantom Reference)滓玖,這4中引用強(qiáng)度依次減弱

  • 強(qiáng)引用
    強(qiáng)引用就是指程序代碼中普遍存在的 Object obj = new Object()這類引用坪哄,只要強(qiáng)引用還存在,垃圾收集器永遠(yuǎn)不會(huì)回收掉被引用的對象势篡,使用StrongReference實(shí)現(xiàn)
  • 軟引用
    jdk1.2之后出現(xiàn)軟引用用來描述一些有用翩肌,但不是必須的對象,軟引用關(guān)聯(lián)的對象殊霞,在系統(tǒng)將要發(fā)生內(nèi)存溢出異常之前摧阅,將會(huì)把這些對象列入可回收范圍中進(jìn)行第二次回收,如果這次回收還不能解決內(nèi)存問題绷蹲,那么拋出內(nèi)存溢出錯(cuò)誤,顾孽,使用SoftReference實(shí)現(xiàn)
  • 弱引用
    弱引用也是用來描述非必需的對象祝钢,被弱引用關(guān)聯(lián)的對象,只能生存到下一次垃圾收集發(fā)生之前若厚,當(dāng)垃圾收集器工作時(shí)候拦英,無論當(dāng)前內(nèi)存是否足夠,都會(huì)回收掉测秸,使用WeakReference類實(shí)現(xiàn)虛引用
  • 虛引用
    最弱的引用疤估,一個(gè)對象是否有徐勇勇的存在,完全不會(huì)對其生存時(shí)間構(gòu)成影響霎冯,也無法通過虛引用來取得一個(gè)對象實(shí)例铃拇,為一個(gè)對象設(shè)置虛引用關(guān)聯(lián)的唯一目的,就是能在這個(gè)對象被收集器回收時(shí)收到一個(gè)系統(tǒng)通知沈撞,jdk1.2之后通過PhantomReference類來實(shí)現(xiàn)虛引用慷荔,

4.對象死了嗎

當(dāng)對象沒有存在GC Root引用鏈上,也不是馬上死缠俺,會(huì)被進(jìn)行一次標(biāo)記并進(jìn)行一次篩選显晶,查看對象的finalliaze方法是否被覆蓋贷岸,或者是否被虛擬機(jī)調(diào)用過了,

如果被覆蓋或者沒有被調(diào)用磷雇,那么這個(gè)對象會(huì)被放置到F-Queue中偿警,等待執(zhí)行finaliaze方法,虛擬機(jī)會(huì)開啟一條低優(yōu)先級(jí)的線程去觸發(fā)這些方法唯笙,如果對象在finalize方法中重新加入了引用鏈(把自己賦值給某個(gè)類變量螟蒸,或者對象的成員變量),那么就不會(huì)被回收了睁本,

5.回收方法區(qū)

回收方法區(qū)內(nèi)廢棄常量和無用的類

廢棄常量:如果常量池中有各“abc”的字面量尿庐,但是卻沒有一個(gè)string 對象叫做abc,那么這個(gè)就是廢棄常量呢堰,當(dāng)垃圾回收的時(shí)候就會(huì)回收

無用的類:在堆中已經(jīng)沒有這個(gè)類的實(shí)例抄瑟,加載該類的類加載器已經(jīng)被回收,這個(gè)Class對象沒有在任何地方被引用枉疼,無法通過反射獲取這個(gè)類的方法

2皮假、怎么收集

垃圾收集在方法區(qū)和堆區(qū)

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

標(biāo)記清除:當(dāng)堆內(nèi)存耗盡的時(shí)候,觸發(fā)GC線程骂维,使用戶線程停止惹资,遍歷所有的GC root,將還存活的隨想標(biāo)記一下航闺,之后清除所有未標(biāo)記的對象褪测,繼續(xù)用戶線程,缺點(diǎn):產(chǎn)生內(nèi)存碎片潦刃,使得內(nèi)存不連續(xù)侮措,當(dāng)有對象申請大內(nèi)存的時(shí)候,出現(xiàn)問題

復(fù)制算法: 將原內(nèi)存一分為二乖杠,只用一半的內(nèi)存分扎,當(dāng)需要垃圾回收的時(shí)候, 標(biāo)記存活對象胧洒,然后將存活對象拷貝到另一半空間中去畏吓,前一半直接全部回收,缺點(diǎn):無論什么時(shí)候卫漫,只有一半的內(nèi)存可用菲饼,浪費(fèi),拷貝對象需要時(shí)間

標(biāo)記整理算法:標(biāo)記存活對象汛兜,將存活對象按照某種規(guī)則排列巴粪,清除別的對象,缺點(diǎn):需要遍歷標(biāo)記,需要移動(dòng)對象肛根,浪費(fèi)時(shí)間

分代回收:
堆分為新生代和老年代辫塌,新生代分三個(gè)模塊,Enden surviver0 surviver1 8:1:1 new出來的對象放在enden區(qū)域派哲,當(dāng)發(fā)生gc臼氨,將存活的放在surviver0,第二次將存活的芭届,surviver0中的放在surviver1中储矩,反復(fù)如此,使用標(biāo)記復(fù)制算法褂乍,當(dāng)新生代的對象活過一定次數(shù)gc持隧,就會(huì)去到老年代
新生代使用復(fù)制算法,老年代使用標(biāo)記清除逃片,標(biāo)記整理算法

3屡拨、常見的垃圾收集器

1.Serial垃圾收集器(客戶端模式下的虛擬機(jī),新生代默認(rèn)收集器)

單線程垃圾收集器褥实,在進(jìn)行垃圾收集的時(shí)候呀狼,會(huì)停止用戶線程,當(dāng)垃圾收集完畢损离,開始用戶線程哥艇,這個(gè)是對用戶不可見的,完全由虛擬機(jī)執(zhí)行僻澎,單CPU效率最高的收集器貌踏,沒有線程交替的開銷

2.ParNew垃圾收集器(服務(wù)端模式下的虛擬機(jī),新生代默認(rèn)收集器)

Serial收集器的多線程版本窟勃,在進(jìn)行垃圾收集哩俭,也會(huì)先停止用戶線程,除了Serial只有這個(gè)收集器可以和CMS收集器使用拳恋,

3. Parallel Scavenge收集器
多線程并行的垃圾收集器,與ParNew類似砸捏,但是這個(gè)收集器注點(diǎn)在于達(dá)到一個(gè)可控制的吞吐量谬运,吞吐量就是CPU用于運(yùn)行用戶代碼的時(shí)間與cpu總消耗時(shí)間的比值,
4. Serial Old收集器
是serial收集器的老年版本垦藏,同樣是一個(gè)單線程收集器梆暖,使用標(biāo)記整理算法,是給客戶端模式下的虛擬機(jī)使用掂骏,在server模式下的客戶端有兩大用途:一是在jdk1.5之前轰驳,與Parallel Scavenge收集器搭配使用,二就是作為CMS收集器的后備預(yù)案,在并發(fā)收集器發(fā)生Concurrent Mode Failure時(shí)使用级解,
也會(huì)暫停用戶線程
5. CMS收集器
是一種以獲取短回收停頓時(shí)間為目標(biāo)的收集器冒黑,采用標(biāo)記清除方式,運(yùn)作過程有

  • 初始標(biāo)記
  • 并發(fā)標(biāo)記
  • 重新標(biāo)記
  • 并發(fā)清除

其中初始標(biāo)記與重新標(biāo)記需要停止用戶線程勤哗,初始標(biāo)記只是標(biāo)記一下GC Root能直接關(guān)聯(lián)到的對象抡爹,速度很快,并發(fā)標(biāo)記階段就是進(jìn)行GC Root Tracing的過程芒划,而重新標(biāo)記階段則是為了修正并發(fā)標(biāo)記期間因?yàn)橛脩舫绦蚶^續(xù)運(yùn)作而導(dǎo)致的標(biāo)記產(chǎn)生變動(dòng)的那一部分對象的記錄冬竟,這個(gè)階段停頓的時(shí)間一般會(huì)比初始標(biāo)記階段稍長一點(diǎn),但遠(yuǎn)比并發(fā)標(biāo)記的時(shí)間短民逼,泵殴,由于整個(gè)過程中耗時(shí)最長的并發(fā)標(biāo)記和并發(fā)清除過程,收集器線程可以和用戶線程一起工作拼苍,所以笑诅,總體來看,CMS收集器的內(nèi)存回收過程食欲用戶線程一起并發(fā)執(zhí)行的映屋,
缺點(diǎn):CMS無法處理浮動(dòng)垃圾苟鸯,可能出現(xiàn)Concurrent Mode Failure失敗而導(dǎo)致另一次Full GC的產(chǎn)生,由于CMS的并發(fā)清理階段適合用戶線程一起的棚点,那么程序運(yùn)行就會(huì)有新的垃圾產(chǎn)生早处,這一部分垃圾在標(biāo)記之后,所以CMS不會(huì)處理瘫析,下一次處理砌梆, 也是由于在垃圾收集階段用戶線程還需要運(yùn)行,那也就是需要預(yù)留有足夠的內(nèi)存空間給用戶線程使用贬循,因此CMS收集器不能像其他收集器那樣等到老年代幾乎完全填滿在進(jìn)行收集咸包,需要留一部分空間提供并發(fā)收集時(shí)的程序運(yùn)作使用,當(dāng)在CMS運(yùn)行期間預(yù)留的內(nèi)存無法滿足程序需要就會(huì)出現(xiàn)一次Concurrent Mode Failure失敗杖虾,這個(gè)時(shí)候就會(huì)啟動(dòng)Serial Old收集器進(jìn)行老年代的垃圾收集烂瘫,
6. G1收集器
具有以下特點(diǎn),

  • 并行與并發(fā)
    充分利用多核多CPU奇适,縮短Stop The World的時(shí)間坟比,G1收集器通過并發(fā)的方式讓java程序繼續(xù)執(zhí)行
  • 分代收集
    與其他收集器一樣,分代概念也在G1中保存嚷往,G1不需要通過其他收集器配合就可以管理真?zhèn)€堆葛账,但是它可以通過不同的方式處理,
  • 空間整合
    G1從整體來看是基于標(biāo)記整理算法實(shí)現(xiàn)的皮仁,從局部來看是基于復(fù)制算法實(shí)現(xiàn)的籍琳,不會(huì)產(chǎn)生內(nèi)存碎片菲宴,收集后能提供規(guī)整的可用內(nèi)存,不會(huì)因?yàn)榉峙浯髮ο笳也坏竭B續(xù)內(nèi)存空間觸發(fā)GC
  • 可預(yù)測的停頓

G1可以讓使用者明確指定在一個(gè)長度為n毫秒的時(shí)間片段內(nèi)趋急,消耗在垃圾收集上的時(shí)間不能超過n毫秒喝峦,
具體過程
G1將對分為多個(gè)大小相等的獨(dú)立區(qū)域(Region),雖然保存著新生代與老年代的概念宣谈,但是不是物理隔離的愈犹,G1可以預(yù)測停頓時(shí)間,是因?yàn)槲懦螅谶M(jìn)行垃圾收集的時(shí)候漩怎,G1跟蹤各個(gè)Region里面的垃圾堆積的價(jià)值大小(回收所獲得的空間大小與回收所需要的時(shí)間的經(jīng)驗(yàn)值)嗦嗡,在后臺(tái)維護(hù)一個(gè)列表勋锤,每次根據(jù)允許的收集時(shí)間,優(yōu)先回收價(jià)值最大的Region侥祭,保證了G1收集器在有限時(shí)間內(nèi)有高效率
具體步驟:

  • 初始標(biāo)記
  • 并發(fā)標(biāo)記
  • 最終標(biāo)記
  • 篩選回收

初始標(biāo)記階段是標(biāo)記一下GC root能夠達(dá)到的對象叁执,會(huì)停頓用戶線程,但是時(shí)間很短矮冬,并發(fā)標(biāo)記是從GC Root開始從堆中對象進(jìn)行可達(dá)性分析谈宛,找出存活的對象,時(shí)間較長胎署,但是可以和用戶線程并發(fā)執(zhí)行吆录,最終標(biāo)記階段是為了修正在并發(fā)標(biāo)記期間因用戶程序繼續(xù)運(yùn)作而導(dǎo)致標(biāo)記產(chǎn)生變動(dòng)的那一部分,篩選回收琼牧,則是進(jìn)行回收

4恢筝、內(nèi)存分配與回收策略

Minor GC : 新生代的垃圾回收

Full GC:老年代的垃圾回收,也會(huì)回收新生代

1.對象優(yōu)先在Eden分配

大多數(shù)情況下巨坊,對象在新生代Eden區(qū)中分配撬槽,當(dāng)Eden沒有足夠空間分配,就是觸發(fā)Minor GC

2.大對象直接進(jìn)入老年代

大對象趾撵,指需要大量連續(xù)內(nèi)存空間的java對象侄柔,最典型的的就是那種很長的字符串和數(shù)組

3.長期存活的對象進(jìn)入老年代

在Eden區(qū)的對象經(jīng)過一次Minor GC,會(huì)被移動(dòng)到Survivor區(qū)占调,年齡加一勋拟,當(dāng)存活過一定時(shí)間,就會(huì)進(jìn)入老年區(qū)

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

當(dāng)survivor中相同年齡所有對象大小的總和大于survivor空間的一般妈候,年齡大于等于改年齡的對象可以直接進(jìn)入老年代,不需要達(dá)到指定年齡

5.空間分配擔(dān)保

在進(jìn)行Minor GC之前挂滓,虛擬機(jī)會(huì)檢查老年代的最大可用的連續(xù)空間是否大于新生區(qū)所有對象的總空間苦银,如果這個(gè)條件成立,那么這次Minor GC是安全的,如果不成立幔虏,虛擬機(jī)會(huì)查看HandlerPromotionFailure設(shè)置值是否允許擔(dān)保失敗纺念,如果允許那么會(huì)繼續(xù)檢查老年代最大可用連續(xù)空間是否大于歷次晉升到老年代對象的平均大小,如果大于想括,就嘗試著進(jìn)行一次Minor GC陷谱,盡管這次Minor GC是有風(fēng)險(xiǎn)的,如果小于瑟蜈,或者不允許冒險(xiǎn)烟逊,那么就進(jìn)行Full GC

更多內(nèi)容請看后續(xù)
QQ群:552113611

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市铺根,隨后出現(xiàn)的幾起案子宪躯,更是在濱河造成了極大的恐慌,老刑警劉巖位迂,帶你破解...
    沈念sama閱讀 207,248評論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件访雪,死亡現(xiàn)場離奇詭異,居然都是意外死亡掂林,警方通過查閱死者的電腦和手機(jī)臣缀,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,681評論 2 381
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來泻帮,“玉大人精置,你說我怎么就攤上這事⌒趟常” “怎么了氯窍?”我有些...
    開封第一講書人閱讀 153,443評論 0 344
  • 文/不壞的土叔 我叫張陵,是天一觀的道長蹲堂。 經(jīng)常有香客問我狼讨,道長,這世上最難降的妖魔是什么柒竞? 我笑而不...
    開封第一講書人閱讀 55,475評論 1 279
  • 正文 為了忘掉前任政供,我火速辦了婚禮,結(jié)果婚禮上朽基,老公的妹妹穿的比我還像新娘布隔。我一直安慰自己,他們只是感情好稼虎,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,458評論 5 374
  • 文/花漫 我一把揭開白布衅檀。 她就那樣靜靜地躺著,像睡著了一般霎俩。 火紅的嫁衣襯著肌膚如雪哀军。 梳的紋絲不亂的頭發(fā)上沉眶,一...
    開封第一講書人閱讀 49,185評論 1 284
  • 那天,我揣著相機(jī)與錄音杉适,去河邊找鬼谎倔。 笑死,一個(gè)胖子當(dāng)著我的面吹牛猿推,可吹牛的內(nèi)容都是我干的片习。 我是一名探鬼主播,決...
    沈念sama閱讀 38,451評論 3 401
  • 文/蒼蘭香墨 我猛地睜開眼蹬叭,長吁一口氣:“原來是場噩夢啊……” “哼藕咏!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起具垫,我...
    開封第一講書人閱讀 37,112評論 0 261
  • 序言:老撾萬榮一對情侶失蹤侈离,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后筝蚕,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體卦碾,經(jīng)...
    沈念sama閱讀 43,609評論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,083評論 2 325
  • 正文 我和宋清朗相戀三年起宽,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了洲胖。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 38,163評論 1 334
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡坯沪,死狀恐怖绿映,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情腐晾,我是刑警寧澤叉弦,帶...
    沈念sama閱讀 33,803評論 4 323
  • 正文 年R本政府宣布,位于F島的核電站藻糖,受9級(jí)特大地震影響淹冰,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜巨柒,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,357評論 3 307
  • 文/蒙蒙 一樱拴、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧洋满,春花似錦晶乔、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,357評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至驻民,卻和暖如春腺怯,著一層夾襖步出監(jiān)牢的瞬間袱饭,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,590評論 1 261
  • 我被黑心中介騙來泰國打工呛占, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人懦趋。 一個(gè)月前我還...
    沈念sama閱讀 45,636評論 2 355
  • 正文 我出身青樓晾虑,卻偏偏與公主長得像,于是被迫代替她去往敵國和親仅叫。 傳聞我的和親對象是個(gè)殘疾皇子帜篇,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,925評論 2 344

推薦閱讀更多精彩內(nèi)容