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

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

程序計(jì)數(shù)器

當(dāng)前線程所執(zhí)行的字節(jié)碼的行號(hào)指示器,,字節(jié)碼解釋器工作時(shí)就是通過(guò)改變這個(gè)計(jì)數(shù)器的值來(lái)選取下一條要執(zhí)行的字節(jié)碼,每個(gè)線程有獨(dú)立的程序計(jì)數(shù)器,是線程私有的

Java虛擬機(jī)棧

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

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

Java方法棧

與Java虛擬機(jī)棧類(lèi)似,為虛擬機(jī)使用到的native方法進(jìn)行服務(wù)

Java堆

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

方法區(qū)

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

運(yùn)行時(shí)常量池

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

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

根搜索算法

通過(guò)GC root的對(duì)象作為起點(diǎn),從這些節(jié)點(diǎn)開(kāi)始向下搜索,搜索的過(guò)程稱(chēng)為引用鏈,當(dāng)一個(gè)對(duì)象到GC root沒(méi)有任何引用鏈相連的時(shí)候,則證明此對(duì)象是不可用的。可以作為GC root的對(duì)象包括以下幾種

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

引用

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

對(duì)象回收過(guò)程

一個(gè)對(duì)象被回收需要經(jīng)歷兩次標(biāo)記過(guò)程,如果一個(gè)對(duì)象在經(jīng)過(guò)根搜索之后沒(méi)有與GC root相連的引用鏈,那么它會(huì)被第一次標(biāo)記并進(jìn)行篩選,篩選的條件是該對(duì)象有沒(méi)有必要執(zhí)行finalize()方法,沒(méi)有必要執(zhí)行的條件

  • 對(duì)象有沒(méi)有覆蓋finalize()
  • finalize()是否已經(jīng)被虛擬機(jī)調(diào)用過(guò)

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

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

回收方法區(qū)

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

  • 廢棄常量
  • 無(wú)用的類(lèi)

如果常量池中有常量不再被引用,將被從常量池中移除。判定無(wú)用的類(lèi)的條件

  • 該類(lèi)所有實(shí)例都應(yīng)經(jīng)被回收,即Java堆中不存在該類(lèi)的任何實(shí)例
  • 加載該類(lèi)的ClassLoader被回收
  • 該類(lèi)對(duì)應(yīng)的java.lang.Class對(duì)象沒(méi)有被引用,無(wú)法通過(guò)反射訪問(wèn)該類(lèi)

垃圾收集算法

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

首先標(biāo)記需要回收的對(duì)象,在標(biāo)記完后統(tǒng)一進(jìn)行回收,缺點(diǎn)

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

復(fù)制算法

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

  • 優(yōu)點(diǎn)

    • 實(shí)現(xiàn)簡(jiǎn)單
    • 運(yùn)行高效
  • 缺點(diǎn)

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

用來(lái)回收新生代,將內(nèi)存分為較大的Eden區(qū)和兩塊較小的Survivor區(qū),當(dāng)回收時(shí)將Eden和Survivor中存活的對(duì)象拷貝到另一個(gè)Survivor中,然后清除掉Eden和第一塊Survivor,當(dāng)Survivor空間不足時(shí)這些對(duì)象會(huì)被存放到老年代。HotSpot虛擬機(jī)默認(rèn)Eden和Survivor的大小比例是8:1。

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

老年代中使用,過(guò)程和標(biāo)記-清除算法一樣,后續(xù)不回收,而是將對(duì)象向一端移動(dòng),最后直接清除掉邊界以外的內(nèi)存

分代收集算法

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

垃圾收集器

Serial收集器

單線程收集器,進(jìn)行垃圾收集時(shí)必須暫停其它所有工作線程

ParNew收集器

多線程的Serial收集器

Parallel Scavenge收集器

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

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

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

Serial Old收集器

Serial的老年代版本,使用標(biāo)記-整理算法

Parallel Old收集器

Parallel Scavenge的老年代版本,使用標(biāo)記整理算法

CMS(Concurrent Mark Sweep)收集器

CMS時(shí)一種獲取最短停頓時(shí)間為目標(biāo)的收集器

  • 過(guò)程

    • 初始標(biāo)記
    • 并發(fā)標(biāo)記
    • 重新標(biāo)記
    • 并發(fā)清除
  • 缺點(diǎn)

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

G1收集器

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

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

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

參考

  • 深入理解Java虛擬機(jī), 周志明
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 229,836評(píng)論 6 540
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 99,275評(píng)論 3 428
  • 文/潘曉璐 我一進(jìn)店門(mén),熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人,你說(shuō)我怎么就攤上這事。” “怎么了?”我有些...
    開(kāi)封第一講書(shū)人閱讀 177,904評(píng)論 0 383
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我,道長(zhǎng),這世上最難降的妖魔是什么? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 63,633評(píng)論 1 317
  • 正文 為了忘掉前任,我火速辦了婚禮,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 72,368評(píng)論 6 410
  • 文/花漫 我一把揭開(kāi)白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上,一...
    開(kāi)封第一講書(shū)人閱讀 55,736評(píng)論 1 328
  • 那天,我揣著相機(jī)與錄音,去河邊找鬼。 笑死,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,740評(píng)論 3 446
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起,我...
    開(kāi)封第一講書(shū)人閱讀 42,919評(píng)論 0 289
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 49,481評(píng)論 1 335
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 41,235評(píng)論 3 358
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 43,427評(píng)論 1 374
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,968評(píng)論 5 363
  • 正文 年R本政府宣布,位于F島的核電站,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 44,656評(píng)論 3 348
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 35,055評(píng)論 0 28
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 36,348評(píng)論 1 294
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 52,160評(píng)論 3 398
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 48,380評(píng)論 2 379

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

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