Java虛擬機(一)—內(nèi)存管理

運行時數(shù)據(jù)區(qū)域

程序計數(shù)器

當(dāng)前線程所執(zhí)行的字節(jié)碼的行號指示器,雇锡,字節(jié)碼解釋器工作時就是通過改變這個計數(shù)器的值來選取下一條要執(zhí)行的字節(jié)碼,每個線程有獨立的程序計數(shù)器曙痘,是線程私有的

Java虛擬機棧

也是線程私有的立肘,生命周期與線程相同谅年。虛擬機棧是描述Java方法執(zhí)行的內(nèi)存模型,每個方法被執(zhí)行的時候都會創(chuàng)建一個棧幀(stack frame)用于存放局部變量表融蹂、操作棧、動態(tài)鏈接和方法出口等信息区拳。每一個方法從開始執(zhí)行到結(jié)束就對應(yīng)著一個棧幀在虛擬機棧從入棧到出棧的過程樱调。

  • 線程請求棧深度大于虛擬機允許的深度,拋出StackOverflowError的異常
  • 當(dāng)虛擬機動態(tài)擴展后仍無法申請足夠的內(nèi)存時拋出OutOfMemoryError的異常

Java方法棧

與Java虛擬機棧類似圣猎,為虛擬機使用到的native方法進行服務(wù)

Java堆

堆是被所有線程共享的內(nèi)存區(qū)域菩颖,用于存放對象實例,是垃圾收集器管理的主要區(qū)域,不一定在連續(xù)的內(nèi)存空間上鳍怨,只要邏輯連續(xù)即可鞋喇。

方法區(qū)

是各個線程共享的區(qū)域,用于存放已被虛擬機加載的類信息落塑、常量罐韩、靜態(tài)變量和即時編譯器編譯后的代碼等數(shù)據(jù)。

運行時常量池

是方法區(qū)的一部分龙考,用于存放編譯期間生成的各種字面量和符號引用矾睦。

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

根搜索算法

通過GC root的對象作為起點,從這些節(jié)點開始向下搜索缓溅,搜索的過程稱為引用鏈赁温,當(dāng)一個對象到GC root沒有任何引用鏈相連的時候,則證明此對象是不可用的酝陈〕涟铮可以作為GC root的對象包括以下幾種

  • 虛擬機棧中引用的對象
  • 方法區(qū)中的類靜態(tài)屬性引用的對象
  • 方法區(qū)中常量引用的對象
  • native方法中引用的對象

引用

  • 強引用(String Reference): 只要強引用還在,垃圾收集器永遠不會回收被引用對象
  • 軟引用(Soft Reference): 在內(nèi)存不足時待牵,垃圾收集器會回收這部分對象
  • 弱引用(Weak Reference): 弱引用的對象只能存活到下次GC之前喇勋,無論內(nèi)存是否夠用都會被回收
  • 虛引用(Phantom Reference): 一個對象是否有虛引用都不會對它的生存時間產(chǎn)生影響,也無法通過虛引用來取得一個對象實例贰拿,熄云,為對象設(shè)置虛引用的目的是希望這個對象被回收時收到一個系統(tǒng)通知

對象回收過程

一個對象被回收需要經(jīng)歷兩次標記過程缴允,如果一個對象在經(jīng)過根搜索之后沒有與GC root相連的引用鏈,那么它會被第一次標記并進行篩選矗漾,篩選的條件是該對象有沒有必要執(zhí)行finalize()方法薄料,沒有必要執(zhí)行的條件

  • 對象有沒有覆蓋finalize()
  • finalize()是否已經(jīng)被虛擬機調(diào)用過

如果被認為有必要執(zhí)行,這個對象會被放到F-Queue的隊列中嫡锌,并放在由一條虛擬機創(chuàng)建的低優(yōu)先級Finalizer線程中去執(zhí)行琳钉。執(zhí)行操作由虛擬機觸發(fā),不保證會等到執(zhí)行結(jié)束啦桌。稍后GC將對F-Queue中的對象進行二次小規(guī)模標記,如果對象成功在finalize()方法中重新和引用鏈上任意對象創(chuàng)建關(guān)聯(lián)且改,在二次標記的時候會被移除F-Queue板驳,如果沒有的話就會很快被回收。

  • finalize()只會被調(diào)用一次

