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

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

Java虛擬機(jī)在執(zhí)行Java程序的過程中會(huì)把它所管理的內(nèi)存劃分為若干個(gè)不同的數(shù)據(jù)區(qū)域。這些區(qū)域都有各自的用途朱庆,以及創(chuàng)建和銷毀的時(shí)間榨惠,有的區(qū)域隨著虛擬機(jī)進(jìn)程的啟動(dòng)而存在,有些區(qū)域則是依賴用戶線程的啟動(dòng)和結(jié)束而建立和銷毀憾赁。


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

運(yùn)行時(shí)數(shù)據(jù)區(qū)大致分為共享區(qū)(方法區(qū)和堆)和私有區(qū)(VM棧和Native Method棧污朽,程序計(jì)步器)。

程序計(jì)步器

程序計(jì)數(shù)器(Program Counter Register)是一塊較小的內(nèi)存空間龙考,它的作用可以看做是當(dāng)前線程所執(zhí)行的字節(jié)碼的行號(hào)指示器蟆肆。
由于Java虛擬機(jī)的多線程是通過線程輪流切換并分配處理器執(zhí)行時(shí)間的方式來實(shí)現(xiàn)的矾睦,在任何一個(gè)確定的時(shí)刻,一個(gè)處理器(對(duì)于多核處理器來說是一個(gè)內(nèi)核)只會(huì)執(zhí)行一條線程中的指令炎功。因此枚冗,為了線程切換后能恢復(fù)到正確的執(zhí)行位置,每條線程都需要有一個(gè)獨(dú)立的程序計(jì)數(shù)器蛇损,各條線程之間的計(jì)數(shù)器互不影響赁温,獨(dú)立存儲(chǔ),我們稱這類內(nèi)存區(qū)域?yàn)椤熬€程私有”的內(nèi)存淤齐。
如果線程正在執(zhí)行的是一個(gè)Java方法股囊,這個(gè)計(jì)數(shù)器記錄的是正在執(zhí)行的虛擬機(jī)字節(jié)碼指令的地址;如果正在執(zhí)行的是Natvie方法更啄,這個(gè)計(jì)數(shù)器值則為空(Undefined)稚疹。<strong>此內(nèi)存區(qū)域是唯一一個(gè)在Java虛擬機(jī)規(guī)范中沒有規(guī)定任何OutOfMemoryError情況的區(qū)域。</strong>

VM Stack

與程序計(jì)數(shù)器一樣祭务,<strong>Java虛擬機(jī)棧(Java Virtual Machine Stacks)也是線程私有的内狗,它的生命周期與線程相同。</strong>

每個(gè)方法被執(zhí)行的時(shí)候都會(huì)同時(shí)創(chuàng)建一個(gè)<strong>棧幀</strong>用于存儲(chǔ)局部變量表待牵、操作棧其屏、動(dòng)態(tài)鏈接、方法出口等信息缨该。每一個(gè)方法被調(diào)用直至執(zhí)行完成的過程偎行,就對(duì)應(yīng)著一個(gè)棧幀在虛擬機(jī)棧中從入棧到出棧的過程。

局部變量表存放了編譯期可知的各種基本數(shù)據(jù)類型(boolean贰拿、byte蛤袒、char、short膨更、int妙真、float、long荚守、double)珍德、對(duì)象引用(reference類型,它不等同于對(duì)象本身矗漾,根據(jù)不同的虛擬機(jī)實(shí)現(xiàn)锈候,它可能是一個(gè)指向?qū)ο笃鹗嫉刂返囊弥羔槪部赡苤赶蛞粋€(gè)代表對(duì)象的句柄或者其他與此對(duì)象相關(guān)的位置)和returnAddress類型(指向了一條字節(jié)碼指令的地址)敞贡。

其中64位長度的long和double類型的數(shù)據(jù)會(huì)占用2個(gè)局部變量空間(Slot)泵琳,其余的數(shù)據(jù)類型只占用1個(gè)。局部變量表所需的內(nèi)存空間在編譯期間完成分配,當(dāng)進(jìn)入一個(gè)方法時(shí)获列,這個(gè)方法需要在幀中分配多大的局部變量空間是完全確定的谷市,在方法運(yùn)行期間不會(huì)改變局部變量表的大小。

