JVM--內(nèi)存區(qū)域

一人柿、運(yùn)行時(shí)數(shù)據(jù)區(qū)域

  • Java虛擬機(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)毀慰毅。
    JVM內(nèi)存分布圖

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

  • 程序計(jì)數(shù)器是一塊較小的內(nèi)存空間隘截,可以看作是當(dāng)前線(xiàn)程所執(zhí)行的字節(jié)碼的行號(hào)指示器
  • 線(xiàn)程私有:由于Java虛擬機(jī)的多線(xiàn)程是通過(guò)線(xiàn)程輪流切換并分配處理器執(zhí)行時(shí)間的方式來(lái)是實(shí)現(xiàn)的,在任何一個(gè)確定的時(shí)刻婶芭,一個(gè)處理器(對(duì)于多核處理器來(lái)說(shuō)是一個(gè)內(nèi)核)都會(huì)執(zhí)行一條線(xiàn)程中的指令东臀。因此,為了線(xiàn)程切換后能恢復(fù)到正確的執(zhí)行位置犀农,每條線(xiàn)程都需要有一個(gè)獨(dú)立的程序計(jì)數(shù)器惰赋,各線(xiàn)程計(jì)數(shù)器互不影響,獨(dú)立存儲(chǔ)呵哨。
  • 唯一一個(gè)不會(huì)出現(xiàn)OutOfMemoryError情況的區(qū)域:如果線(xiàn)程正在執(zhí)行的是一個(gè)Java方法赁濒,這個(gè)計(jì)數(shù)器記錄的是正在執(zhí)行的虛擬機(jī)字節(jié)碼指令的地址;如果正在執(zhí)行的是Native方法孟害,這個(gè)計(jì)數(shù)器值為空(Undefined)拒炎。

2 Java虛擬機(jī)棧(Java Virtual Machine Stacks)

  • 線(xiàn)程私有,生命周期與線(xiàn)程相同
  • 存儲(chǔ)局部變量表(基本類(lèi)型挨务、對(duì)象引用)击你、操作數(shù)棧、動(dòng)態(tài)鏈接谎柄、方法出口等信息丁侄。
  • java方法執(zhí)行的內(nèi)存模型,每個(gè)方法執(zhí)行的同時(shí)都會(huì)創(chuàng)建一個(gè)棧幀朝巫,每一個(gè)方法被調(diào)用直至執(zhí)行完成的過(guò)程鸿摇,就對(duì)應(yīng)著一個(gè)棧幀在虛擬機(jī)棧中從入棧到出棧的過(guò)程。
  • StackOverflowError異常:當(dāng)線(xiàn)程請(qǐng)求的棧深度大于虛擬機(jī)所允許的深度
  • OutOfMemoryError異常:如果棧的擴(kuò)展時(shí)無(wú)法申請(qǐng)到足夠的內(nèi)存

JVM棧是線(xiàn)程私有的劈猿,每個(gè)線(xiàn)程創(chuàng)建的同時(shí)都會(huì)創(chuàng)建JVM棧户辱,JVM棧中存放的為當(dāng)前線(xiàn)程中局部基本類(lèi)型的變量、部分的返回結(jié)果以及Stack Frame糙臼。其他引用類(lèi)型的對(duì)象在JVM棧上僅存放變量名和指向堆上對(duì)象實(shí)例的首地址。

3 本地方法棧(Native Method Stack)

  • 與虛擬機(jī)棧相似恩商,主要為虛擬機(jī)使用到Native方法服務(wù)变逃,在HotSpot虛擬機(jī)中直接把本地方法棧與虛擬機(jī)棧二合一

4 Java堆(Java Heap)

  • 被所有線(xiàn)程共享的一塊內(nèi)存區(qū)域,在虛擬機(jī)啟動(dòng)時(shí)創(chuàng)建
  • 所有的對(duì)象實(shí)例以及數(shù)組都要在堆上分配
  • 可以通過(guò)-Xmx和-Xms控制堆的大小
  • OutOfMemoryError異常:當(dāng)在堆中沒(méi)有內(nèi)存完成實(shí)例分配怠堪,且堆也無(wú)法再擴(kuò)展時(shí)揽乱。

