深入淺出 JVM - JVM 內(nèi)部結(jié)構(gòu)總結(jié)

目錄

  • 運(yùn)行時(shí)數(shù)據(jù)區(qū)域
  • 垃圾回收算法
  • 垃圾收集器

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

  • 線程私有區(qū)域
    • 程序計(jì)數(shù)器
    • Java 虛擬機(jī)棧
    • 本地方法棧
  • 線程共享區(qū)域
    • Java 堆
    • 方法區(qū)
    • 運(yùn)行時(shí)常量池(屬于方法區(qū)的一部分)

線程私有區(qū)域

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

程序計(jì)數(shù)器(Program Counter Register)是一塊較小的內(nèi)存空間,它可以看作是當(dāng)前線程所執(zhí)行的字節(jié)碼的行號(hào)指示器绰筛。字節(jié)碼解釋器工作時(shí)就是通過(guò)改變這個(gè)計(jì)數(shù)器的值來(lái)選取下一條需要執(zhí)行的字節(jié)碼指令枢泰,分支、循環(huán)铝噩、跳轉(zhuǎn)宗苍、異常處理、線程恢復(fù)等基礎(chǔ)功能都需要依賴這個(gè)計(jì)算器來(lái)完成薄榛。

由于 Java 虛擬機(jī)的多線程是通過(guò)線程輪流切換并分配處理器執(zhí)行時(shí)間的方式來(lái)實(shí)現(xiàn)的,在任何一個(gè)確定的時(shí)刻让歼,一個(gè)處理器(對(duì)于多核處理器來(lái)說(shuō)是一個(gè)內(nèi)核)都只會(huì)執(zhí)行一條線程中的指令敞恋。故為了線程切換后能恢復(fù)到正確的執(zhí)行位置,每條線程都需要有一個(gè)獨(dú)立的程序計(jì)數(shù)器谋右,各條線程之間計(jì)數(shù)器互不影響硬猫,獨(dú)立存儲(chǔ),所以這塊內(nèi)存區(qū)域是"線程私有"的區(qū)域。

Java 虛擬機(jī)棧

Java 虛擬機(jī)棧(Java Virtual Machine Stacks)也是線程私有的啸蜜,它的生命周期與線程相同坑雅。虛擬機(jī)棧描述的是 Java 方法執(zhí)行的內(nèi)存模型,每個(gè)方法在執(zhí)行的同時(shí)都會(huì)創(chuàng)建一個(gè)棧幀(Stack Frame)用于存儲(chǔ)局部變量表衬横、操作數(shù)棧裹粤、動(dòng)態(tài)鏈接、方法出口等信息蜂林。每個(gè)方法從調(diào)用直至執(zhí)行完成的過(guò)程遥诉,就對(duì)應(yīng)著一個(gè)棧幀在虛擬機(jī)棧中從入棧到出棧的過(guò)程。

本地方法棧

本地方法棧(Native Method Stack)與虛擬機(jī)棧所發(fā)揮的作用是非常相似的噪叙,它們之間的區(qū)別不過(guò)是虛擬機(jī)棧為虛擬機(jī)棧執(zhí)行 Java 方法(也就是字節(jié)碼)服務(wù)矮锈,而本地方法棧則為虛擬機(jī)使用到的 Native 方法服務(wù)。


線程共享區(qū)域

Java 堆

對(duì)于大多數(shù)應(yīng)用來(lái)說(shuō)睁蕾,Java 堆(Java Heap)是 Java 虛擬機(jī)所管理的內(nèi)存中最大的一塊苞笨。Java 堆是被所有線程共享的一塊內(nèi)存區(qū)域,在虛擬機(jī)啟動(dòng)是創(chuàng)建子眶。此內(nèi)存區(qū)域的唯一目的就是存放對(duì)象實(shí)例瀑凝,幾乎所有的對(duì)象實(shí)例都在這里分配內(nèi)存。這一點(diǎn)在 Java 虛擬機(jī)規(guī)范中的描述是:所有對(duì)象的實(shí)例以及數(shù)組都要在堆上分配壹店,但是隨著 JIT 編譯器的發(fā)展與逃逸分析技術(shù)逐漸成熟猜丹,棧上分配、標(biāo)量替換優(yōu)化技術(shù)將會(huì)導(dǎo)致一些微妙的變化發(fā)生硅卢,所有對(duì)象都分配在堆上也漸漸變得沒(méi)那么"絕對(duì)"了射窒。