在Java虛擬機(jī)規(guī)范中击孩,對(duì)這個(gè)區(qū)域規(guī)定了兩種異常狀況:<strong>如果線程請(qǐng)求的棧深度大于虛擬機(jī)所允許的深度迫悠,將拋出StackOverflowError異常;如果虛擬機(jī)椝莺可以動(dòng)態(tài)擴(kuò)展(當(dāng)前大部分的Java虛擬機(jī)都可動(dòng)態(tài)擴(kuò)展及皂,只不過Java虛擬機(jī)規(guī)范中也允許固定長度的虛擬機(jī)棧),當(dāng)擴(kuò)展時(shí)無法申請(qǐng)到足夠的內(nèi)存時(shí)會(huì)拋出OutOfMemoryError異常且改。</strong>

Native Method Stacks

本地方法棧(Native Method Stacks)與虛擬機(jī)棧所發(fā)揮的作用是非常相似的验烧,其區(qū)別不過是<strong>虛擬機(jī)棧為虛擬機(jī)執(zhí)行Java方法(也就是字節(jié)碼)服務(wù),而本地方法棧則是為虛擬機(jī)使用到的Native方法服務(wù)又跛。</strong>虛擬機(jī)規(guī)范中對(duì)本地方法棧中的方法使用的語言碍拆、使用方式與數(shù)據(jù)結(jié)構(gòu)并沒有強(qiáng)制規(guī)定,因此具體的虛擬機(jī)可以自由實(shí)現(xiàn)它慨蓝。甚至有的虛擬機(jī)(譬如Sun HotSpot虛擬機(jī))直接就把本地方法棧和虛擬機(jī)棧合二為一感混。與虛擬機(jī)棧一樣,本地方法棧區(qū)域也會(huì)拋出StackOverflowError和OutOfMemoryError異常礼烈。

JAVA Heap

對(duì)于大多數(shù)應(yīng)用來說弧满,Java堆(Java Heap)是Java虛擬機(jī)所管理的內(nèi)存中最大的一塊。Java堆是被所有線程共享的一塊內(nèi)存區(qū)域此熬,在虛擬機(jī)啟動(dòng)時(shí)創(chuàng)建庭呜。<strong>此內(nèi)存區(qū)域的唯一目的就是存放對(duì)象實(shí)例,幾乎所有的對(duì)象實(shí)例都在這里分配內(nèi)存犀忱。</strong>這一點(diǎn)在Java虛擬機(jī)規(guī)范中的描述是:所有的對(duì)象實(shí)例以及數(shù)組都要在堆上分配募谎,但是隨著JIT編譯器的發(fā)展與逃逸分析技術(shù)的逐漸成熟,棧上分配阴汇、標(biāo)量替換優(yōu)化技術(shù)將會(huì)導(dǎo)致一些微妙的變化發(fā)生数冬,所有的對(duì)象都分配在堆上也漸漸變得不是那么“絕對(duì)”了。

Java堆是垃圾收集器管理的主要區(qū)域搀庶,因此很多時(shí)候也被稱做“GC堆”拐纱。

根據(jù)Java虛擬機(jī)規(guī)范的規(guī)定,Java堆可以處于物理上不連續(xù)的內(nèi)存空間中哥倔,只要邏輯上是連續(xù)的即可戳玫,就像我們的磁盤空間一樣。在實(shí)現(xiàn)時(shí)未斑,既可以實(shí)現(xiàn)成固定大小的,也可以是可擴(kuò)展的,不過當(dāng)前主流的虛擬機(jī)都是按照可擴(kuò)展來實(shí)現(xiàn)的(通過-Xmx和-Xms控制)蜡秽。如果在堆中沒有內(nèi)存完成實(shí)例分配府阀,并且堆也無法再擴(kuò)展時(shí),將會(huì)拋出OutOfMemoryError異常芽突。

方法區(qū)