Java堆是垃圾收集器管理的主要區(qū)域。
細(xì)致劃分為:
(1) 新生代:新建的對(duì)象都由新生代分配內(nèi)存粟矿。常常又被劃分為Eden區(qū)和Survivor區(qū)凰棉。Eden空間不足時(shí)會(huì)把存活的對(duì)象轉(zhuǎn)移到Survivor。新生代的大小可由-Xmn控制陌粹,也可用-XX:SurvivorRatio控制Eden和Survivor的比例撒犀。
(2) 舊生代:存放經(jīng)過(guò)多次垃圾回收仍然存活的對(duì)象。

  • 持久代(方法區(qū)):存放靜態(tài)文件,如今Java類(lèi)或舞、方法等荆姆。持久代在方法區(qū),對(duì)垃圾回收沒(méi)有顯著影響映凳。

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

  • 線(xiàn)程間共享
  • 用于存儲(chǔ)已被虛擬機(jī)加載的類(lèi)信息胆筒、常量、靜態(tài)變量诈豌、即時(shí)編譯器后的代碼等數(shù)據(jù)仆救。
  • OutOfMemoryError異常:當(dāng)方法區(qū)無(wú)法滿(mǎn)足內(nèi)存的分配需求時(shí)

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

  • 方法區(qū)的一部分
  • 用于存放編譯期生成的各種字面量和符號(hào)引用,如String類(lèi)型常量就存放在常量池
  • OutOfMemoryError異常:當(dāng)常量池?zé)o法再申請(qǐng)到內(nèi)存時(shí)

7 直接內(nèi)存(Direct Memory)

  • 直接內(nèi)存并不是虛擬機(jī)運(yùn)行的一部分矫渔,也不是Java虛擬機(jī)規(guī)范中定義的內(nèi)存區(qū)域彤蔽,但是這部分內(nèi)存也被頻繁使用
  • OutOfMemoryError異常:系統(tǒng)內(nèi)存不足時(shí)
  • NIO可以使用Native函數(shù)庫(kù)直接分配堆外內(nèi)存,堆中的DirectByteBuffer對(duì)象作為這塊內(nèi)存的引用進(jìn)行操作
  • 大小不受Java堆大小的限制,受本機(jī)(服務(wù)器)內(nèi)存限制

注:

  1. Java對(duì)象實(shí)例存放在堆中;
  2. 常量存放在方法區(qū)的常量池格带;
  3. 虛擬機(jī)加載的類(lèi)信息肛宋、常量、靜態(tài)變量誓沸、及時(shí)編輯器編譯后的代碼等數(shù)據(jù)放在方法區(qū);
  4. 以上區(qū)域是所有線(xiàn)程共享的;
    5.棧是線(xiàn)程私有的撕阎,存放該方法的局部變量表(基本類(lèi)型、對(duì)象引用)碌补、操作數(shù)棧虏束、動(dòng)態(tài)鏈接、方法出口等信息厦章;
    6.一個(gè)Java程序?qū)?yīng)一個(gè)JVM镇匀,一個(gè)方法(線(xiàn)程)對(duì)應(yīng)一個(gè)Java棧。

二袜啃、Java 對(duì)象的內(nèi)存分布

1. 存儲(chǔ)布局的3塊區(qū)域

1.1 對(duì)象頭(Header)

分為兩部分信息:

  • 一部分用于存儲(chǔ)對(duì)象自身的運(yùn)行時(shí)數(shù)據(jù)汗侵,如哈希碼(HashCode)、GC分代年齡群发、鎖狀態(tài)標(biāo)志晰韵、線(xiàn)程持有的鎖、偏向線(xiàn)程ID熟妓、偏向時(shí)間戳等雪猪,這部分的長(zhǎng)度在32位和64位(未開(kāi)啟壓縮指針)中分別為32bit和64bit,即 “Mark Word”起愈。


    HotSpot 虛擬機(jī)對(duì)象頭 Mark Work
  • 另一部分是類(lèi)型指針只恨,即對(duì)象指向它的類(lèi)元數(shù)據(jù)的指針译仗,虛擬機(jī)通過(guò)這個(gè)指針來(lái)確定這個(gè)對(duì)象是哪個(gè)類(lèi)的實(shí)例
