Java內(nèi)存結(jié)構(gòu)

運(yùn)行時(shí)的數(shù)據(jù)區(qū)域可以看以下兩張圖


image.png

image.png

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

程序計(jì)數(shù)器(Pregram Counter Register是塊較小的內(nèi)存空間全封, 它可以看作是當(dāng)前線程所執(zhí)行的字節(jié)碼的行號(hào)指示器。在虛擬機(jī)的概念模型里,字節(jié)碼解釋器工作時(shí)就是通過(guò)改變這個(gè)計(jì)數(shù)器的值來(lái)選取下一條需要執(zhí)行的字節(jié)碼指令揍诽,分支啸盏、循環(huán)弧岳、跳轉(zhuǎn)、異常處理几晤、線程恢復(fù)等基礎(chǔ)功能都需要依賴這個(gè)計(jì)數(shù)器來(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ǔ)众雷,我們稱這類(lèi)內(nèi)存區(qū)域?yàn)椤熬€程私有”的內(nèi)存灸拍。

如果線程正在執(zhí)行的是一個(gè)Java方法,這個(gè)計(jì)數(shù)器記錄的是正在執(zhí)行的虛擬機(jī)字節(jié)碼指令的地址;如果正在執(zhí)行的是Native方法砾省,這個(gè)計(jì)數(shù)器值則為空( Undefined)鸡岗。此內(nèi)存區(qū)域是唯一一個(gè)在Java虛擬機(jī)規(guī)范中沒(méi)有規(guī)定任何OutOfMemoryError情況的區(qū)域。

二编兄、Java虛擬機(jī)棧

Java虛擬機(jī)棧(java Virtual Mechine 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ī)棧中的入棧到出棧.

局部變量表存放了編譯器可知的各種基本數(shù)據(jù)類(lèi)型(boolean,byte,char,short,int,float,long,double),對(duì)象引用(reference類(lèi)型)和returnAddress類(lèi)型(指向一條字節(jié)碼指令的地址)

在Java虛擬機(jī)規(guī)范中轩性,對(duì)這個(gè)區(qū)域規(guī)定了兩種異常狀況:如果線程請(qǐng)求的棧深度大于虛擬機(jī)所允許的深度,將拋出StackOveFlowError異常;如果虛擬機(jī)椇菰В可以動(dòng)態(tài)擴(kuò)展(當(dāng)前大部分的Java虛擬機(jī)都可動(dòng)態(tài)擴(kuò)展揣苏,只不過(guò)Java虛擬機(jī)規(guī)范中也允許固定長(zhǎng)度的虛擬機(jī)棧)悯嗓,如果擴(kuò)展時(shí)無(wú)法申請(qǐng)到足夠的內(nèi)存,就會(huì)拋出OutOfMemoryEror異常卸察。

三脯厨、本地方法棧

本地方法棧(Native Method Stacks)與虛擬機(jī)棧作用相似,也會(huì)拋出StackOverflowError和OutOfMemoryError異常坑质。
區(qū)別在于虛擬機(jī)棧為虛擬機(jī)執(zhí)行Java方法(字節(jié)碼)服務(wù)合武,而本地方法棧是為虛擬機(jī)使用到的Native方法服務(wù)。

四洪乍、Java堆

對(duì)于大多數(shù)應(yīng)用來(lái)說(shuō)眯杏,Java堆 (Java Heap)是Java虛擬機(jī)所管理的內(nèi)存中最大的內(nèi)存塊。Java堆是被所有線程共享的一塊內(nèi)存區(qū)域壳澳, 在虛擬機(jī)啟動(dòng)時(shí)創(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ì)象都分配在堆上也漸漸變得不是那么“絕對(duì)”了。