方法區(qū)(Method Area)與Java堆一樣试浙,是各個(gè)線程共享的內(nèi)存區(qū)域,<strong>它用于存儲(chǔ)已被虛擬機(jī)加載的類信息寞蚌、常量田巴、靜態(tài)變量、即時(shí)編譯器編譯后的代碼等數(shù)據(jù)挟秤。</strong>雖然Java虛擬機(jī)規(guī)范把方法區(qū)描述為堆的一個(gè)邏輯部分壹哺,但是它卻有一個(gè)別名叫做Non-Heap(非堆),目的應(yīng)該是與Java堆區(qū)分開來艘刚。
Java虛擬機(jī)規(guī)范對(duì)這個(gè)區(qū)域的限制非常寬松管宵,除了和Java堆一樣不需要連續(xù)的內(nèi)存和可以選擇固定大小或者可擴(kuò)展外,還可以選擇不實(shí)現(xiàn)垃圾收集攀甚。相對(duì)而言箩朴,垃圾收集行為在這個(gè)區(qū)域是比較少出現(xiàn)的,但并非數(shù)據(jù)進(jìn)入了方法區(qū)就如永久代的名字一樣“永久”存在了秋度。這個(gè)區(qū)域的內(nèi)存回收目標(biāo)主要是針對(duì)常量池的回收和對(duì)類型的卸載炸庞,一般來說這個(gè)區(qū)域的回收“成績”比較難以令人滿意,尤其是類型的卸載荚斯,條件相當(dāng)苛刻埠居,但是這部分區(qū)域的回收確實(shí)是有必要的。在Sun公司的BUG列表中鲸拥,曾出現(xiàn)過的若干個(gè)嚴(yán)重的BUG就是由于低版本的HotSpot虛擬機(jī)對(duì)此區(qū)域未完全回收而導(dǎo)致內(nèi)存泄漏华畏。
根據(jù)Java虛擬機(jī)規(guī)范的規(guī)定弓候,當(dāng)方法區(qū)無法滿足內(nèi)存分配需求時(shí),將拋出OutOfMemoryError異常。

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

運(yùn)行時(shí)常量池(Runtime Constant Pool)是方法區(qū)的一部分牡借。<strong>Class文件中除了有類的版本、字段实辑、方法不从、接口等描述等信息外,還有一項(xiàng)信息是常量池(Constant Pool Table)牵敷,用于存放編譯期生成的各種字面量和符號(hào)引用胡岔,這部分內(nèi)容將在類加載后存放到方法區(qū)的運(yùn)行時(shí)常量池中。</strong>

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ī)范沒有做任何細(xì)節(jié)的要求屋剑,不同的提供商實(shí)現(xiàn)的虛擬機(jī)可以按照自己的需要來實(shí)現(xiàn)這個(gè)內(nèi)存區(qū)域。不過诗眨,一般來說唉匾,除了保存Class文件中描述的符號(hào)引用外,還會(huì)把翻譯出來的直接引用也存儲(chǔ)在運(yùn)行時(shí)常量池中匠楚。

