[JVM知識(shí)點(diǎn)梳理]JVM之內(nèi)存管理機(jī)制

運(yùn)行時(shí)內(nèi)存區(qū)域劃分

Java源文件(.java文件)會(huì)被Java編譯器編譯為字節(jié)碼文件(.class文件),再由JVM中的類加載器去加載各個(gè)類的字節(jié)碼文件弦疮,加載完成后交給JVM執(zhí)行引擎執(zhí)行夹攒。

在Java程序執(zhí)行過(guò)程中,會(huì)動(dòng)態(tài)地將內(nèi)存劃分為如下幾大區(qū)域:

  • 虛擬機(jī)棧
  • 方法區(qū)
  • 程序計(jì)數(shù)器
  • 本地方法棧

其中這些區(qū)域又可劃分為兩大類

  • 由所有線程共享的區(qū)域

    方法區(qū)胁塞、堆咏尝、本地方法棧

  • 線程私有的數(shù)據(jù)區(qū)

    虛擬機(jī)棧压语、程序計(jì)數(shù)器

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

  • 是一塊較小的內(nèi)存
  • 作用:當(dāng)前線程所執(zhí)行的字節(jié)碼的行號(hào)指示器
  • 通過(guò)改變這個(gè)計(jì)數(shù)器的值來(lái)選取下一條需要執(zhí)行的字節(jié)碼指令
  • 為了線程切換后能恢復(fù)到正確的執(zhí)行位置,因此每條線程都需要一個(gè)獨(dú)立的程序計(jì)數(shù)器编检,各條線程之間的計(jì)數(shù)器互不影響胎食,獨(dú)立存儲(chǔ)
  • 它的區(qū)域?yàn)椤熬€程私有”的內(nèi)存
  • 此內(nèi)存區(qū)域是唯一一個(gè)在Java虛擬機(jī)規(guī)范中沒(méi)有規(guī)定任何OutOfMemoryError情況的區(qū)域

在Java的內(nèi)存分配中有這么一段話:

如果線程正在執(zhí)行的是一個(gè)Java方法,這個(gè)計(jì)數(shù)器記錄的是正在執(zhí)行的虛擬機(jī)字節(jié)碼指令的地址允懂;如果正在執(zhí)行的是Native方法厕怜,這個(gè)計(jì)數(shù)器值為空。

上述這句話引入了一個(gè)問(wèn)題:

我們知道蕾总,程序計(jì)數(shù)器用來(lái)存放字節(jié)碼指令的地址粥航;通過(guò)這個(gè)地址,虛擬機(jī)就能知道執(zhí)行到哪里谤专,以下下一步執(zhí)行什么躁锡,但是調(diào)用native方法,值就變空了置侍,那么機(jī)器不就直接崩潰了嗎映之?

解釋:當(dāng)線程中調(diào)用native方法的時(shí)候,則重新啟動(dòng)一個(gè)新的線程蜡坊,那么新的線程的計(jì)數(shù)器為空則不會(huì)影響當(dāng)前線程的計(jì)數(shù)器杠输,相互獨(dú)立。而調(diào)用此方法的線程就會(huì)處于阻塞狀態(tài)秕衙,直到另外一個(gè)線程執(zhí)行結(jié)束才會(huì)恢復(fù)到運(yùn)行狀態(tài)

虛擬機(jī)棧

  • 線程私有蠢甲,聲明周期與線程相同
  • 方法在執(zhí)行時(shí)會(huì)創(chuàng)建一個(gè)棧幀,每一個(gè)方法被調(diào)用直至執(zhí)行完成的過(guò)程据忘,就對(duì)應(yīng)一個(gè)棧幀在虛擬機(jī)棧中從入棧到出棧的過(guò)程

上面提到了棧幀鹦牛,那么什么是棧幀呢
解釋:棧幀用來(lái)存儲(chǔ)局部變量表操作棧勇吊、動(dòng)態(tài)鏈接曼追、方法出口等信息。

