【JVM】Java內(nèi)存區(qū)域詳解

本文將介紹了 Java 虛擬機內(nèi)存的各個區(qū)域以及這些區(qū)域的作用、服務對象和其中可能出現(xiàn)的異常等。

JVM 運行時數(shù)據(jù)區(qū)域

Java 虛擬機在執(zhí)行 Java 程序的過程中會把它所管理的內(nèi)存劃分為五個不同的數(shù)據(jù)區(qū)域(如圖所示)梆奈。

image
  • 紅色邊框的是由所有線程共享的數(shù)據(jù)區(qū)
  • 藍色邊框的是線程隔離的數(shù)據(jù)區(qū)

除了程序計數(shù)器之外撵颊,其他四個區(qū)域都可能會出現(xiàn) OutOfMemoryError 異常。

程序計數(shù)器

  • 程序計數(shù)器是一塊較小的內(nèi)存空間

  • 是當前線程所執(zhí)行的字節(jié)碼的行號顯示器

  • 字節(jié)碼解釋器就是通過改變這個計數(shù)器的值來選取下一條需要執(zhí)行的字節(jié)碼指令的

  • 執(zhí)行 Java 方法和執(zhí)行 Native 方法的區(qū)別:

    • 執(zhí)行 Java 方法時抱虐,計數(shù)器記錄虛擬機正在執(zhí)行的字節(jié)碼指令的地址
    • 執(zhí)行 Native 方法時颈将,無記錄梢夯,也就是計數(shù)器的值為空(Undefined)

程序計數(shù)器是唯一一個不會出現(xiàn) OOM 的區(qū)域。

Java 虛擬機棧

  • 每個 Java 方法被執(zhí)行的時候晴圾,Java 虛擬機都會同步創(chuàng)建一個棧幀用于存儲局部變量表颂砸、操作數(shù)棧、動態(tài)連接疑务、方法出口等信息

  • 每個方法被調(diào)用一直到執(zhí)行完畢的過程沾凄,都對應著一個棧幀在 Java 虛擬機棧中從入棧到出棧的過程

  • Java 虛擬機棧服務于 Java 方法

  • 可能出現(xiàn)的異常:

    • StackOverflowError:線程請求的棧深度 大于 Java 虛擬機所允許的深度時
    • OutOfMemoryError:在 Java 虛擬機棧容量可動態(tài)擴展的情況下,當棧擴展時無法申請到足夠的內(nèi)存時
  • 虛擬機參數(shù)設置:-Xss

本地方法棧

  • 與 Java 虛擬機棧發(fā)揮的作用類似知允,區(qū)別在于本地方法棧服務于 Native 方法

  • 可能出現(xiàn)的異常:與 Java 虛擬機棧一樣叙谨。

Java 堆

  • 唯一目的:存放對象實例

  • 垃圾回收器管理的內(nèi)存區(qū)域

  • 可以處于物理上不連續(xù)的內(nèi)存空間中温鸽,但是在邏輯上應該是連續(xù)的

  • 可能出現(xiàn)的異常:

    • OutOfMemoryError:Java 堆中沒有內(nèi)存完成實例分配,并且堆也無法再擴展時
  • 虛擬機參數(shù)設置:

    • 最大值:-Xmx

    • 最小值:-Xms

    • 兩個參數(shù)設置成相同值時可避免堆自動擴展

方法區(qū)

  • 用于存儲已被 Java 虛擬機加載的類型信息、常量涤垫、靜態(tài)變量姑尺、即時編譯器編譯后的代碼緩存等數(shù)據(jù)

  • 可以選擇不實現(xiàn)垃圾收集,換句話說垃圾收集行為在這個區(qū)域非常少見蝠猬,但是對于經(jīng)常動態(tài)性生成大量 Class 的應用切蟋,如 Spring 等,需要特別注意類的回收情況

  • 可能出現(xiàn)的異常:

    • OutOfMemoryError:方法區(qū)無法滿足新的內(nèi)存分配需求時

運行時常量池

  • 運行時常量池是方法區(qū)的一部分
  • Class 文件除了有類的版本榆芦、字段柄粹、方法、接口等描述信息外匆绣,還有一項是常量池表驻右,用于存放編譯期生成的各種字面量(就是代碼中定義的 static final 常量)和符號引用,這部分內(nèi)容將在類加載后存放到方法區(qū)的運行時常量池中
  • 可能出現(xiàn)的異常:
    • OutOfMemoryError:常量池無法再申請到內(nèi)存時

