深入理解JVM1-Java內(nèi)存區(qū)域與內(nèi)存溢出異常

自動(dòng)內(nèi)存管理機(jī)制

java內(nèi)存區(qū)域與內(nèi)存溢出異常

1.java虛擬機(jī)運(yùn)行時(shí)數(shù)據(jù)區(qū)

  • 程序計(jì)數(shù)器(Program Counter Register)

它是一塊較小的內(nèi)存空間累贤,它的作用可以看做是當(dāng)先線程所執(zhí)行的字節(jié)碼的信號(hào)指示器襟交。

每一條JVM線程都有自己的PC寄存器,各條線程之間互不影響检诗,獨(dú)立存儲(chǔ),這類內(nèi)存區(qū)域被稱為“線程私有”內(nèi)存

在任意時(shí)刻,一條JVM線程只會(huì)執(zhí)行一個(gè)方法的代碼吐葵。該方法稱為該線程的當(dāng)前方法(Current Method)

如果該方法是java方法,那PC寄存器保存JVM正在執(zhí)行的字節(jié)碼指令的地址

如果該方法是native桥氏,那PC寄存器的值是undefined温峭。

此內(nèi)存區(qū)域是唯一一個(gè)在Java虛擬機(jī)規(guī)范中沒(méi)有規(guī)定任何OutOfMemoryError情況的區(qū)域。

  • Java虛擬機(jī)棧(Java Virtual Machine Stack)

與PC寄存器一樣字支,Java虛擬機(jī)棧也是線程私有的凤藏。每一個(gè)JVM線程都有自己的java虛擬機(jī)棧,這個(gè)棧與線程同時(shí)創(chuàng)建堕伪,它的生命周期與線程相同揖庄。

虛擬機(jī)棧描述的是Java方法執(zhí)行的內(nèi)存模型:每個(gè)方法被執(zhí)行的時(shí)候都會(huì)同時(shí)創(chuàng)建一個(gè)棧幀(Stack Frame)用于存儲(chǔ)局部變量表、操作數(shù)棧欠雌、動(dòng)態(tài)鏈接蹄梢、方法出口等信息。每一個(gè)方法被調(diào)用直至執(zhí)行完成的過(guò)程就對(duì)應(yīng)著一個(gè)棧幀在虛擬機(jī)棧中從入棧到出棧的過(guò)程富俄。

JVM stack 可以被實(shí)現(xiàn)成固定大小禁炒,也可以根據(jù)計(jì)算動(dòng)態(tài)擴(kuò)展。

如果采用固定大小的JVM stack設(shè)計(jì)蛙酪,那么每一條線程的JVM Stack容量應(yīng)該在線程創(chuàng)建時(shí)獨(dú)立地選定齐苛。JVM實(shí)現(xiàn)應(yīng)該提供調(diào)節(jié)JVM Stack初始容量的手段;如果采用動(dòng)態(tài)擴(kuò)展和收縮的JVM Stack方式桂塞,應(yīng)該提供調(diào)節(jié)最大凹蜂、最小容量的手段。

如果線程請(qǐng)求的棧深度大于虛擬機(jī)所允許的深度將拋出StackOverflowError;

如果JVM Stack可以動(dòng)態(tài)擴(kuò)展玛痊,但是在嘗試擴(kuò)展時(shí)無(wú)法申請(qǐng)到足夠的內(nèi)存時(shí)拋出OutOfMemoryError汰瘫。

  • 本地方法棧(Native Method Stack)

本地方法棧與虛擬機(jī)棧作用相似,后者為虛擬機(jī)執(zhí)行Java方法服務(wù)擂煞,而前者為虛擬機(jī)用到的Native方法服務(wù)混弥。

虛擬機(jī)規(guī)范對(duì)于本地方法棧中方法使用的語(yǔ)言,使用方式和數(shù)據(jù)結(jié)構(gòu)沒(méi)有強(qiáng)制規(guī)定对省,甚至有的虛擬機(jī)(比如HotSpot)直接把二者合二為一蝗拿。

這玩意兒拋出的異常跟上面的虛擬機(jī)棧一樣。

  • Java堆(Java Heap)

