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

內(nèi)存管理機(jī)制中講述了java運(yùn)行時(shí)區(qū)域的各個(gè)部分,其中程序計(jì)數(shù)器年碘、虛擬機(jī)棧澈歉、本地方法棧3個(gè)區(qū)域隨線程而生,隨線程而滅屿衅。而java堆和方法區(qū)則不一樣埃难,這個(gè)部分的內(nèi)存的分配和回收都是動態(tài)的,垃圾收集器所關(guān)注的是這部分的內(nèi)存涤久。在堆中涡尘,垃圾收集器的回收率比較高,尤其是新生代响迂,一次大約可以回收70%到95%的空間考抄。而方法區(qū)(永久代)的回收效率遠(yuǎn)低于此。

一蔗彤、怎么判斷對象是無用的對象川梅?垃圾收集器主要對被判定無用的對象進(jìn)行回收。有以下幾種算法:1然遏、引用計(jì)數(shù)算法贫途;2、可達(dá)性分析算法待侵。

1丢早、引用計(jì)數(shù)算法是當(dāng)一個(gè)地方引用它是計(jì)數(shù)器就加1,引用失效時(shí)計(jì)數(shù)器就減1秧倾,計(jì)數(shù)器為0時(shí)就是沒有被引用的對象怨酝。很多主流虛擬機(jī)沒有使用這個(gè)算法,因?yàn)樗茈y解決對象之間互相循環(huán)引用的問題那先;

2农猬、可達(dá)性分析算法的基本思路是通過一系列被稱為“GC Roots”的對象最為起點(diǎn),從這些節(jié)點(diǎn)開始向下搜索售淡,搜索走過的路徑稱為引用鏈盛险,當(dāng)一個(gè)對象到GC Roots沒有引用鏈時(shí)瞄摊,就判定對象無引用】嗑颍可是為GC Roots的對象有:虛擬機(jī)棧(棧幀中的本地變量表)中的引用對象换帜、方法區(qū)中的類靜態(tài)屬性引用的對象、方法區(qū)中常量池引用的對象鹤啡、本地方法棧中JNI(一般說的本地方法惯驼,即Native方法)引用的對象。

二递瑰、什么是引用祟牲?如果reference類型的數(shù)據(jù)中儲存的數(shù)據(jù)代表的另一塊內(nèi)存的地址,那這個(gè)數(shù)據(jù)就是一個(gè)引用抖部。JDK1.2之后對引用進(jìn)行了擴(kuò)展说贝,分為:? 1、強(qiáng)引用慎颗;2乡恕、軟引用3、弱引用俯萎;4傲宜、虛引用。

1夫啊、強(qiáng)引用就是引用還存在函卒,垃圾收集器永遠(yuǎn)不會回收掉被引用的對象;

2撇眯、軟引用是在系統(tǒng)將要發(fā)生內(nèi)存溢出前把這些對象列進(jìn)回收范圍之中進(jìn)行二次回收报嵌,如果內(nèi)存還是不足,才拋出內(nèi)存溢出異常熊榛,軟引用使用SoftReference類來實(shí)現(xiàn)沪蓬;

3、弱引用是對象只能活到下一次垃圾收集發(fā)生之前来候,無論內(nèi)存是否足夠,都會被回收掉逸雹。弱引用使用WeakReference類實(shí)現(xiàn)营搅;

4、虛引用完全不會對其生存時(shí)間構(gòu)成影響梆砸,也無法通過虛引用獲得對象實(shí)例转质。虛引用的唯一作用就是在實(shí)例被回收之前收到系統(tǒng)的通知。使用PhantomReference類來實(shí)現(xiàn)虛引用帖世。

三休蟹、對象的finalize()方法沸枯。對象在被判定沒有引用后和被垃圾回收之前會至少進(jìn)行2次標(biāo)記,第一次為可達(dá)性算法判定對象沒有引用鏈時(shí)赂弓,會對還有必要執(zhí)行finalize()方法的對象進(jìn)行標(biāo)記绑榴,當(dāng)對象沒有覆蓋finalize()方法或者該方法已經(jīng)被執(zhí)行過后,虛擬機(jī)將視為沒有必要執(zhí)行此方法盈魁。之后隊(duì)列被放進(jìn)一個(gè)F-Queue隊(duì)列等待執(zhí)行finalize()方法翔怎,然后GC將對對象進(jìn)行第二次標(biāo)記。