局部變量表

  • 存放編譯期可知的各種基本類型數(shù)據(jù)(boolean汉规、byte礼殊、charshort针史、int晶伦、floatlong啄枕、double)婚陪、對(duì)象引用(reference類型)和returnAddress類型(指向了一條字節(jié)碼指令的地址)
  • 除了64位的longdouble類型的數(shù)據(jù)會(huì)占用2個(gè)局部變量空間,其余的數(shù)據(jù)類型只占用1個(gè)
  • 當(dāng)進(jìn)入一個(gè)方法频祝,這個(gè)方法需要在棧幀中分配多大局部變量空間時(shí)完全確定的近忙,方法在運(yùn)行期間不會(huì)改變局部變量表的大小

棧異常

  • 線程請(qǐng)求的的棧深度大于虛擬機(jī)所允許的深度竭业,將拋出StackOverflowError異常
  • 若虛擬機(jī)可動(dòng)態(tài)擴(kuò)展(當(dāng)前大部分的Java虛擬機(jī)都可動(dòng)態(tài)擴(kuò)展,只不過(guò)Java虛擬機(jī)規(guī)范中也允許固定長(zhǎng)度的虛擬機(jī)棧)及舍,但擴(kuò)展無(wú)法申請(qǐng)到足夠內(nèi)存時(shí)會(huì)拋出StackOverflowError異常

本地方法棧

  • 與虛擬機(jī)棧的作用類似
  • 區(qū)別:虛擬機(jī)棧為虛擬機(jī)執(zhí)行Java方法服務(wù)未辆,而本地方法則為虛擬機(jī)使用到的Native方法服務(wù)
  • Sun HotSpot虛擬機(jī)直接把本地方法棧和虛擬機(jī)棧合二為一
  • 本地方法棧也會(huì)拋出StackOverflowErrorOutOfMemoryError異常

Java堆

  • 是Java虛擬機(jī)所管理的內(nèi)存中最大的一塊
  • 被所有線程共享
  • 所有的對(duì)象實(shí)例以及數(shù)組都要在堆上分配
  • 現(xiàn)在的收集器基本都采用分代收集算法,所以Java堆還可以細(xì)分為:新生代老生代
  • 如果堆中沒(méi)有內(nèi)存完成實(shí)例分配锯玛,并且堆也無(wú)法再擴(kuò)展時(shí)咐柜,將會(huì)拋出OutOfMemoryError異常

方法區(qū)

  • 所有線程共享的內(nèi)存區(qū)域
  • 存儲(chǔ)已被虛擬機(jī)加載的類信息、常量攘残、靜態(tài)變量
  • 垃圾收集在這個(gè)區(qū)域比較少出現(xiàn)
  • 這個(gè)區(qū)域的內(nèi)存回收目標(biāo)主要對(duì)常良池的回收和對(duì)類型的卸載
  • 當(dāng)方法去無(wú)法滿足內(nèi)存分配需求時(shí)拙友,將拋出OutOfMemoryError異常

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

  • 方法區(qū)的一部分
  • Class文件中除了有類的版本、字段歼郭、方法遗契、接口等描述信息外,還有一項(xiàng)信息是常量池病曾,用于存放編譯器存放的各種字面量和符號(hào)引用牍蜂,這部分內(nèi)容將在類加載后存放到方法區(qū)的運(yùn)行時(shí)常量池中
  • 除了保存Class文件中描述的符號(hào)引用外,還會(huì)把翻譯出來(lái)的直接引用也存儲(chǔ)在運(yùn)行時(shí)常量池中

對(duì)象訪問(wèn)