方法區(qū)(非堆)

方法區(qū)(Method Area)與 Java 堆一樣,是各個(gè)線程共享的內(nèi)存區(qū)域将塑,它用于存儲(chǔ)已被虛擬機(jī)加載的類信息脉顿、常量、靜態(tài)變量点寥、即時(shí)編譯器編譯后的代碼等數(shù)據(jù)艾疟。雖然 Java 虛擬機(jī)規(guī)范把 Java 方法區(qū)描述為堆的一個(gè)邏輯部分,但是它卻有一個(gè)別名叫做 Non Heap(非堆)敢辩,目的應(yīng)該是與 Java 堆區(qū)分開(kāi)來(lái)蔽莱。

方法區(qū)也被開(kāi)發(fā)者成為"永久代"(Permanent Generation)。

運(yùn)行時(shí)常量池(屬于方法區(qū)的一部分)

Class 文件中除了有類的版本戚长、字段盗冷、方法、接口等描述信息外同廉,還有一項(xiàng)信息就是常量池(Constant Pool Table)仪糖,用于存放編譯期生成的各種字面量和符號(hào)引用柑司,這部分內(nèi)容將在類加載后進(jìn)入方法區(qū)的運(yùn)行時(shí)常量池中存放。


垃圾回收算法

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

如同名字一樣锅劝,算法分為"標(biāo)記"和"清除"兩個(gè)階段:首先標(biāo)記出所有需要回收的對(duì)象攒驰,在標(biāo)記完成后統(tǒng)一回收所有被標(biāo)記的對(duì)象,它的標(biāo)記過(guò)程其實(shí)在前一節(jié)講述對(duì)象標(biāo)記判定時(shí)已經(jīng)介紹過(guò)了故爵。之所以說(shuō)它是最基礎(chǔ)的算法玻粪,是因?yàn)楹罄m(xù)的收集算法都是基于這種思路并對(duì)其不足進(jìn)行改進(jìn)而得到的。

它的主要不足有兩個(gè):一個(gè)是效率問(wèn)題稠集,標(biāo)記和清除兩個(gè)過(guò)程的效率都不高奶段;另一個(gè)是空間問(wèn)題,標(biāo)記清除之后會(huì)產(chǎn)生大量不連續(xù)的內(nèi)存碎片剥纷,空間碎片太多可能會(huì)導(dǎo)致以后在程序運(yùn)行過(guò)程中需要分配較大對(duì)象時(shí)痹籍,無(wú)法找到足夠的連續(xù)內(nèi)存而不得不提前觸發(fā)另一次垃圾收集動(dòng)作。

復(fù)制算法

為了解決效率問(wèn)題晦鞋,復(fù)制(Copying)算法出現(xiàn)了蹲缠,它將可用內(nèi)存按容量劃分為大小相等的兩塊,每次只使用其中的一塊悠垛。當(dāng)這一塊的內(nèi)存用完了线定,就將還存活著的對(duì)象復(fù)制到另外一塊上面,然后再把已使用過(guò)的內(nèi)存空間一次清理掉确买。這樣就是每次只對(duì)其中一塊內(nèi)存進(jìn)行回收斤讥,內(nèi)存分配時(shí)也就不用考慮內(nèi)存碎片等復(fù)雜情況,只要移動(dòng)堆頂指針湾趾,按順序分配內(nèi)存即可芭商,實(shí)現(xiàn)簡(jiǎn)單,運(yùn)行高效搀缠。

這種算法的代價(jià)是將內(nèi)存縮小為了原來(lái)的一半铛楣,代價(jià)很大。這種算法也在特殊場(chǎng)景中會(huì)有很大用處艺普,比如回收新生代的時(shí)候簸州,IBM 公司的專門(mén)研究表明,新生代的對(duì)象 98% 是"朝生夕滅"的歧譬,所以不需要按照 1:1 的比例來(lái)劃分內(nèi)存區(qū)域岸浑,而是將內(nèi)存分為一塊較大的 Eden 空間和兩塊較小的 Survivor 空間,每次使用 Eden 空間和其中一塊 Survivor 空間瑰步。當(dāng)回收時(shí)助琐,將 Eden 空間和 Survivor 空間中還存活著的對(duì)象一次性地復(fù)制到另外一塊 Survivor 空間上,最后清理掉 Eden 和剛才使用過(guò)的 Survivor 空間面氓。這里肯定有一個(gè)具體空間分配比例兵钮,HotSpot 虛擬機(jī)默認(rèn) Eden:Survivor 為 8:1,也就是每次新生代中可用內(nèi)存為整個(gè)新生代的 90%(80%+10%)舌界,只有 10% 的內(nèi)存會(huì)被"浪費(fèi)"掘譬。當(dāng)然,98% 的對(duì)象可回收只是一般場(chǎng)景下的數(shù)據(jù)呻拌,JVM 沒(méi)有辦法保證每次回收都只有不多于 10% 的對(duì)象存活葱轩,當(dāng) Survivor 空間不夠用時(shí),需要依賴其它內(nèi)存(這里指老年代)進(jìn)行分配擔(dān)保(Handle Promotion)藐握。