四杨耙、方法區(qū)(永久代)的回收內(nèi)容主要是兩部分:廢棄常量和無用的類赤套。廢棄常量:如常量池中的“abc”,如果沒有一個(gè)String對象叫做“abc”也沒有其他類使用“abc”珊膜,那這個(gè)常量就是廢棄常量容握。判定一個(gè)類是無用的類有三個(gè)必要條件:1、該類所有的實(shí)例都已經(jīng)被回收车柠,也就是java堆中不存在該類的實(shí)例剔氏;2、加載該類的ClassLoader已經(jīng)被回收堪遂;3介蛉、該類對java.lang.Class對象沒有在任何地方被引用,無法再任何地方通過反射訪問該類的方法溶褪。

五币旧、垃圾收集算法

1、標(biāo)記-清除算法? 是將被標(biāo)記為可回收的對象進(jìn)行清除猿妈,此算法有兩大問題:效率問題和空間問題吹菱。因?yàn)闃?biāo)記和清除兩個(gè)過程效率都不高,并且清除后的內(nèi)存空間不連續(xù)彭则;

2鳍刷、復(fù)制算法? 是將內(nèi)存分為兩塊,一塊滿時(shí)就將存活的對象按順序的復(fù)制到另一塊內(nèi)存中俯抖,然后將原有的類刪除输瓜。有點(diǎn)是實(shí)現(xiàn)簡單,運(yùn)行高效芬萍,但是可用內(nèi)存減小了一半尤揣。為此HotSpot虛擬機(jī)默認(rèn)Eden區(qū)和Survivor區(qū)的比例是8:1,以Eden區(qū)和一塊Suvivor區(qū)作為新生代柬祠,另一塊Suvivor區(qū)作為保留區(qū)域北戏,每當(dāng)垃圾回收時(shí)將存活的對象復(fù)制到保留區(qū)Suvivor中,清除新生代的所有對象漫蛔。如果存在對象100%存活的場景嗜愈,不能使用此算法

3旧蛾、標(biāo)記-整理算法? 標(biāo)記的過程和標(biāo)記-清除算法相同,然后讓所有的存活對象向一邊移動蠕嫁,然后將存活端邊的對象清除锨天。

4、分代收集算法? 只是把堆分成新生代和老年代拌阴,然后根據(jù)不同的代使用不同的回收算法绍绘。新生代一般使用復(fù)制算法,老年代則必須使用標(biāo)記-清除算法或者標(biāo)記-整理算法

六迟赃、收集器是收集算法的具體實(shí)現(xiàn)

1陪拘、Serial收集器(新生代、單線程纤壁、復(fù)制算法)? 是最基本左刽、發(fā)展歷史最悠久的收集器。它在JDK1.3之前是新生代的唯一選擇酌媒。這個(gè)收集器是一個(gè)單線程收集器欠痴,這里的單線程是指在收集器工作時(shí),必須暫停其他線程的工作秒咨,一般稱為Stop?The World喇辽。新生代采用復(fù)制算法,暫停所有線程雨席。

2菩咨、ParNew收集器(新生代、多線程陡厘、復(fù)制算法)? 其實(shí)就是Serial收集器的多線程版本抽米,出了使用多條線程進(jìn)行垃圾收集之外,其余行為包括Serial收集器可用所有控制參數(shù)(例如:-XX:SurvivorRatio糙置、-XX:PretenureSizeThreshold云茸、-XX:HandlePromotionFailure等)、收集算法谤饭、Stop The world标捺、對象分配規(guī)則、回收策略等都與Serial收集器一樣揉抵。使用-XX:+UseConcMarkSweepGC選項(xiàng)后默認(rèn)使用ParNew收集器亡容,也可以使用-XX:UseParNewGC來選擇使用」σǎ可以使用-XX:ParallelGCTreads來限制垃圾收集的線程數(shù)。

