Java虛擬機(jī):內(nèi)存區(qū)域

版權(quán)聲明:本文為斑馬君學(xué)習(xí)總結(jié)文章,轉(zhuǎn)載請(qǐng)注明出處!

一囊卜、jdk、jre眠菇、jvm之間的關(guān)系

從廣義上講边败,運(yùn)行于java虛擬機(jī)上的語(yǔ)音及其相關(guān)的程序都屬于java技術(shù)體系中的一員。Sun官方所定義的java技術(shù)體系包括以下幾個(gè)組成部分:

  • 1 java程序設(shè)計(jì)語(yǔ)言
  • 2 各種硬件平臺(tái)上的java虛擬機(jī)
  • 3 Class文件格式
  • 4 Java API 類(lèi)庫(kù)
  • 5 第三方Java類(lèi)庫(kù)

    把Java程序設(shè)計(jì)語(yǔ)言捎废、java虛擬笑窜、javaAPI類(lèi)庫(kù)這三部分統(tǒng)稱(chēng)為JDK。把JavaAPI類(lèi)庫(kù)中的JavaSE API子集和Java虛擬機(jī)這兩部分統(tǒng)稱(chēng)為JRE.JRE是java程序運(yùn)行的標(biāo)準(zhǔn)環(huán)境登疗。Jvm: Java Virtual Machine java虛擬機(jī)排截。三者之間關(guān)系圖。
二辐益、Java虛擬機(jī)內(nèi)存管理

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

2.1.線(xiàn)程共享區(qū):
方法區(qū):存儲(chǔ)運(yùn)行時(shí)常量池续捂,已被虛擬機(jī)加載的類(lèi)信息垦垂,常量,靜態(tài)變量牙瓢,即時(shí)編譯器編譯后的代碼等數(shù)據(jù)劫拗。
Java堆:存儲(chǔ)對(duì)象實(shí)例。
2.2線(xiàn)程獨(dú)占區(qū)
本地方法棧:為jvm所調(diào)用到的Native腳本地方法服務(wù)矾克。
虛擬機(jī)棧:存放方法運(yùn)行時(shí)所需的數(shù)據(jù)页慷,成為棧幀。
程序計(jì)數(shù)器:記錄當(dāng)前線(xiàn)程所執(zhí)行的字節(jié)碼的行號(hào)。

三酒繁、程序計(jì)數(shù)器

程序計(jì)數(shù)器是一塊較小的內(nèi)存空間滓彰,它可以看作是當(dāng)前線(xiàn)程所執(zhí)行的字節(jié)碼的行號(hào)指示器。程序計(jì)數(shù)器處于線(xiàn)程獨(dú)占區(qū)欲逃。

如果線(xiàn)程執(zhí)行的是Java方法找蜜,這個(gè)計(jì)數(shù)器記錄的是正在執(zhí)行的虛擬機(jī)字節(jié)碼指令的地址。如果正在執(zhí)行的是native方法稳析,這個(gè)計(jì)數(shù)器的值為undefined洗做。此區(qū)域是唯一一個(gè)在java虛擬機(jī)規(guī)范中沒(méi)有規(guī)定任何OutOfMemoryError情況的區(qū)域。

四彰居、虛擬機(jī)棧

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

棧幀:每個(gè)方法執(zhí)行井辆,都會(huì)創(chuàng)建一個(gè)棧幀,伴隨著方法從創(chuàng)建到執(zhí)行完成溶握。用于存儲(chǔ)局部變量表杯缺,操作數(shù)棧,動(dòng)態(tài)鏈接睡榆,方法出口等萍肆。

局部變量表:存放編譯期可知的各種基本數(shù)據(jù)類(lèi)型,引用類(lèi)型胀屿,returnAddress類(lèi)型塘揣。
局部變量表在內(nèi)存空間的編譯期完成分配,當(dāng)進(jìn)入一個(gè)方法時(shí)宿崭,這個(gè)方法需要在幀分配多少內(nèi)存是固定的亲铡,在方法運(yùn)行期間是不會(huì)改變局部變量表的大小。

如果線(xiàn)程請(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ò)展時(shí)無(wú)法申請(qǐng)到足夠的內(nèi)存房资,就會(huì)拋出OutOfMemoryError異常蜕劝。

五、本地方法棧

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

六、Java堆