回收方法區(qū)

收益比較低慨蓝,主要回收兩部分內(nèi)容

  • 廢棄常量
  • 無用的類

如果常量池中有常量不再被引用礼烈,將被從常量池中移除婆跑。判定無用的類的條件

  • 該類所有實例都應(yīng)經(jīng)被回收,即Java堆中不存在該類的任何實例
  • 加載該類的ClassLoader被回收
  • 該類對應(yīng)的java.lang.Class對象沒有被引用犀忱,無法通過反射訪問該類

垃圾收集算法

標記-清除算法

首先標記需要回收的對象郊供,在標記完后統(tǒng)一進行回收,缺點

  • 效率問題: 標記和清除的效率都不高
  • 空間問題: 會產(chǎn)生大量不連續(xù)的內(nèi)存碎片

復(fù)制算法

劃分兩塊大小相等的內(nèi)存,每次用一塊疯淫,當(dāng)這塊內(nèi)存用完了戳玫,就將活著的內(nèi)存復(fù)制到另一塊內(nèi)存上咕宿,然后把已使用的內(nèi)存清理掉。

  • 優(yōu)點

    • 實現(xiàn)簡單
    • 運行高效
  • 缺點

    • 內(nèi)存使用量翻倍

用來回收新生代缆镣,將內(nèi)存分為較大的Eden區(qū)和兩塊較小的Survivor區(qū)试浙,當(dāng)回收時將Eden和Survivor中存活的對象拷貝到另一個Survivor中,然后清除掉Eden和第一塊Survivor钠糊,當(dāng)Survivor空間不足時這些對象會被存放到老年代。HotSpot虛擬機默認Eden和Survivor的大小比例是8:1艘刚。

標記-整理算法

老年代中使用截珍,過程和標記-清除算法一樣,后續(xù)不回收云稚,而是將對象向一端移動沈堡,最后直接清除掉邊界以外的內(nèi)存

分代收集算法

新生代--復(fù)制算法
老年代--標記整理算法

垃圾收集器

Serial收集器

單線程收集器诞丽,進行垃圾收集時必須暫停其它所有工作線程

ParNew收集器

多線程的Serial收集器

Parallel Scavenge收集器

使用復(fù)制算法的收集器僧免,和其它收集器區(qū)別

  • CMS等關(guān)注用戶線程等待時間,Parallel Scavenge收集器的目的是達到一個可控制的吞吐量撞叨,高吞吐量意味著更高效率的使用CPU浊洞,主要用于后臺不需要交互的任務(wù)

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

Serial Old收集器

Serial的老年代版本,使用標記-整理算法

Parallel Old收集器

Parallel Scavenge的老年代版本枷餐,使用標記整理算法

CMS(Concurrent Mark Sweep)收集器

CMS時一種獲取最短停頓時間為目標的收集器

  • 過程

    • 初始標記
    • 并發(fā)標記
    • 重新標記
    • 并發(fā)清除
  • 缺點

    • 對CPU資源敏感
    • 無法處理浮動垃圾毛肋,可能出現(xiàn)Concurrent Mode Failure失敗導(dǎo)致Full GC
    • CMS采用標記-清除算法屋剑,會產(chǎn)生內(nèi)存碎片

G1收集器

  • 基于標記-整理算法
  • 可以非常精準的控制停頓,可以不犧牲吞吐量的前提下完成低停頓的內(nèi)存回收

內(nèi)存分配與回收策略

  • 對象優(yōu)先在Eden分配: 當(dāng)Eden沒有足夠的空間時虛擬機發(fā)起一次Minor GC
  • 大對象直接進入老年代: 大對象指需要大量連續(xù)儲存空間的Java對象趁桃,例如長字符串卫病、數(shù)組(byte[])等
  • 長期存活對象進入老年代: 虛擬機給每個對象定義一個對象年齡計數(shù)器,對象在Eden生成后進過一次Minor GC后仍能存活益咬,并能放入Survivor中帜平,年齡設(shè)為1,以后每經(jīng)過一次Minor GC年齡都加1冗锁,當(dāng)年齡增加到一定閾值的時候進入老年代
  • 動態(tài)對象年齡判定: 如果在Survivor中相同年齡所有對象大小的綜合等于Survivor一半的時候嗤栓,年齡大于等于該年齡進入老年代