1.2 實(shí)例數(shù)據(jù)(Instance Data)
  • 是對(duì)象真正存儲(chǔ)的有效信息,也是在程序代碼中所定義的各種類(lèi)型的字段內(nèi)容
1.3 對(duì)齊填充(Padding)
  • 類(lèi)似于占位符坤次,由于 HotSpot的自動(dòng)內(nèi)存管理系統(tǒng)要求對(duì)象起始位置必須是 8字節(jié)的整數(shù)倍古劲,即對(duì)象的大小必須是 8字節(jié)的整數(shù)倍,而對(duì)象頭部分在正好是 8字節(jié)的倍數(shù)(1倍或者2倍)缰猴,因此产艾,當(dāng)對(duì)象實(shí)例數(shù)據(jù)部分沒(méi)有對(duì)齊時(shí),就需要通過(guò)對(duì)齊填充來(lái)補(bǔ)全滑绒。

2.壓縮指針

  • 為了減少類(lèi)型指針的內(nèi)存占用闷堡,將 64 為指針壓縮至 32 位,進(jìn)而節(jié)約內(nèi)存疑故。之前 64 為尋址杠览,尋的是字節(jié),現(xiàn)在 32 位尋址纵势,尋的是變量踱阿。
  • 對(duì)應(yīng)虛擬機(jī)選項(xiàng) -XX:+UseCompressedOops,默認(rèn)開(kāi)啟钦铁∪砩啵可將堆中原本 64位的Java對(duì)象指針壓縮成32 位的。因此對(duì)象頭中的類(lèi)型指針也會(huì)被壓縮成 32位牛曹,使得對(duì)象頭大小從 16字節(jié)將至 12字節(jié)佛点。
  • 內(nèi)存對(duì)齊,對(duì)應(yīng)虛擬機(jī)選項(xiàng) -XX:ObjectAlignmentlnBytes黎比,默認(rèn)值為 8超营。使得CPU緩存行 可以更好的實(shí)施。保證每個(gè)變量都只出現(xiàn)在一條緩存行中阅虫,不會(huì)出現(xiàn)跨行緩存演闭。提高程序的執(zhí)行效率

3. 字段重排列

  • Java 虛擬機(jī)重新分配字段的先后順序,以達(dá)到內(nèi)存對(duì)齊的目的颓帝,即方便尋址和節(jié)省空間米碰。JVM有三種排列方法(對(duì)應(yīng)JVM選項(xiàng) -XX:FieldsAllocationStyle,默認(rèn)值為1)
    遵循的規(guī)則:
    1. 如果一個(gè)字段占據(jù) C 個(gè)字節(jié)躲履,那么該字段的偏移量需要對(duì)齊至 NC。(這里偏移量至的是字段地址與對(duì)象的起始地址差值)聊闯。
      以long 類(lèi)為例工猜,它僅有一個(gè) long 類(lèi)型的實(shí)例字段,在使用了壓縮指針的 64位虛擬機(jī)中菱蔬,盡管對(duì)象頭的大小為 12 字節(jié)篷帅,該long 類(lèi)型字段的偏移量也只能是16史侣, 而中間空著的 4字節(jié)便會(huì)被浪費(fèi)掉。
    2. 子類(lèi)所繼承字段的偏移量魏身,需要與父類(lèi)對(duì)應(yīng)字段的偏移量保持一致惊橱。
      對(duì)具體實(shí)現(xiàn)中,Java 虛擬機(jī)還會(huì)對(duì)齊子類(lèi)字段的起始位置箭昵。對(duì)于使用了壓縮指針的 64位虛擬機(jī)税朴,子類(lèi)第一個(gè)字段需要對(duì)齊至 4N;而對(duì)于關(guān)閉了壓縮指針的 64位虛擬機(jī)家制,子類(lèi)第一個(gè)字段則需要對(duì)齊至 8N正林。
      如下代碼:
class A {
  long l;
  int i;
}

class B extends A {
  long l;
  int i;
}

啟動(dòng)壓縮指針觅廓,子類(lèi)第一個(gè)字段需要對(duì)齊至 4N,對(duì)象整體大小也需要對(duì)齊至 4N