3身弊、parallel Scavenge收集器(新生代辟汰、多線程列敲、復(fù)制算法)? 它也是采用復(fù)制算法的收集器,看上去和ParNew都一樣帖汞,但是Parallel Scavenge收集器的目標(biāo)是達(dá)到一個(gè)可控制的吞吐量戴而。所謂吞吐量,是CPU用于運(yùn)行用戶代碼的時(shí)間與CPU總消耗時(shí)間的比值翩蘸,即吞吐量=運(yùn)行用戶代碼時(shí)間/(運(yùn)行用戶代碼時(shí)間+垃圾收集時(shí)間)所意。高吞吐量可盡快的運(yùn)行完用戶的代碼。Parallel Scavenge收集器提供了兩個(gè)準(zhǔn)確控制吞吐量的參數(shù)催首,分別是控制最大垃圾收集停頓時(shí)間的-XX:MaxGCPauseMills參數(shù)和直接設(shè)置垃圾收集時(shí)間和總時(shí)間的比例的-XX:GCTimeRatio扶踊。MaxGCPauseMills參數(shù)調(diào)的越大,垃圾收集次數(shù)越頻繁郎任,吞吐量就越小秧耗。打開-XX:+UseAdaptiveSizePolicy參數(shù)后,就不需要手工配置新生代大小舶治,Eden區(qū)和Suvivor區(qū)的比例等參數(shù)了分井。

4、Serail Old收集器(老年代霉猛,單線程尺锚、標(biāo)記-整理算法)??

5、Parallel Old收集器(老年代惜浅、多線程瘫辩、標(biāo)記-整理算法)?

6、CMS收集器(老年代赡矢、多線程并發(fā)杭朱、標(biāo)記清除算法)? 整個(gè)過程分為4個(gè)步驟:1、初始標(biāo)記(Stop The World)吹散;2弧械、并發(fā)標(biāo)記;3空民、重新標(biāo)記(Stop The World)刃唐;4、并發(fā)清除界轩。但是有三個(gè)缺點(diǎn):1画饥、對CPU資源敏感;2浊猾、無法處理浮動垃圾(在垃圾回收過程中產(chǎn)生的類)抖甘,JDK1.5之后老年代在使用了68%內(nèi)存后默認(rèn)開啟CMS收集器,可以通過-XX:CMSInitiatingOccupancyFranction參數(shù)來設(shè)置觸發(fā)半分比葫慎;3衔彻、標(biāo)記清除算法帶來的空間使用不充分薇宠,可以開啟-XX:+UseCMSCompactAtFullColection參數(shù)在觸發(fā)Full GC前整合碎片空間,但是停頓時(shí)間會相應(yīng)變長艰额。另一個(gè)參數(shù)-XX:CMSFullGCCsBeforeCompaction是設(shè)置多少次Full GC后必須出現(xiàn)一次整合枉侧。

7波闹、G1收集器? 結(jié)合了以上收集器的特點(diǎn),并行并發(fā),分代收集(G1收集器能獨(dú)立管理整個(gè)GC堆)掸宛,空間整合(G1收集器從整體上看是基于標(biāo)記-整理算法實(shí)現(xiàn)的贴见,從局部上看是基于復(fù)制算法實(shí)現(xiàn)的)佑力,可預(yù)測的停頓筋量。

六、內(nèi)存分配

1棕硫、對象優(yōu)先在Eden分配髓涯,當(dāng)Eden區(qū)內(nèi)存不足時(shí)會發(fā)生一次Minor GC可通過-XX:+PrintGCDetails打印日志哈扮。

2纬纪、大對象直接進(jìn)入老年代,需要連續(xù)內(nèi)存空間的Java對象比如很長的字符串和數(shù)組滑肉,程序應(yīng)該避免這種寫法包各。可以通過設(shè)置-XX:PertenureSizeThreshold參數(shù)來判斷內(nèi)存大于多少的對象直接被放到老年代靶庙。

3问畅、長期存活的對象將進(jìn)入老年代,在Eden區(qū)中經(jīng)過一側(cè)Minor GC后并且成功進(jìn)入到Survivor區(qū)的對象年齡計(jì)數(shù)器加1六荒,并且在之后的Minor

GC發(fā)生后繼續(xù)累加护姆,累加到閾值后進(jìn)入老年代,可以通過-XX:MaxTenuringThreshold參數(shù)設(shè)置這個(gè)閾值掏击。