內(nèi)存的分配擔(dān)保就好比我們現(xiàn)在使用支付寶里面的花唄靴拱,如果我們信譽(yù)很好,在 98% 的情況下都能按時(shí)償還猾普,于是支付寶會(huì)默認(rèn)我們會(huì)在下一月也能按時(shí)按量的償還我們的預(yù)支袜炕,只需要有一個(gè)擔(dān)保人能保證如果我下次不能還款時(shí),可以幫助你還錢(qián)初家,那支付寶就認(rèn)為我們預(yù)支花唄是沒(méi)有風(fēng)險(xiǎn)的偎窘。內(nèi)存的分配擔(dān)保也一樣,如果另外一塊 Survivor 空間沒(méi)有足夠空間存放上一次新生代收集下來(lái)的存活對(duì)象時(shí)溜在,這些對(duì)象將直接通過(guò)分配擔(dān)保機(jī)制進(jìn)入老年代陌知。具體怎么分配擔(dān)保會(huì)在后續(xù)分析。

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

復(fù)制收集算法在對(duì)象存活率較高時(shí)就要進(jìn)行較多的復(fù)制操作掖肋,效率將會(huì)變低仆葡。更關(guān)鍵的時(shí),如果不想浪費(fèi) 50% 的空間志笼,就需要有額外的空間進(jìn)行分配擔(dān)保沿盅,以應(yīng)對(duì)使用的內(nèi)存中所有對(duì)象都 100% 存活的極端情況,所以在老年代一般不能直接選用復(fù)制算法籽腕。

根據(jù)老年代存活時(shí)間較長(zhǎng)的特點(diǎn)嗡呼,有人提出了另一種"標(biāo)記-整理"(Mark-Compact)的算法,標(biāo)記過(guò)程仍然與"標(biāo)記-清除"算法一樣皇耗,但后續(xù)步驟不是直接對(duì)可回收對(duì)象進(jìn)行清理南窗,而是讓所有存活對(duì)象想一端移動(dòng),然后直接清理掉邊界以外的內(nèi)存郎楼。

分代收集算法

這種算法沒(méi)有什么新的思想万伤,只是根據(jù)對(duì)象存活周期的不同將內(nèi)存劃分為幾塊。一般把 Java 堆分為新生代和老年代呜袁,這樣就可以根據(jù)各個(gè)年代的特點(diǎn)采用最適當(dāng)?shù)乃惴ā?/p>

  • 新生代:復(fù)制算法

    因?yàn)樵谛律械新颍看卫厥諘r(shí)都發(fā)現(xiàn)有大批對(duì)象死去香缺,只有少量存活毙死,那就選用復(fù)制算法,只需付出少量存活對(duì)象的復(fù)制成本就可以完成收集。

  • 老年代:標(biāo)記-清理/標(biāo)記-整理

    因?yàn)槔夏甏鷮?duì)象存活率高柄错、沒(méi)有額外空間對(duì)它進(jìn)行分配擔(dān)保。