存放對(duì)象事例婴削。垃圾收集器管理的主要區(qū)域廊镜,新生代,老年代唉俗。Eden空間嗤朴。通過(guò)-Xmx -Xms參數(shù)來(lái)控制堆內(nèi)存的大小。如果在堆中沒(méi)有內(nèi)存完成實(shí)例分配虫溜,并且堆也無(wú)法再擴(kuò)展時(shí)雹姊,將會(huì)拋出OutOfMemoryError異常。

七衡楞、方法區(qū)

存儲(chǔ)虛擬機(jī)加載的類(lèi)信息吱雏,常量,靜態(tài)變量瘾境,即時(shí)編譯器編譯后的代碼等數(shù)據(jù)歧杏。方法區(qū)并不等價(jià)于永久代。這區(qū)域的內(nèi)存回收目標(biāo)主要是針對(duì)常量池的回收和堆類(lèi)型的卸載迷守。

八犬绒、運(yùn)行時(shí)常量池

方法區(qū)的一部分。Class文件中除了有類(lèi)的版本盒犹、字段懂更、方法、接口等描述信息外急膀。還有一項(xiàng)信息是常量池沮协。用于存放編譯期生成的各種字面量和符號(hào)引用,者部分內(nèi)存將在類(lèi)加載后進(jìn)入方法區(qū)的運(yùn)行時(shí)常量池中存放卓嫂。比如String str =”abc”慷暂。

九、直接內(nèi)存:

并不是虛擬機(jī)運(yùn)行時(shí)數(shù)據(jù)區(qū)的一部分晨雳。也不是Java虛擬機(jī)規(guī)范中定義的內(nèi)存區(qū)域行瑞。新加入了NIO類(lèi),引入了一個(gè)基于通道和緩沖區(qū)的I/O方式餐禁,它可以使用Native函數(shù)庫(kù)直接分配堆外內(nèi)存血久,然后通過(guò)一個(gè)存儲(chǔ)在java堆中的DirectByteBuffer對(duì)象作為這塊內(nèi)存的引用進(jìn)行操作。

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

對(duì)象的創(chuàng)建主要分四部分:1.給對(duì)象分配內(nèi)存 2.線(xiàn)程安全性問(wèn)題 3.初始化對(duì)象 4.執(zhí)行構(gòu)造方法

對(duì)象分配內(nèi)存:虛擬機(jī)將為新生對(duì)象分配內(nèi)存帮非。對(duì)象所需內(nèi)存的大小在類(lèi)加載完成后便可完全確定(如何確定將在2.3.2節(jié)中介紹)氧吐,為對(duì)象分配空間的任務(wù)等同于把一塊確定大小的內(nèi)存從Java堆中劃分出來(lái)讹蘑。假設(shè)Java堆中內(nèi)存是絕對(duì)規(guī)整的,所有用過(guò)的內(nèi)存都放在一邊筑舅,空閑的內(nèi)存放在另一邊座慰,中間放著一個(gè)指針作為分界點(diǎn)的指示器,那所分配內(nèi)存就僅僅是把那個(gè)指針向空閑空間那邊挪動(dòng)一段與對(duì)象大小相等的距離翠拣,這種分配方式稱(chēng)為“指針碰撞”(Bump the Pointer)版仔。
指針碰撞
如果Java堆中的內(nèi)存并不是規(guī)整的,已使用的內(nèi)存和空閑的內(nèi)存相互交錯(cuò)误墓,那就沒(méi)有辦法簡(jiǎn)單地進(jìn)行指針碰撞了蛮粮,虛擬機(jī)就必須維護(hù)一個(gè)列表,記錄上哪些內(nèi)存塊是可用的优烧,在分配的時(shí)候從列表中找到一塊足夠大的空間劃分給對(duì)象例蝉揍,并更新列表上的記錄,這種分配方式稱(chēng)為“空閑列表”(Free List)畦娄。
空閑列表記憶內(nèi)存
選擇哪種分配方式由Java堆是否規(guī)整決定又沾,而Java堆是否規(guī)整又由所采用的垃圾收集器是否帶有壓縮整理功能決定。
線(xiàn)程安全問(wèn)題:對(duì)象創(chuàng)建在虛擬機(jī)中是非常頻繁的行為熙卡,即使是僅僅修改一個(gè)指針?biāo)赶虻奈恢谜人ⅲ诓l(fā)情況下也并不是線(xiàn)程安全的,可能出現(xiàn)正在給對(duì)象A分配內(nèi)存驳癌,指針還沒(méi)來(lái)得及修改滑燃,對(duì)象B又同時(shí)使用了原來(lái)的指針來(lái)分配內(nèi)存的情況。