Java堆是垃圾收集器管理的主要區(qū)域垮耳,因此很多時(shí)候也被稱做“GC堆”颈渊。從內(nèi)存回收的角度來(lái)看,由于收集器基本都采用分代收集算法终佛,所以Java堆中還可以細(xì)分為:新生代和老年代:再細(xì)致一點(diǎn)的有Eden空間俊嗽、From Survivor空間、To Survivor空間等铃彰。從內(nèi)存分配的角度來(lái)看绍豁,線程共享的Java堆中可能劃分出多個(gè)線程私有的分配緩沖區(qū)(Thread Local Alocation Buffer, TLAB).不過(guò)無(wú)論如何劃分,都與存放內(nèi)容無(wú)關(guān)牙捉,無(wú)論哪個(gè)區(qū)域竹揍,存儲(chǔ)的都仍然是對(duì)象實(shí)例,進(jìn)步劃分的目的是為了更好地回收內(nèi)存邪铲,或者更快地分配內(nèi)存芬位。

根據(jù)Java虛擬機(jī)規(guī)范的規(guī)定,Java 堆可以處于物理上不連續(xù)的內(nèi)存空間中带到,只要邏輯上是連續(xù)的即可晶衷,就像我們的磁盤(pán)空間一樣。在實(shí)現(xiàn)時(shí)阴孟,既可以實(shí)現(xiàn)成固定大小的晌纫,也可以是可擴(kuò)展的,不過(guò)當(dāng)前主流的虛擬機(jī)都是按照可擴(kuò)展來(lái)實(shí)現(xiàn)的(通過(guò)-Xmx和-Xms控制).如果在堆中設(shè)有內(nèi)存完成實(shí)例分配永丝,并且堆也無(wú)法再擴(kuò)展時(shí)锹漱,將會(huì)拋出OutOfMemoryError異常.

五、方法區(qū)

方法區(qū)(Method Area)與Java堆一樣慕嚷,是各個(gè)線程共享的內(nèi)存區(qū)城哥牍,它用于存儲(chǔ)已被虛擬機(jī)加載的類(lèi)信息、常量喝检、靜態(tài)變量嗅辣、即時(shí)編譯器編譯后的代碼等數(shù)據(jù)。

六挠说、運(yùn)行時(shí)常量池

運(yùn)行時(shí)常量池( Runtime Constant Pool)是方法區(qū)的一部分澡谭。Class 文件中除了有類(lèi)的版本、字段损俭、方法蛙奖、接口等描述信息外,還有一項(xiàng)信息是常量池(Constant Pool Table), 用于存放編譯期生成的各種字面量符號(hào)引用杆兵,這部分內(nèi)容將在類(lèi)加載后進(jìn)人方法區(qū)的運(yùn)行時(shí)常量池中存放.

七雁仲、直接內(nèi)存

直接內(nèi)存(Direct Memory)并不是虛擬機(jī)運(yùn)行時(shí)數(shù)據(jù)區(qū)的一部分,也不是虛擬機(jī)規(guī)范中定義的內(nèi)存區(qū)域琐脏。但是這部分內(nèi)存也被頻繁地使用攒砖,而且也可能導(dǎo)致OutOfMemoryError異常的出現(xiàn).