更多精彩原創(chuàng)內(nèi)容請(qǐng)關(guān)注:JavaInterview狼渊,歡迎 star拴念,支持鼓勵(lì)以下作者,萬(wàn)分感謝春畔。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末脱货,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子律姨,更是在濱河造成了極大的恐慌振峻,老刑警劉巖,帶你破解...
    沈念sama閱讀 211,265評(píng)論 6 490
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件择份,死亡現(xiàn)場(chǎng)離奇詭異扣孟,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī)缓淹,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,078評(píng)論 2 385
  • 文/潘曉璐 我一進(jìn)店門(mén)哈打,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人讯壶,你說(shuō)我怎么就攤上這事料仗。” “怎么了伏蚊?”我有些...
    開(kāi)封第一講書(shū)人閱讀 156,852評(píng)論 0 347
  • 文/不壞的土叔 我叫張陵立轧,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我躏吊,道長(zhǎng)氛改,這世上最難降的妖魔是什么? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 56,408評(píng)論 1 283
  • 正文 為了忘掉前任比伏,我火速辦了婚禮胜卤,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘赁项。我一直安慰自己葛躏,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,445評(píng)論 5 384
  • 文/花漫 我一把揭開(kāi)白布悠菜。 她就那樣靜靜地躺著舰攒,像睡著了一般。 火紅的嫁衣襯著肌膚如雪悔醋。 梳的紋絲不亂的頭發(fā)上摩窃,一...
    開(kāi)封第一講書(shū)人閱讀 49,772評(píng)論 1 290
  • 那天,我揣著相機(jī)與錄音芬骄,去河邊找鬼猾愿。 笑死鹦聪,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的匪蟀。 我是一名探鬼主播椎麦,決...
    沈念sama閱讀 38,921評(píng)論 3 406
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼材彪!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起琴儿,我...
    開(kāi)封第一講書(shū)人閱讀 37,688評(píng)論 0 266
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤段化,失蹤者是張志新(化名)和其女友劉穎,沒(méi)想到半個(gè)月后造成,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體显熏,經(jīng)...
    沈念sama閱讀 44,130評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,467評(píng)論 2 325
  • 正文 我和宋清朗相戀三年晒屎,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了喘蟆。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 38,617評(píng)論 1 340
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡鼓鲁,死狀恐怖蕴轨,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情骇吭,我是刑警寧澤橙弱,帶...
    沈念sama閱讀 34,276評(píng)論 4 329
  • 正文 年R本政府宣布,位于F島的核電站燥狰,受9級(jí)特大地震影響棘脐,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜龙致,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,882評(píng)論 3 312
  • 文/蒙蒙 一蛀缝、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧目代,春花似錦屈梁、人聲如沸。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 30,740評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至忽冻,卻和暖如春真朗,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背僧诚。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 31,967評(píng)論 1 265
  • 我被黑心中介騙來(lái)泰國(guó)打工遮婶, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留蝗碎,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 46,315評(píng)論 2 360
  • 正文 我出身青樓旗扑,卻偏偏與公主長(zhǎng)得像蹦骑,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子臀防,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,486評(píng)論 2 348

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

  • 內(nèi)存溢出和內(nèi)存泄漏的區(qū)別 內(nèi)存溢出:out of memory眠菇,是指程序在申請(qǐng)內(nèi)存時(shí),沒(méi)有足夠的內(nèi)存空間供其使用袱衷,...
    Aimerwhy閱讀 732評(píng)論 0 1
  • 《深入理解Java虛擬機(jī)》筆記_第一遍 先取看完這本書(shū)(JVM)后必須掌握的部分捎废。 第一部分 走近 Java 從傳...
    xiaogmail閱讀 5,067評(píng)論 1 34
  • 一、運(yùn)行時(shí)數(shù)據(jù)區(qū)域 Java虛擬機(jī)管理的內(nèi)存包括幾個(gè)運(yùn)行時(shí)數(shù)據(jù)內(nèi)存:方法區(qū)致燥、虛擬機(jī)棧登疗、本地方法棧、堆嫌蚤、程序計(jì)數(shù)器辐益,...
    luhanlin閱讀 541評(píng)論 0 0
  • 第二部分 自動(dòng)內(nèi)存管理機(jī)制 第二章 java內(nèi)存異常與內(nèi)存溢出異常 運(yùn)行數(shù)據(jù)區(qū)域 程序計(jì)數(shù)器:當(dāng)前線程所執(zhí)行的字節(jié)...
    小明oh閱讀 1,136評(píng)論 0 2
  • 一、運(yùn)行時(shí)數(shù)據(jù)區(qū)域 Java虛擬機(jī)管理的內(nèi)存包括幾個(gè)運(yùn)行時(shí)數(shù)據(jù)內(nèi)存:方法區(qū)脱吱、虛擬機(jī)棧智政、本地方法棧、堆急凰、程序計(jì)數(shù)器女仰,...
    加油小杜閱讀 1,514評(píng)論 1 15