方案一:一種是對(duì)分配內(nèi)存空間的動(dòng)作進(jìn)行同步處理颓鲜,實(shí)際上虛擬機(jī)采用CAS配上失敗重試的方式保證更新操作的原子性表窘。

方案二:把內(nèi)存分配的動(dòng)作按照線(xiàn)程劃分在不同的空間之中進(jìn)行,即每個(gè)線(xiàn)程在Java堆中預(yù)先分配一小塊內(nèi)存甜滨,稱(chēng)為本地線(xiàn)程分配緩沖(Thread Local Allocation Buffer,TLAB)乐严。哪個(gè)線(xiàn)程要分配內(nèi)存,就在哪個(gè)線(xiàn)程的TLAB上分配衣摩,只有TLAB用完并分配新的TLAB時(shí)昂验,才需要同步鎖定。虛擬機(jī)是否使用TLAB艾扮,可以通過(guò)-XX:+/-UseTLAB參數(shù)來(lái)設(shè)定既琴。

初始化對(duì)象:內(nèi)存分配完成后,虛擬機(jī)需要將分配到內(nèi)存空間都初始化為零值泡嘴。

執(zhí)行構(gòu)造方法:虛擬機(jī)要對(duì)對(duì)象進(jìn)行必要的設(shè)置甫恩,例如這個(gè)對(duì)象是哪個(gè)類(lèi)的實(shí)例厂汗,如何才能找到類(lèi)的元數(shù)據(jù)信息鼠冕、對(duì)象的哈希碼爷贫、對(duì)象的GC分代年齡等信息步势。

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

在HotSpot虛擬機(jī)中丹诀,對(duì)象在內(nèi)存中存儲(chǔ)的布局可以分為3塊區(qū)域:對(duì)象頭(Header)喝滞、實(shí)例數(shù)據(jù)(Instance Data)和對(duì)齊填充(Padding)异旧。
1.Header(對(duì)象頭)包含兩部分信息涵卵,第一部分用于存儲(chǔ)對(duì)象自身的運(yùn)行時(shí)數(shù)據(jù)(Mark Word) 哈希碼 GC分代年齡 鎖狀態(tài)標(biāo)志 線(xiàn)程持有的鎖莱褒,偏向線(xiàn)程ID 偏向時(shí)間戳击困。根據(jù)鎖的狀態(tài)不同,把這個(gè)對(duì)象頭區(qū)域記錄不同的信息广凸,
2.類(lèi)型指針:即對(duì)象指向它的類(lèi)元數(shù)據(jù)的指針阅茶,虛擬機(jī)通過(guò)這個(gè)指針來(lái)確定這個(gè)對(duì)象是哪個(gè)類(lèi)的實(shí)例。
3.InstanceData:是對(duì)象真正存儲(chǔ)的有效數(shù)據(jù)谅海。也是在程序代碼中所定義的各種類(lèi)型的字段內(nèi)容脸哀。這部分的存儲(chǔ)順序會(huì)受到虛擬機(jī)分配策略參數(shù)和字段在java源碼中定義順序的影響。
4.Padding:對(duì)齊填充并不是必然存在的扭吁,它僅僅起著占位符的作用撞蜂。

根據(jù)鎖的狀態(tài)存儲(chǔ)不同的對(duì)象頭信息

對(duì)象的訪(fǎng)問(wèn)和定位

Java程序需要通過(guò)棧上的reference數(shù)據(jù)來(lái)操作堆上的具體對(duì)象。由于reference類(lèi)型在java虛擬機(jī)規(guī)范中只規(guī)定一個(gè)指向?qū)ο蟮囊媒耐啵](méi)有定義這個(gè)引用應(yīng)該通過(guò)何種方式去定位蝌诡、訪(fǎng)問(wèn)堆中的對(duì)象的具體位置,所以對(duì)象訪(fǎng)問(wèn)方式也是取決于虛擬機(jī)實(shí)現(xiàn)而定的枫吧。目前主流的訪(fǎng)問(wèn)方式有句柄和直接指針兩種浦旱。