運(yùn)行時(shí)常量池相對(duì)于Class文件常量池的另外一個(gè)重要特征是具備動(dòng)態(tài)性巍膘,Java語言并不要求常量一定只能在編譯期產(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異常。

總結(jié):

程序計(jì)步器(私有):存放的只是一條指向幽告,不存在內(nèi)存溢出啥的梅鹦。
java虛擬機(jī)棧(私有):存儲(chǔ)局部變量表,操作棧冗锁,動(dòng)態(tài)鏈接齐唆、方法出口。會(huì)拋出StackOverflowError和OutOfMemoryError
本地方法棧(私有):虛擬機(jī)使用Native方法服務(wù)冻河。會(huì)拋出StackOverflowError和OutOfMemoryError
堆(共享):存放對(duì)象實(shí)例箍邮,gc主要的地方,通過-Xmx和-Xms控制叨叙,會(huì)拋出OutOfMemoryError異常锭弊。
方法區(qū)(共享):存放被虛擬機(jī)加載的類信息,常量擂错,靜態(tài)變量味滞,即時(shí)編譯器編譯后的代碼等數(shù)據(jù),會(huì)拋出OutOfMemoryError異常钮呀。

摘自《深入理解java虛擬機(jī)》

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末剑鞍,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子爽醋,更是在濱河造成了極大的恐慌蚁署,老刑警劉巖,帶你破解...
    沈念sama閱讀 218,284評(píng)論 6 506
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件蚂四,死亡現(xiàn)場離奇詭異光戈,居然都是意外死亡哪痰,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,115評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門久妆,熙熙樓的掌柜王于貴愁眉苦臉地迎上來妒御,“玉大人,你說我怎么就攤上這事镇饺。” “怎么了送讲?”我有些...
    開封第一講書人閱讀 164,614評(píng)論 0 354
  • 文/不壞的土叔 我叫張陵奸笤,是天一觀的道長。 經(jīng)常有香客問我哼鬓,道長监右,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,671評(píng)論 1 293
  • 正文 為了忘掉前任异希,我火速辦了婚禮健盒,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘称簿。我一直安慰自己扣癣,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,699評(píng)論 6 392
  • 文/花漫 我一把揭開白布憨降。 她就那樣靜靜地躺著父虑,像睡著了一般。 火紅的嫁衣襯著肌膚如雪授药。 梳的紋絲不亂的頭發(fā)上士嚎,一...
    開封第一講書人閱讀 51,562評(píng)論 1 305
  • 那天,我揣著相機(jī)與錄音悔叽,去河邊找鬼莱衩。 笑死,一個(gè)胖子當(dāng)著我的面吹牛娇澎,可吹牛的內(nèi)容都是我干的笨蚁。 我是一名探鬼主播,決...
    沈念sama閱讀 40,309評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼九火,長吁一口氣:“原來是場噩夢(mèng)啊……” “哼赚窃!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起岔激,我...
    開封第一講書人閱讀 39,223評(píng)論 0 276
  • 序言:老撾萬榮一對(duì)情侶失蹤勒极,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后虑鼎,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體辱匿,經(jīng)...
    沈念sama閱讀 45,668評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡键痛,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,859評(píng)論 3 336
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了匾七。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片絮短。...
    茶點(diǎn)故事閱讀 39,981評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖昨忆,靈堂內(nèi)的尸體忽然破棺而出丁频,到底是詐尸還是另有隱情,我是刑警寧澤邑贴,帶...
    沈念sama閱讀 35,705評(píng)論 5 347
  • 正文 年R本政府宣布席里,位于F島的核電站,受9級(jí)特大地震影響拢驾,放射性物質(zhì)發(fā)生泄漏奖磁。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,310評(píng)論 3 330
  • 文/蒙蒙 一繁疤、第九天 我趴在偏房一處隱蔽的房頂上張望咖为。 院中可真熱鬧,春花似錦稠腊、人聲如沸躁染。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,904評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽褐啡。三九已至,卻和暖如春鳖昌,著一層夾襖步出監(jiān)牢的瞬間备畦,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,023評(píng)論 1 270
  • 我被黑心中介騙來泰國打工许昨, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留懂盐,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 48,146評(píng)論 3 370
  • 正文 我出身青樓糕档,卻偏偏與公主長得像莉恼,于是被迫代替她去往敵國和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子速那,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,933評(píng)論 2 355

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

  • JVM內(nèi)存模型Java虛擬機(jī)(Java Virtual Machine=JVM)的內(nèi)存空間分為五個(gè)部分俐银,分別是: ...
    光劍書架上的書閱讀 2,510評(píng)論 2 26
  • 這篇文章是我之前翻閱了不少的書籍以及從網(wǎng)絡(luò)上收集的一些資料的整理,因此不免有一些不準(zhǔn)確的地方端仰,同時(shí)不同JDK版本的...
    高廣超閱讀 15,604評(píng)論 3 83
  • 從三月份找實(shí)習(xí)到現(xiàn)在捶惜,面了一些公司,掛了不少荔烧,但最終還是拿到小米吱七、百度汽久、阿里、京東踊餐、新浪景醇、CVTE、樂視家的研發(fā)崗...
    時(shí)芥藍(lán)閱讀 42,246評(píng)論 11 349
  • 不敢隨意評(píng)價(jià)這部影片 至今記得亞特蘭大戰(zhàn)火中斯嘉麗奔走的背影吝岭,裙邊擺動(dòng)三痰,野性驕傲,不甘屈服窜管。一個(gè)人的性格往往會(huì)決定...
    七個(gè)好聽的名字閱讀 195評(píng)論 1 0
  • 對(duì)于經(jīng)常需要坐在電腦前工作一整天的人來說酒觅,健康問題是不得不關(guān)注的。下面推薦我一直在用的兩款體積非常形⒎濉(幾百KB)的...
    小敏紙閱讀 6,275評(píng)論 10 100