虛擬機(jī)管理的內(nèi)存中最大的一塊蒿涎,同時(shí)也是被所有線程所共享的哀托,它在虛擬機(jī)啟動(dòng)時(shí)創(chuàng)建,這貨存在的意義就是存放對(duì)象實(shí)例劳秋,幾乎所有的對(duì)象實(shí)例以及數(shù)組都要在這里分配內(nèi)存仓手。這里面的對(duì)象被自動(dòng)管理,也就是俗稱的GC(Garbage Collector)所管理玻淑。用就是了嗽冒,有GC扛著呢,不用操心銷毀回收的事兒补履。

Java堆的容量可以是固定大小添坊,也可以隨著需求動(dòng)態(tài)擴(kuò)展(-Xms和-Xmx),并在不需要過(guò)多空間時(shí)自動(dòng)收縮干像。

Java堆所使用的內(nèi)存不需要保證是物理連續(xù)的帅腌,只要邏輯上是連續(xù)的即可。

JVM實(shí)現(xiàn)應(yīng)當(dāng)提供給程序員調(diào)節(jié)Java 堆初始容量的手段麻汰,對(duì)于可動(dòng)態(tài)擴(kuò)展和收縮的堆來(lái)說(shuō)速客,則應(yīng)當(dāng)提供調(diào)節(jié)其最大和最小容量的手段。

如果堆中沒(méi)有內(nèi)存完成實(shí)例分配并且堆也無(wú)法擴(kuò)展五鲫,就會(huì)拋OutOfMemoryError溺职。

  • 方法區(qū)(Method Area)

跟堆一樣是被各個(gè)線程共享的內(nèi)存區(qū)域,用于存儲(chǔ)以被虛擬機(jī)加載的類信息位喂、常量浪耘、靜態(tài)變量、即時(shí)編譯器編譯后的代碼等數(shù)據(jù)塑崖。雖然這個(gè)區(qū)域被虛擬機(jī)規(guī)范把方法區(qū)描述為堆的一個(gè)邏輯部分七冲,但是它的別名叫非堆,用來(lái)與堆做一下區(qū)別规婆。

方法區(qū)在虛擬機(jī)啟動(dòng)的時(shí)候創(chuàng)建澜躺。

方法區(qū)的容量可以是固定大小的蝉稳,也可以隨著程序執(zhí)行的需求動(dòng)態(tài)擴(kuò)展,并在不需要過(guò)多空間時(shí)自動(dòng)收縮掘鄙。

方法區(qū)在實(shí)際內(nèi)存空間中可以是不連續(xù)的耘戚。

Java虛擬機(jī)實(shí)現(xiàn)應(yīng)當(dāng)提供給程序員或者最終用戶調(diào)節(jié)方法區(qū)初始容量的手段,對(duì)于可以動(dòng)態(tài)擴(kuò)展和收縮方法區(qū)來(lái)說(shuō)操漠,則應(yīng)當(dāng)提供調(diào)節(jié)其最大收津、最小容量的手段。

當(dāng)方法區(qū)無(wú)法滿足內(nèi)存分配需求時(shí)就會(huì)拋OutOfMemoryError浊伙。

  • 運(yùn)行時(shí)常量池(Runtime Constant Pool)

它是方法區(qū)的一部分撞秋。Class文件中除了有類的版本、字段嚣鄙、方法部服、接口等描述等信息外,還有一項(xiàng)信息是常量池(Constant Pool Table)拗慨,用于存放編譯期生成的各種字面量和符號(hào)引用,這部分內(nèi)容將在類加載后存放到方法區(qū)的運(yùn)行時(shí)常量池中奉芦。

Java虛擬機(jī)對(duì)Class文件的每一部分(自然也包括常量池)的格式都有嚴(yán)格的規(guī)定赵抢,每一個(gè)字節(jié)用于存儲(chǔ)哪種數(shù)據(jù)都必須符合規(guī)范上的要求,這樣才會(huì)被虛擬機(jī)認(rèn)可声功、裝載和執(zhí)行烦却。但對(duì)于運(yùn)行時(shí)常量池,Java虛擬機(jī)規(guī)范沒(méi)有做任何細(xì)節(jié)的要求先巴,不同的提供商實(shí)現(xiàn)的虛擬機(jī)可以按照自己的需要來(lái)實(shí)現(xiàn)這個(gè)內(nèi)存區(qū)域其爵。不過(guò),一般來(lái)說(shuō)伸蚯,除了保存Class文件中描述的符號(hào)引用外摩渺,還會(huì)把翻譯出來(lái)的直接引用也存儲(chǔ)在運(yùn)行時(shí)常量池中。