在JDK 1.4中新加人了NIO (New Input/Output)類(lèi),引人了一種基于通道(Channel 與緩沖區(qū)(Buffer) 的IO方式日裙,它可以使用Native函數(shù)庫(kù)直接分配堆外內(nèi)存吹艇,然后通過(guò)一個(gè)存儲(chǔ)在Java堆中的DirectByteBuffer對(duì)象作為這塊內(nèi)存的引用進(jìn)行操作。這樣能在一些場(chǎng)景中顯著提高性能阅签,因?yàn)楸苊饬嗽贘ava堆和Native堆中來(lái)回復(fù)制數(shù)據(jù)掐暮。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市政钟,隨后出現(xiàn)的幾起案子路克,更是在濱河造成了極大的恐慌,老刑警劉巖养交,帶你破解...
    沈念sama閱讀 211,639評(píng)論 6 492
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件精算,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡碎连,警方通過(guò)查閱死者的電腦和手機(jī)灰羽,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,277評(píng)論 3 385
  • 文/潘曉璐 我一進(jìn)店門(mén),熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人廉嚼,你說(shuō)我怎么就攤上這事玫镐。” “怎么了怠噪?”我有些...
    開(kāi)封第一講書(shū)人閱讀 157,221評(píng)論 0 348
  • 文/不壞的土叔 我叫張陵恐似,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我傍念,道長(zhǎng)矫夷,這世上最難降的妖魔是什么? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 56,474評(píng)論 1 283
  • 正文 為了忘掉前任憋槐,我火速辦了婚禮双藕,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘阳仔。我一直安慰自己忧陪,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,570評(píng)論 6 386
  • 文/花漫 我一把揭開(kāi)白布驳概。 她就那樣靜靜地躺著赤嚼,像睡著了一般。 火紅的嫁衣襯著肌膚如雪顺又。 梳的紋絲不亂的頭發(fā)上更卒,一...
    開(kāi)封第一講書(shū)人閱讀 49,816評(píng)論 1 290
  • 那天,我揣著相機(jī)與錄音稚照,去河邊找鬼蹂空。 笑死,一個(gè)胖子當(dāng)著我的面吹牛果录,可吹牛的內(nèi)容都是我干的上枕。 我是一名探鬼主播,決...
    沈念sama閱讀 38,957評(píng)論 3 408
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼弱恒,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼辨萍!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起返弹,我...
    開(kāi)封第一講書(shū)人閱讀 37,718評(píng)論 0 266
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤锈玉,失蹤者是張志新(化名)和其女友劉穎,沒(méi)想到半個(gè)月后义起,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體拉背,經(jīng)...
    沈念sama閱讀 44,176評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,511評(píng)論 2 327
  • 正文 我和宋清朗相戀三年默终,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了椅棺。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片犁罩。...
    茶點(diǎn)故事閱讀 38,646評(píng)論 1 340
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖两疚,靈堂內(nèi)的尸體忽然破棺而出床估,到底是詐尸還是另有隱情,我是刑警寧澤鬼雀,帶...
    沈念sama閱讀 34,322評(píng)論 4 330
  • 正文 年R本政府宣布顷窒,位于F島的核電站,受9級(jí)特大地震影響源哩,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜鸦做,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,934評(píng)論 3 313
  • 文/蒙蒙 一励烦、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧泼诱,春花似錦坛掠、人聲如沸。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 30,755評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至耸袜,卻和暖如春友多,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背堤框。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 31,987評(píng)論 1 266
  • 我被黑心中介騙來(lái)泰國(guó)打工域滥, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人蜈抓。 一個(gè)月前我還...
    沈念sama閱讀 46,358評(píng)論 2 360
  • 正文 我出身青樓启绰,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親沟使。 傳聞我的和親對(duì)象是個(gè)殘疾皇子委可,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,514評(píng)論 2 348

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

  • [toc] 參考:Java虛擬機(jī)詳解02----JVM內(nèi)存結(jié)構(gòu)深入理解java虛擬機(jī) 精華總結(jié)(面試)深入理解JV...
    小小少年Boy閱讀 890評(píng)論 0 1
  • 概述 對(duì)于從事C、C++程序開(kāi)發(fā)的開(kāi)發(fā)人員來(lái)說(shuō)腊嗡,在內(nèi)存管理領(lǐng)域着倾,他們既是擁有最高權(quán)力的“皇帝”又是從事最基礎(chǔ)工作的...
    靜_9060閱讀 1,747評(píng)論 0 1
  • Java虛擬機(jī)在執(zhí)行Java程序的過(guò)程中會(huì)把他所管理的內(nèi)存劃分為若干個(gè)不同的數(shù)據(jù)區(qū)域。如下所示: 程序計(jì)數(shù)器 程序...
    BelieveFrank閱讀 174評(píng)論 0 0
  • java開(kāi)發(fā)過(guò)程中經(jīng)常見(jiàn)到一堆有關(guān)內(nèi)存的錯(cuò)誤叽唱,比如: 我們統(tǒng)一叫做內(nèi)存溢出屈呕,那么這些異常的底層到底有什么不同,各自...
    激情的狼王閱讀 714評(píng)論 4 4
  • Java堆(Java Heap) java堆是java虛擬機(jī)所管理的內(nèi)存中最大的一塊棺亭,是被所有線程共享的一塊內(nèi)存區(qū)...
    Mark_ZSQ閱讀 88評(píng)論 0 0