4卵皂、動態(tài)對象年齡判定是指虛擬機(jī)并不是永遠(yuǎn)的要求對象年齡必須達(dá)到閾值后才能被轉(zhuǎn)移到老年代,如果Survivor區(qū)中相同年齡所有對象大小的總和大于Survivor空間的一半砚亭,年齡大于等于該年齡的對象直接被轉(zhuǎn)移到老年代灯变。

5、空間分配擔(dān)保是指在發(fā)生Minor GC之前虛擬機(jī)會先檢查老年代最大可用的連續(xù)空間是否大于新生代所有對象總空間捅膘,如果這個(gè)條件成立添祸,那么Minor GC可以確保是安全的。如果不成立寻仗,則虛擬機(jī)會查看HandelPromotionFailure設(shè)置值是否允許擔(dān)保失敗刃泌,如果允許。那么會繼續(xù)檢查老年代最大可用的連續(xù)空間是否大于歷次轉(zhuǎn)移到老年代對象的平均大小,如果大于耙替,則嘗試一次Minor GC鲤遥,這次GC會有風(fēng)險(xiǎn)。如果小于就進(jìn)行一次FULL GC(清理整個(gè)堆)林艘。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市混坞,隨后出現(xiàn)的幾起案子狐援,更是在濱河造成了極大的恐慌,老刑警劉巖究孕,帶你破解...
    沈念sama閱讀 211,265評論 6 490
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件啥酱,死亡現(xiàn)場離奇詭異,居然都是意外死亡厨诸,警方通過查閱死者的電腦和手機(jī)镶殷,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,078評論 2 385
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來微酬,“玉大人绘趋,你說我怎么就攤上這事】殴埽” “怎么了陷遮?”我有些...
    開封第一講書人閱讀 156,852評論 0 347
  • 文/不壞的土叔 我叫張陵,是天一觀的道長垦江。 經(jīng)常有香客問我帽馋,道長,這世上最難降的妖魔是什么比吭? 我笑而不...
    開封第一講書人閱讀 56,408評論 1 283
  • 正文 為了忘掉前任绽族,我火速辦了婚禮,結(jié)果婚禮上衩藤,老公的妹妹穿的比我還像新娘吧慢。我一直安慰自己,他們只是感情好慷彤,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,445評論 5 384
  • 文/花漫 我一把揭開白布娄蔼。 她就那樣靜靜地躺著,像睡著了一般底哗。 火紅的嫁衣襯著肌膚如雪岁诉。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,772評論 1 290
  • 那天跋选,我揣著相機(jī)與錄音涕癣,去河邊找鬼。 笑死,一個(gè)胖子當(dāng)著我的面吹牛坠韩,可吹牛的內(nèi)容都是我干的距潘。 我是一名探鬼主播,決...
    沈念sama閱讀 38,921評論 3 406
  • 文/蒼蘭香墨 我猛地睜開眼只搁,長吁一口氣:“原來是場噩夢啊……” “哼音比!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起氢惋,我...
    開封第一講書人閱讀 37,688評論 0 266
  • 序言:老撾萬榮一對情侶失蹤洞翩,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后焰望,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體骚亿,經(jīng)...
    沈念sama閱讀 44,130評論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,467評論 2 325
  • 正文 我和宋清朗相戀三年熊赖,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了来屠。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 38,617評論 1 340
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡震鹉,死狀恐怖俱笛,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情传趾,我是刑警寧澤嫂粟,帶...
    沈念sama閱讀 34,276評論 4 329
  • 正文 年R本政府宣布,位于F島的核電站墨缘,受9級特大地震影響星虹,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜镊讼,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,882評論 3 312
  • 文/蒙蒙 一宽涌、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧蝶棋,春花似錦卸亮、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,740評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至吃溅,卻和暖如春溶诞,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背决侈。 一陣腳步聲響...
    開封第一講書人閱讀 31,967評論 1 265
  • 我被黑心中介騙來泰國打工螺垢, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 46,315評論 2 360
  • 正文 我出身青樓枉圃,卻偏偏與公主長得像功茴,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個(gè)殘疾皇子孽亲,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,486評論 2 348

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