運(yùn)行時(shí)常量池相對(duì)于Class文件常量池的另外一個(gè)重要特征是具備動(dòng)態(tài)性剂邮,Java語(yǔ)言并不要求常量一定只能在編譯期產(chǎn)生摇幻,也就是并非預(yù)置入Class文件中常量池的內(nèi)容才能進(jìn)入方法區(qū)運(yùn)行時(shí)常量池,運(yùn)行期間也可能將新的常量放入池中挥萌,這種特性被開發(fā)人員利用得比較多的便是String類的intern()方法绰姻。

既然運(yùn)行時(shí)常量池是方法區(qū)的一部分,自然會(huì)受到方法區(qū)內(nèi)存的限制引瀑,當(dāng)常量池?zé)o法再申請(qǐng)到內(nèi)存時(shí)會(huì)拋出OutOfMemoryError異常狂芋。

2.hotspot虛擬機(jī)對(duì)象探秘

1.對(duì)象的創(chuàng)建

new->檢查這個(gè)指令參數(shù)是否能在常量池中定位到一個(gè)類的引用符號(hào)->判斷這個(gè)類是否被加載、解析憨栽、初始化過(guò)->加載檢查通過(guò)后帜矾,分配內(nèi)存(指針碰撞翼虫,空閑列表)

->對(duì)分配內(nèi)存空間的動(dòng)作進(jìn)行同步處理(CAS配上失敗重試、TLAB)->虛擬機(jī)需要將分配到的內(nèi)存空間都初始化為零值->對(duì)對(duì)象進(jìn)行必要的設(shè)置

2.對(duì)象的內(nèi)存布局

還Hotspot虛擬機(jī)中黍特,對(duì)象的內(nèi)存中存儲(chǔ)的布局分為3塊區(qū)域:對(duì)象頭(header)蛙讥、實(shí)例數(shù)據(jù)(Instance Data)、對(duì)其填充(Padding)

Hotspot虛擬機(jī)的對(duì)象頭包括兩部分信息灭衷,第一部分用于存儲(chǔ)自身運(yùn)行時(shí)的數(shù)據(jù)次慢,例如:哈希碼、GC分代年齡翔曲、鎖狀態(tài)標(biāo)識(shí)迫像、線程持有鎖、偏向線程id瞳遍、偏向時(shí)間戳闻妓,這部分?jǐn)?shù)據(jù)數(shù)據(jù)長(zhǎng)度在32位和64位的虛擬機(jī)(未開啟指針壓縮)中分別為32bit和64bit,官方稱為’Mark word’掠械。對(duì)象需要存儲(chǔ)的運(yùn)行時(shí)的數(shù)據(jù)非常多由缆,已經(jīng)超出了32位、64位bitmap結(jié)構(gòu)所能記錄的限度猾蒂,但是對(duì)象頭信息是與對(duì)象自身定義的數(shù)據(jù)無(wú)關(guān)額外的存儲(chǔ)成本髓棋,考慮到虛擬機(jī)的空間效率侠草,Mark work被設(shè)計(jì)成一個(gè)非固定的數(shù)據(jù)結(jié)構(gòu)以便在極小空間內(nèi)存儲(chǔ)盡可能多的信息躺坟,他會(huì)根據(jù)對(duì)象狀態(tài)復(fù)用自己的存儲(chǔ)空間菱阵。
對(duì)象頭的另一部分是類型指針,即對(duì)象指向他的類元數(shù)據(jù)的指針蚊逢,虛擬機(jī)通過(guò)這個(gè)指針來(lái)確定這個(gè)對(duì)象是哪個(gè)類的實(shí)例层扶。如果對(duì)象是一個(gè)Java數(shù)組,那在對(duì)象中還必須有一塊用于記錄數(shù)組長(zhǎng)度的數(shù)據(jù)烙荷,因?yàn)樘摂M機(jī)可通過(guò)普通 Java對(duì)象的元數(shù)據(jù)信息確定Java對(duì)象的大小镜会,但是從數(shù)組的元數(shù)據(jù)中卻無(wú)法確定數(shù)組的大小。

接下來(lái)的實(shí)例數(shù)據(jù)是對(duì)象真正存儲(chǔ)的有效信息奢讨,也是在程序代碼中所定義的各種類型的字段內(nèi)容稚叹。無(wú)論是從父類繼承下來(lái)的還是在子類中定義的,都需要記錄下來(lái)拿诸。這部分的存儲(chǔ)順序會(huì)受到虛擬機(jī)分配策略參數(shù)和字段在Java源碼中定義順序的影響扒袖。Hotspot虛擬機(jī)的分配策略是相同寬度的字段總是被分配到一起。在滿足這個(gè)前提條件下亩码,在父類中定義的變量會(huì)出現(xiàn)在子類之前季率。