1.使用句柄:如果使用句柄訪(fǎng)問(wèn)的話(huà),那么java堆中將會(huì)劃分一塊內(nèi)存來(lái)作為句柄池九杂,reference中存儲(chǔ)的就是對(duì)象的句柄地址颁湖,而句柄包含了對(duì)象實(shí)例數(shù)據(jù)與類(lèi)型數(shù)據(jù)各自的具體地址信息。

使用句柄池
2.直接指針:如果使用直接指針訪(fǎng)問(wèn)例隆,那么java堆對(duì)象的布局中就必須考慮如何放置訪(fǎng)問(wèn)類(lèi)型數(shù)據(jù)的相關(guān)信息甥捺。
使用直接對(duì)象
使用句柄來(lái)訪(fǎng)問(wèn)的最大好處就是reference中存儲(chǔ)的是穩(wěn)定的句柄地址,在對(duì)象被移動(dòng)時(shí)只會(huì)改變句柄中的實(shí)例數(shù)據(jù)指針裳擎,而reference本身不需要修改涎永。使用直接指針訪(fǎng)問(wèn)的最大好處就是速度更快,它節(jié)省了一次指針定位的時(shí)間開(kāi)銷(xiāo)鹿响。其中類(lèi)的信息放在方法區(qū)羡微,調(diào)用方法要知道類(lèi)的信息。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末惶我,一起剝皮案震驚了整個(gè)濱河市妈倔,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌绸贡,老刑警劉巖盯蝴,帶你破解...
    沈念sama閱讀 216,324評(píng)論 6 498
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件毅哗,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡捧挺,警方通過(guò)查閱死者的電腦和手機(jī)虑绵,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,356評(píng)論 3 392
  • 文/潘曉璐 我一進(jìn)店門(mén),熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)闽烙,“玉大人翅睛,你說(shuō)我怎么就攤上這事『诰海” “怎么了捕发?”我有些...
    開(kāi)封第一講書(shū)人閱讀 162,328評(píng)論 0 353
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)很魂。 經(jīng)常有香客問(wèn)我扎酷,道長(zhǎng),這世上最難降的妖魔是什么遏匆? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 58,147評(píng)論 1 292
  • 正文 為了忘掉前任法挨,我火速辦了婚禮,結(jié)果婚禮上拉岁,老公的妹妹穿的比我還像新娘坷剧。我一直安慰自己,他們只是感情好喊暖,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,160評(píng)論 6 388
  • 文/花漫 我一把揭開(kāi)白布惫企。 她就那樣靜靜地躺著,像睡著了一般陵叽。 火紅的嫁衣襯著肌膚如雪狞尔。 梳的紋絲不亂的頭發(fā)上,一...
    開(kāi)封第一講書(shū)人閱讀 51,115評(píng)論 1 296
  • 那天巩掺,我揣著相機(jī)與錄音偏序,去河邊找鬼。 笑死胖替,一個(gè)胖子當(dāng)著我的面吹牛研儒,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播独令,決...
    沈念sama閱讀 40,025評(píng)論 3 417
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼端朵,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了燃箭?” 一聲冷哼從身側(cè)響起冲呢,我...
    開(kāi)封第一講書(shū)人閱讀 38,867評(píng)論 0 274
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎招狸,沒(méi)想到半個(gè)月后敬拓,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體邻薯,經(jīng)...
    沈念sama閱讀 45,307評(píng)論 1 310
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,528評(píng)論 2 332
  • 正文 我和宋清朗相戀三年乘凸,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了厕诡。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 39,688評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡翰意,死狀恐怖木人,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情冀偶,我是刑警寧澤,帶...
    沈念sama閱讀 35,409評(píng)論 5 343
  • 正文 年R本政府宣布渔嚷,位于F島的核電站进鸠,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏形病。R本人自食惡果不足惜客年,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,001評(píng)論 3 325
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望漠吻。 院中可真熱鬧量瓜,春花似錦、人聲如沸途乃。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 31,657評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)耍共。三九已至烫饼,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間试读,已是汗流浹背杠纵。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 32,811評(píng)論 1 268
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留钩骇,地道東北人比藻。 一個(gè)月前我還...
    沈念sama閱讀 47,685評(píng)論 2 368
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像倘屹,于是被迫代替她去往敵國(guó)和親银亲。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,573評(píng)論 2 353

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