參考

  • 深入理解Java虛擬機, 周志明
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末茉帅,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子擂错,更是在濱河造成了極大的恐慌樱蛤,老刑警劉巖昨凡,帶你破解...
    沈念sama閱讀 218,386評論 6 506
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異,居然都是意外死亡形用,警方通過查閱死者的電腦和手機就轧,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,142評論 3 394
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來田度,“玉大人妒御,你說我怎么就攤上這事≌蚪龋” “怎么了乎莉?”我有些...
    開封第一講書人閱讀 164,704評論 0 353
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經(jīng)常有香客問我惋啃,道長哼鬓,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,702評論 1 294
  • 正文 為了忘掉前任异希,我火速辦了婚禮,結(jié)果婚禮上绒瘦,老公的妹妹穿的比我還像新娘称簿。我一直安慰自己,他們只是感情好惰帽,可當(dāng)我...
    茶點故事閱讀 67,716評論 6 392
  • 文/花漫 我一把揭開白布憨降。 她就那樣靜靜地躺著,像睡著了一般该酗。 火紅的嫁衣襯著肌膚如雪授药。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,573評論 1 305
  • 那天垂涯,我揣著相機與錄音烁焙,去河邊找鬼。 笑死耕赘,一個胖子當(dāng)著我的面吹牛骄蝇,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播操骡,決...
    沈念sama閱讀 40,314評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼九火,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了册招?” 一聲冷哼從身側(cè)響起岔激,我...
    開封第一講書人閱讀 39,230評論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎是掰,沒想到半個月后虑鼎,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,680評論 1 314
  • 正文 獨居荒郊野嶺守林人離奇死亡键痛,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,873評論 3 336
  • 正文 我和宋清朗相戀三年炫彩,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片絮短。...
    茶點故事閱讀 39,991評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡江兢,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出丁频,到底是詐尸還是另有隱情杉允,我是刑警寧澤邑贴,帶...
    沈念sama閱讀 35,706評論 5 346
  • 正文 年R本政府宣布,位于F島的核電站叔磷,受9級特大地震影響拢驾,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜世澜,卻給世界環(huán)境...
    茶點故事閱讀 41,329評論 3 330
  • 文/蒙蒙 一独旷、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧寥裂,春花似錦嵌洼、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,910評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至诺舔,卻和暖如春鳖昌,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背低飒。 一陣腳步聲響...
    開封第一講書人閱讀 33,038評論 1 270
  • 我被黑心中介騙來泰國打工许昨, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人褥赊。 一個月前我還...
    沈念sama閱讀 48,158評論 3 370
  • 正文 我出身青樓糕档,卻偏偏與公主長得像,于是被迫代替她去往敵國和親拌喉。 傳聞我的和親對象是個殘疾皇子速那,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 44,941評論 2 355

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

  • 《深入理解Java虛擬機》筆記_第一遍 先取看完這本書(JVM)后必須掌握的部分。 第一部分 走近 Java 從傳...
    xiaogmail閱讀 5,093評論 1 34
  • 第二部分 自動內(nèi)存管理機制 第二章 java內(nèi)存異常與內(nèi)存溢出異常 運行數(shù)據(jù)區(qū)域 程序計數(shù)器:當(dāng)前線程所執(zhí)行的字節(jié)...
    小明oh閱讀 1,164評論 0 2
  • 好姐姐
    煙澀寒閱讀 143評論 0 0
  • 隨著年齡越來越大尿背,身邊的朋友也都一個個結(jié)婚生子端仰,大家都開始進入了人生的另一個階段。我一直想著田藐,結(jié)婚后就開始了油鹽...
    清荷he閱讀 152評論 0 0
  • 我是一個拒絕在任何湯湯水水中加糖的人荔烧,就算是豆?jié){奶茶咖啡,從來都是選擇無糖汽久。 我不愛吃糖茴晋,困擾很多孩童的蛀牙問題從...
    流蘇月白閱讀 501評論 0 0