直接內(nèi)存

  • 不屬于 Java 虛擬機運行時數(shù)據(jù)區(qū)域的一部分崎淳,放到這里講是因為這部分內(nèi)存在使用的時候也可能導致 OutOfMemoryError 異常的出現(xiàn):各個內(nèi)存區(qū)域總和大于物理內(nèi)存限制(包括物理的和操作系統(tǒng)級的限制)堪夭,從而導致動態(tài)擴展時出現(xiàn) OutOfMemoryError 異常

  • JDK1.4 的 NIO 類可以使用 Native 函數(shù)庫直接分配堆外內(nèi)存,然后通過一個存儲在 Java 堆里面的 DirectByteBuffer 對象作為這塊內(nèi)存的引用進行操作拣凹,好處是避免了在 Java 堆和 Native 堆中來回復制數(shù)據(jù)森爽,能在一些場景中提高性能

  • 虛擬機參數(shù)設置:-XX:MaxDirectMemorySize

    • 默認等于 Java 堆最大值,即-Xmx指定的值

HotSpot 虛擬機堆中的對象

介紹完 Java 虛擬機的運行時數(shù)據(jù)區(qū)域后嚣镜,我們大致了解的 Java 虛擬機內(nèi)存模型的概況拗秘。這一小節(jié)將介紹 HotSpot 虛擬機在 Java 堆中對象分配、布局和訪問的全過程祈惶。

對象的創(chuàng)建(new)

當虛擬機遇到 new 指令時:

  1. 檢查這個指令的參數(shù)是否能在常量池中定位到一個類的符號引用雕旨,并檢查這個符號引用代表的類是否已經(jīng)被加載、解析和初始化過捧请。如果沒有凡涩,則先把這個類加載進內(nèi)存
  2. 類加載檢查通過后,虛擬機將為這個新的對象分配內(nèi)存疹蛉,內(nèi)存的大小在類加載完成后確定
  3. 在 Java 堆中為新對象分配可用內(nèi)存
  4. 內(nèi)存分配完成后活箕,虛擬機將分配到的內(nèi)存空間都初始化為零值
  5. 虛擬機設置對象頭中的數(shù)據(jù)
  6. 此時,從虛擬機的角度看可款,對象已經(jīng)創(chuàng)建好了育韩,但從 Java 程序角度看,對象創(chuàng)建才剛剛開始闺鲸,構造函數(shù)還沒有執(zhí)行

第 3 步中筋讨,為對象分配可用內(nèi)存時,會涉及兩個問題:

  1. 內(nèi)存分配方式
     - 指針碰撞(Java 堆中的內(nèi)存是絕對規(guī)整的)
       - 所有被使用過的內(nèi)存放在一邊摸恍,沒有被使用過的內(nèi)存放在另一邊悉罕,中間放一個指針赤屋,作為分界點的指示器,那所分配的內(nèi)存就僅僅是把那個指針向空閑內(nèi)存空間方向挪一段與對象大小相等的距離
     - 空閑列表(Java 堆中被使用的內(nèi)存和空閑內(nèi)存相互交錯在一起)
       - Java 虛擬機需要維護一個列表壁袄,記錄上哪些內(nèi)存塊是可用的类早,在分配的時候從列表中找一塊大小足夠大的空間劃分給對象實例
  2. 在并發(fā)情況下虛擬機創(chuàng)建對象也并不是線程安全的,可能出現(xiàn)正在給對象 A 分配內(nèi)存嗜逻,指針還沒來得及修改涩僻,對象 B 又同時使用了原來的指針來分配內(nèi)存的情況
     - 對分配內(nèi)存空間的動作進行同步處理( 采用 CAS 配上失敗重試的方式保證更新操作的原子性 )
     - 把內(nèi)存分配的動作按照線程劃分在不同的空間中進行(每個線程在 Java 堆中預先分配一塊小內(nèi)存(這個小內(nèi)存稱為**本地線程分配緩沖區(qū)**),哪個線程要分配內(nèi)存栈顷,就在哪個線程的本地線程分配緩沖區(qū)中分配逆日,只有這個本地線程分配緩沖區(qū)分配完了,分配新的本地線程分配緩沖區(qū)才需要同步鎖定)
       - 虛擬機參數(shù)設置:`-XX:+/-UseTLAB`

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

在 HotSpot 虛擬機中妨蛹,對象在堆內(nèi)存中的存儲布局分為三部分:

  • 對象頭(包括兩類信息)
    • 用于存儲對象自身的運行時數(shù)據(jù)屏富,如 HashCode、GC 分代年齡蛙卤、鎖狀態(tài)標志狠半、線程持有的鎖、偏向線程 ID颤难、偏向時間戳等
    • 類型指針神年,即對象指向它的類型元數(shù)據(jù)的指針,虛擬機通過這個指針來確定該對象是哪個類的實例行嗤。
  • 實例數(shù)據(jù)(存儲我們在程序代碼中定義的各種類型的字段內(nèi)容)
    • 這部分數(shù)據(jù)受到虛擬機分配策略參數(shù)(-XX:FieldsAllocationStyle)和字段在代碼中定義順序的影響
  • 對齊填充(沒有實際意義已日,起到占位符的作用)