# 啟用壓縮指針時(shí)涵但,B 類(lèi)的字段分布
B object internals:
 OFFSET  SIZE   TYPE DESCRIPTION
      0     4        (object header)
      4     4        (object header)
      8     4        (object header)
     12     4    int A.i                                       0
     16     8   long A.l                                       0
     24     8   long B.l                                       0
     32     4    int B.i                                       0
     36     4        (loss due to the next object alignment)

關(guān)閉壓縮指針杈绸,子類(lèi)第一個(gè)字段需要對(duì)齊至 8N,并且對(duì)象整體大小也需要對(duì)齊至 8N

# 關(guān)閉壓縮指針時(shí)矮瘟,B 類(lèi)的字段分布
B object internals:
 OFFSET  SIZE   TYPE DESCRIPTION
      0     4        (object header)
      4     4        (object header)
      8     4        (object header)
     12     4        (object header)
     16     8   long A.l
     24     4    int A.i
     28     4        (alignment/padding gap)                  
     32     8   long B.l
     40     4    int B.i
     44     4        (loss due to the next object alignment)
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末瞳脓,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子芥永,更是在濱河造成了極大的恐慌篡殷,老刑警劉巖,帶你破解...
    沈念sama閱讀 218,607評(píng)論 6 507
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件埋涧,死亡現(xiàn)場(chǎng)離奇詭異板辽,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī)棘催,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,239評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門(mén)劲弦,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人醇坝,你說(shuō)我怎么就攤上這事邑跪。” “怎么了呼猪?”我有些...
    開(kāi)封第一講書(shū)人閱讀 164,960評(píng)論 0 355
  • 文/不壞的土叔 我叫張陵画畅,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我宋距,道長(zhǎng)轴踱,這世上最難降的妖魔是什么? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 58,750評(píng)論 1 294
  • 正文 為了忘掉前任谚赎,我火速辦了婚禮淫僻,結(jié)果婚禮上诱篷,老公的妹妹穿的比我還像新娘。我一直安慰自己雳灵,他們只是感情好棕所,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,764評(píng)論 6 392
  • 文/花漫 我一把揭開(kāi)白布。 她就那樣靜靜地躺著悯辙,像睡著了一般琳省。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上笑撞,一...
    開(kāi)封第一講書(shū)人閱讀 51,604評(píng)論 1 305
  • 那天岛啸,我揣著相機(jī)與錄音,去河邊找鬼茴肥。 笑死坚踩,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的瓤狐。 我是一名探鬼主播瞬铸,決...
    沈念sama閱讀 40,347評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼础锐!你這毒婦竟也來(lái)了嗓节?” 一聲冷哼從身側(cè)響起,我...
    開(kāi)封第一講書(shū)人閱讀 39,253評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤皆警,失蹤者是張志新(化名)和其女友劉穎拦宣,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體信姓,經(jīng)...
    沈念sama閱讀 45,702評(píng)論 1 315
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡鸵隧,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,893評(píng)論 3 336
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了意推。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片豆瘫。...
    茶點(diǎn)故事閱讀 40,015評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖菊值,靈堂內(nèi)的尸體忽然破棺而出外驱,到底是詐尸還是另有隱情,我是刑警寧澤腻窒,帶...
    沈念sama閱讀 35,734評(píng)論 5 346
  • 正文 年R本政府宣布昵宇,位于F島的核電站,受9級(jí)特大地震影響儿子,放射性物質(zhì)發(fā)生泄漏瓦哎。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,352評(píng)論 3 330
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望杭煎。 院中可真熱鬧,春花似錦卒落、人聲如沸羡铲。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 31,934評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)也切。三九已至,卻和暖如春腰湾,著一層夾襖步出監(jiān)牢的瞬間雷恃,已是汗流浹背。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 33,052評(píng)論 1 270
  • 我被黑心中介騙來(lái)泰國(guó)打工费坊, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留倒槐,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 48,216評(píng)論 3 371
  • 正文 我出身青樓附井,卻偏偏與公主長(zhǎng)得像讨越,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子永毅,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,969評(píng)論 2 355

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