3.對(duì)象的訪問(wèn)定位

  • 句柄

如果使用句柄訪問(wèn)的話,Java堆中將會(huì)劃分出一塊內(nèi)存來(lái)作為句柄池描沟,reference中存儲(chǔ)的就是對(duì)象的句柄地址飒泻,而句柄中包含了對(duì)象實(shí)例數(shù)據(jù)與類型數(shù)據(jù)的具體各自的地址信息鞭光。如圖1所示。


  • 直接指針

如果使用直接指針訪問(wèn)的話泞遗,Java堆對(duì)象的布局中就必須考慮如何放置訪問(wèn)類型數(shù)據(jù)的相關(guān)信息惰许,reference中存儲(chǔ)的直接就是對(duì)象地址,如圖2所示史辙。


3.outofmemoryerror異常

1.java 堆溢出
2.虛擬機(jī)棧本地方法溢出
3.方法區(qū)和運(yùn)行時(shí)常量池溢出
4.本機(jī)直接內(nèi)存溢出

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末汹买,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子聊倔,更是在濱河造成了極大的恐慌晦毙,老刑警劉巖,帶你破解...
    沈念sama閱讀 212,542評(píng)論 6 493
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件耙蔑,死亡現(xiàn)場(chǎng)離奇詭異见妒,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī)甸陌,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,596評(píng)論 3 385
  • 文/潘曉璐 我一進(jìn)店門须揣,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人钱豁,你說(shuō)我怎么就攤上這事返敬。” “怎么了寥院?”我有些...
    開封第一講書人閱讀 158,021評(píng)論 0 348
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)涛目。 經(jīng)常有香客問(wèn)我秸谢,道長(zhǎng),這世上最難降的妖魔是什么霹肝? 我笑而不...
    開封第一講書人閱讀 56,682評(píng)論 1 284
  • 正文 為了忘掉前任估蹄,我火速辦了婚禮,結(jié)果婚禮上沫换,老公的妹妹穿的比我還像新娘臭蚁。我一直安慰自己,他們只是感情好讯赏,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,792評(píng)論 6 386
  • 文/花漫 我一把揭開白布垮兑。 她就那樣靜靜地躺著,像睡著了一般漱挎。 火紅的嫁衣襯著肌膚如雪系枪。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,985評(píng)論 1 291
  • 那天磕谅,我揣著相機(jī)與錄音私爷,去河邊找鬼雾棺。 笑死,一個(gè)胖子當(dāng)著我的面吹牛衬浑,可吹牛的內(nèi)容都是我干的捌浩。 我是一名探鬼主播,決...
    沈念sama閱讀 39,107評(píng)論 3 410
  • 文/蒼蘭香墨 我猛地睜開眼工秩,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼尸饺!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起拓诸,我...
    開封第一講書人閱讀 37,845評(píng)論 0 268
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤侵佃,失蹤者是張志新(化名)和其女友劉穎,沒(méi)想到半個(gè)月后奠支,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體馋辈,經(jīng)...
    沈念sama閱讀 44,299評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,612評(píng)論 2 327
  • 正文 我和宋清朗相戀三年倍谜,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了迈螟。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 38,747評(píng)論 1 341
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡尔崔,死狀恐怖答毫,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情季春,我是刑警寧澤洗搂,帶...
    沈念sama閱讀 34,441評(píng)論 4 333
  • 正文 年R本政府宣布,位于F島的核電站载弄,受9級(jí)特大地震影響耘拇,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜宇攻,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 40,072評(píng)論 3 317
  • 文/蒙蒙 一惫叛、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧逞刷,春花似錦嘉涌、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,828評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至帆喇,卻和暖如春词身,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背番枚。 一陣腳步聲響...
    開封第一講書人閱讀 32,069評(píng)論 1 267
  • 我被黑心中介騙來(lái)泰國(guó)打工法严, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留损敷,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 46,545評(píng)論 2 362
  • 正文 我出身青樓深啤,卻偏偏與公主長(zhǎng)得像拗馒,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子溯街,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,658評(píng)論 2 350

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