對象的訪問定位

我們創(chuàng)建對象之后自然是要使用對象,Java 程序會通過棧上的 reference 數(shù)據(jù)來操作堆上的具體對象(reference 是一個指向對象的引用)栅屏。

主流的對象訪問方式有兩種:

  • 通過句柄訪問(reference 中存儲的是穩(wěn)定的句柄地址飘千,在對象被移動的時候只會改變句柄中的實例數(shù)據(jù)指針,而 reference 本身不需要被修改)
image
  • 通過直接指針訪問(速度快得一批栈雳,節(jié)省了一次指針定位的時間開銷)
image

本文小結

本文從概念上介紹了 Java 虛擬機內(nèi)存的各個區(qū)域以及這些區(qū)域的作用护奈、服務對象和其中可能出現(xiàn)的異常等,還介紹了虛擬機創(chuàng)建對象(new)的過程哥纫、對象的內(nèi)存布局和如何訪問對象霉旗。

?著作權歸作者所有,轉載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市蛀骇,隨后出現(xiàn)的幾起案子厌秒,更是在濱河造成了極大的恐慌,老刑警劉巖擅憔,帶你破解...
    沈念sama閱讀 211,290評論 6 491
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件鸵闪,死亡現(xiàn)場離奇詭異,居然都是意外死亡雕欺,警方通過查閱死者的電腦和手機岛马,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,107評論 2 385
  • 文/潘曉璐 我一進店門棉姐,熙熙樓的掌柜王于貴愁眉苦臉地迎上來屠列,“玉大人啦逆,你說我怎么就攤上這事〉崖澹” “怎么了夏志?”我有些...
    開封第一講書人閱讀 156,872評論 0 347
  • 文/不壞的土叔 我叫張陵,是天一觀的道長苛让。 經(jīng)常有香客問我沟蔑,道長,這世上最難降的妖魔是什么狱杰? 我笑而不...
    開封第一講書人閱讀 56,415評論 1 283
  • 正文 為了忘掉前任瘦材,我火速辦了婚禮,結果婚禮上仿畸,老公的妹妹穿的比我還像新娘食棕。我一直安慰自己,他們只是感情好错沽,可當我...
    茶點故事閱讀 65,453評論 6 385
  • 文/花漫 我一把揭開白布簿晓。 她就那樣靜靜地躺著,像睡著了一般千埃。 火紅的嫁衣襯著肌膚如雪憔儿。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,784評論 1 290
  • 那天放可,我揣著相機與錄音谒臼,去河邊找鬼。 笑死耀里,一個胖子當著我的面吹牛蜈缤,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播备韧,決...
    沈念sama閱讀 38,927評論 3 406
  • 文/蒼蘭香墨 我猛地睜開眼劫樟,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了织堂?” 一聲冷哼從身側響起叠艳,我...
    開封第一講書人閱讀 37,691評論 0 266
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎易阳,沒想到半個月后附较,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 44,137評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡潦俺,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,472評論 2 326
  • 正文 我和宋清朗相戀三年拒课,在試婚紗的時候發(fā)現(xiàn)自己被綠了徐勃。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 38,622評論 1 340
  • 序言:一個原本活蹦亂跳的男人離奇死亡早像,死狀恐怖僻肖,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情卢鹦,我是刑警寧澤臀脏,帶...
    沈念sama閱讀 34,289評論 4 329
  • 正文 年R本政府宣布,位于F島的核電站冀自,受9級特大地震影響揉稚,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜熬粗,卻給世界環(huán)境...
    茶點故事閱讀 39,887評論 3 312
  • 文/蒙蒙 一搀玖、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧驻呐,春花似錦灌诅、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,741評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至答渔,卻和暖如春关带,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背沼撕。 一陣腳步聲響...
    開封第一講書人閱讀 31,977評論 1 265
  • 我被黑心中介騙來泰國打工宋雏, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人务豺。 一個月前我還...
    沈念sama閱讀 46,316評論 2 360
  • 正文 我出身青樓磨总,卻偏偏與公主長得像,于是被迫代替她去往敵國和親笼沥。 傳聞我的和親對象是個殘疾皇子蚪燕,可洞房花燭夜當晚...
    茶點故事閱讀 43,490評論 2 348

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