主流訪問(wèn)方式有兩種:句柄和直接指針

  • 句柄

    使用句柄詢問(wèn)方式泰涂,Java堆中將會(huì)劃分出一塊內(nèi)存來(lái)作為句柄池鲫竞,reference中存儲(chǔ)的就是對(duì)象的句柄地址。而句柄中包含了對(duì)象的實(shí)例數(shù)據(jù)和類型數(shù)據(jù)各自的具體地址信息逼蒙,如下圖所示:

    優(yōu)勢(shì):reference中存儲(chǔ)的是穩(wěn)定的句柄地址从绘,在對(duì)象被移動(dòng)時(shí)(垃圾收集時(shí)移動(dòng)對(duì)象是非常普遍的行為)只會(huì)改變句柄中的實(shí)例數(shù)據(jù)指針,而reference本身不需要被修改

  • 直接指針

    使用直接指針?lè)绞绞抢危琂ava堆對(duì)象的布局中就必須考慮如何放置訪問(wèn)類型數(shù)據(jù)的相關(guān)信息僵井,reference中直接存儲(chǔ)的就是對(duì)象地址,如圖所示:

    優(yōu)勢(shì):速度更快驳棱,它節(jié)省了一次指針定位的時(shí)間開(kāi)銷(xiāo)驹沿,由于對(duì)象的訪問(wèn)在Java中非常頻繁,因此這類開(kāi)銷(xiāo)積少成多后也是一項(xiàng)非车负可觀的執(zhí)行成本,而目前我們使用的虛擬機(jī)Sun HotSpot就是使用第二種方式進(jìn)行對(duì)象訪問(wèn)的

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末朋蔫,一起剝皮案震驚了整個(gè)濱河市罚渐,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌驯妄,老刑警劉巖荷并,帶你破解...
    沈念sama閱讀 221,198評(píng)論 6 514
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異青扔,居然都是意外死亡源织,警方通過(guò)查閱死者的電腦和手機(jī)翩伪,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,334評(píng)論 3 398
  • 文/潘曉璐 我一進(jìn)店門(mén),熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)谈息,“玉大人缘屹,你說(shuō)我怎么就攤上這事∠莱穑” “怎么了轻姿?”我有些...
    開(kāi)封第一講書(shū)人閱讀 167,643評(píng)論 0 360
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)逻炊。 經(jīng)常有香客問(wèn)我互亮,道長(zhǎng),這世上最難降的妖魔是什么余素? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 59,495評(píng)論 1 296
  • 正文 為了忘掉前任豹休,我火速辦了婚禮,結(jié)果婚禮上桨吊,老公的妹妹穿的比我還像新娘威根。我一直安慰自己,他們只是感情好屏积,可當(dāng)我...
    茶點(diǎn)故事閱讀 68,502評(píng)論 6 397
  • 文/花漫 我一把揭開(kāi)白布医窿。 她就那樣靜靜地躺著,像睡著了一般炊林。 火紅的嫁衣襯著肌膚如雪姥卢。 梳的紋絲不亂的頭發(fā)上,一...
    開(kāi)封第一講書(shū)人閱讀 52,156評(píng)論 1 308
  • 那天渣聚,我揣著相機(jī)與錄音独榴,去河邊找鬼。 笑死奕枝,一個(gè)胖子當(dāng)著我的面吹牛棺榔,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播隘道,決...
    沈念sama閱讀 40,743評(píng)論 3 421
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼症歇,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了谭梗?” 一聲冷哼從身側(cè)響起忘晤,我...
    開(kāi)封第一講書(shū)人閱讀 39,659評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎激捏,沒(méi)想到半個(gè)月后设塔,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 46,200評(píng)論 1 319
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡远舅,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,282評(píng)論 3 340
  • 正文 我和宋清朗相戀三年闰蛔,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了痕钢。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 40,424評(píng)論 1 352
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡序六,死狀恐怖任连,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情难咕,我是刑警寧澤课梳,帶...
    沈念sama閱讀 36,107評(píng)論 5 349
  • 正文 年R本政府宣布,位于F島的核電站余佃,受9級(jí)特大地震影響暮刃,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜爆土,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,789評(píng)論 3 333
  • 文/蒙蒙 一椭懊、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧步势,春花似錦氧猬、人聲如沸。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 32,264評(píng)論 0 23
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至倔矾,卻和暖如春妄均,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背哪自。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 33,390評(píng)論 1 271
  • 我被黑心中介騙來(lái)泰國(guó)打工丰包, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人壤巷。 一個(gè)月前我還...
    沈念sama閱讀 48,798評(píng)論 3 376
  • 正文 我出身青樓邑彪,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親胧华。 傳聞我的和親對(duì)象是個(gè)殘疾皇子寄症,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,435評(píng)論 2 359

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