深入理解JVM(1)之--JVM內(nèi)存模型

參考原地址

JVM內(nèi)存模型

Java虛擬機(Java Virtual Machine=JVM)的內(nèi)存空間分為五個部分粤攒,分別是:
1. 程序計數(shù)器
2. Java虛擬機棧
3. 本地方法棧
4. 堆
5. 方法區(qū)百炬。

下面對這五個區(qū)域展開深入的介紹。

1. 程序計數(shù)器

1.1. 什么是程序計數(shù)器诫咱?

程序計數(shù)器是一塊較小的內(nèi)存空間溃列,可以把它看作當(dāng)前線程正在執(zhí)行的字節(jié)碼的行號指示器。也就是說困乒,程序計數(shù)器里面記錄的是當(dāng)前線程正在執(zhí)行的那一條字節(jié)碼指令的地址蝗肪。
注:但是袜爪,如果當(dāng)前線程正在執(zhí)行的是一個本地方法,那么此時程序計數(shù)器為空薛闪。

1.2. 程序計數(shù)器的作用

程序計數(shù)器有兩個作用:

  1. 字節(jié)碼解釋器通過改變程序計數(shù)器來依次讀取指令辛馆,從而實現(xiàn)代碼的流程控制,如:順序執(zhí)行豁延、選擇怀各、循環(huán)、異常處理术浪。
  2. 在多線程的情況下瓢对,程序計數(shù)器用于記錄當(dāng)前線程執(zhí)行的位置,從而當(dāng)線程被切換回來的時候能夠知道該線程上次運行到哪兒了胰苏。

1.3. 程序計數(shù)器的特點

  1. 是一塊較小的存儲空間
  2. 線程私有硕蛹。每條線程都有一個程序計數(shù)器。
  3. 是唯一一個不會出現(xiàn)OutOfMemoryError的內(nèi)存區(qū)域。
  4. 生命周期隨著線程的創(chuàng)建而創(chuàng)建法焰,隨著線程的結(jié)束而死亡秧荆。

2. Java虛擬機棧(JVM Stack)

2.1. 什么是Java虛擬機棧?

Java虛擬機棧是描述Java方法運行過程的內(nèi)存模型埃仪。
Java虛擬機棧會為每一個即將運行的Java方法創(chuàng)建一塊叫做“棧幀”的區(qū)域乙濒,這塊區(qū)域用于存儲該方法在運行過程中所需要的一些信息,這些信息包括:

  1. 局部變量表
    存放基本數(shù)據(jù)類型變量卵蛉、引用類型的變量颁股、returnAddress類型的變量。
  2. 操作數(shù)棧
  3. 動態(tài)鏈接
  4. 方法出口信息

當(dāng)一個方法即將被運行時傻丝,Java虛擬機棧首先會在Java虛擬機棧中為該方法創(chuàng)建一塊“棧幀”甘有,棧幀中包含局部變量表、操作數(shù)棧葡缰、動態(tài)鏈接亏掀、方法出口信息等。當(dāng)方法在運行過程中需要創(chuàng)建局部變量時泛释,就將局部變量的值存入棧幀的局部變量表中滤愕。
當(dāng)這個方法執(zhí)行完畢后,這個方法所對應(yīng)的棧幀將會出棧怜校,并釋放內(nèi)存空間间影。

注意:人們常說,Java的內(nèi)存空間分為“椌禄”和“堆”,棧中存放局部變量蔓搞,堆中存放對象胰丁。
這句話不完全正確!這里的“堆”可以這么理解喂分,但這里的“椊跤梗”只代表了Java虛擬機棧中的局部變量表部分。真正的Java虛擬機棧是由一個個棧幀組成蒲祈,而每個棧幀中都擁有:局部變量表甘萧、操作數(shù)棧、動態(tài)鏈接梆掸、方法出口信息扬卷。

2.2. Java虛擬機棧的特點

  1. 局部變量表的創(chuàng)建是在方法被執(zhí)行的時候,隨著棧幀的創(chuàng)建而創(chuàng)建酸钦。而且怪得,局部變量表的大小在編譯時期就確定下來了,在創(chuàng)建的時候只需分配事先規(guī)定好的大小即可。此外徒恋,在方法運行的過程中局部變量表的大小是不會發(fā)生改變的蚕断。
  2. Java虛擬機棧會出現(xiàn)兩種異常:StackOverFlowError和OutOfMemoryError。
    a) StackOverFlowError:
    若Java虛擬機棧的內(nèi)存大小不允許動態(tài)擴展入挣,那么當(dāng)線程請求棧的深度超過當(dāng)前Java虛擬機棧的最大深度的時候亿乳,就拋出StackOverFlowError異常.
    b) OutOfMemoryError:
    若Java虛擬機棧的內(nèi)存大小允許動態(tài)擴展,且當(dāng)線程請求棧時內(nèi)存用完了径筏,無法再動態(tài)擴展了葛假,此時拋出OutOfMemoryError異常。
  3. Java虛擬機棧也是線程私有的匠璧,每個線程都有各自的Java虛擬機棧桐款,而且隨著線程的創(chuàng)建而創(chuàng)建,隨著線程的死亡而死亡夷恍。

注:StackOverFlowError和OutOfMemoryError的異同魔眨?

StackOverFlowError表示當(dāng)前線程申請的棧超過了事先定好的棧的最大深度,但內(nèi)存空間可能還有很多酿雪。
而OutOfMemoryError是指當(dāng)線程申請棧時發(fā)現(xiàn)棧已經(jīng)滿了遏暴,而且內(nèi)存也全都用光了。

3. 本地方法棧

3.1. 什么是本地方法棧指黎?

本地方法棧和Java虛擬機棧實現(xiàn)的功能類似朋凉,只不過本地方法區(qū)是本地方法運行的內(nèi)存模型。

本地方法被執(zhí)行的時候醋安,在本地方法棧也會創(chuàng)建一個棧幀杂彭,用于存放該本地方法的局部變量表、操作數(shù)棧吓揪、動態(tài)鏈接亲怠、出口信息。

方法執(zhí)行完畢后相應(yīng)的棧幀也會出棧并釋放內(nèi)存空間柠辞。

也會拋出StackOverFlowError和OutOfMemoryError異常团秽。

4. 堆

4.1. 什么是堆?

堆是用來存放對象的內(nèi)存空間叭首。
幾乎所有的對象都存儲在堆中习勤。

4.2. 堆的特點

  1. 線程共享
    整個Java虛擬機只有一個堆,所有的線程都訪問同一個堆焙格。而程序計數(shù)器图毕、Java虛擬機棧、本地方法棧都是一個線程對應(yīng)一個的眷唉。
  2. 在虛擬機啟動時創(chuàng)建
  3. 垃圾回收的主要場所吴旋。
  4. 可以進一步細(xì)分為:新生代损肛、老年代。
    新生代又可被分為:Eden荣瑟、From Survior治拿、To Survior。
    不同的區(qū)域存放具有不同生命周期的對象笆焰。這樣可以根據(jù)不同的區(qū)域使用不同的垃圾回收算法劫谅,從而更具有針對性,從而更高效嚷掠。
  5. 堆的大小既可以固定也可以擴展捏检,但主流的虛擬機堆的大小是可擴展的,因此當(dāng)線程請求分配內(nèi)存不皆,但堆已滿贯城,且內(nèi)存已滿無法再擴展時,就拋出OutOfMemoryError霹娄。

5. 方法區(qū)

5.1. 什么是方法區(qū)能犯?

Java虛擬機規(guī)范中定義方法區(qū)是堆的一個邏輯部分。
方法區(qū)中存放已經(jīng)被虛擬機加載的類信息犬耻、常量踩晶、靜態(tài)變量、即時編譯器編譯后的代碼等枕磁。

5.2. 方法區(qū)的特點

  1. 線程共享
    方法區(qū)是堆的一個邏輯部分渡蜻,因此和堆一樣,都是線程共享的计济。整個虛擬機中只有一個方法區(qū)茸苇。
  2. 永久代
    方法區(qū)中的信息一般需要長期存在,而且它又是堆的邏輯分區(qū)沦寂,因此用堆的劃分方法学密,我們把方法區(qū)稱為老年代。
  3. 內(nèi)存回收效率低
    方法區(qū)中的信息一般需要長期存在凑队,回收一遍內(nèi)存之后可能只有少量信息無效则果。
    對方法區(qū)的內(nèi)存回收的主要目標(biāo)是:對常量池的回收 和 對類型的卸載幔翰。
  4. Java虛擬機規(guī)范對方法區(qū)的要求比較寬松漩氨。
    和堆一樣,允許固定大小遗增,也允許可擴展的大小叫惊,還允許不實現(xiàn)垃圾回收。

5.3. 什么是運行時常量池做修?

方法區(qū)中存放三種數(shù)據(jù):類信息霍狰、常量抡草、靜態(tài)變量、即時編譯器編譯后的代碼蔗坯。其中常量存儲在運行時常量池中康震。

我們一般在一個類中通過public static final來聲明一個常量。這個類被編譯后便生成Class文件宾濒,這個類的所有信息都存儲在這個class文件中腿短。

當(dāng)這個類被Java虛擬機加載后,class文件中的常量就存放在方法區(qū)的運行時常量池中绘梦。而且在運行期間橘忱,可以向常量池中添加新的常量。如:String類的intern()方法就能在運行期間向常量池中添加字符串常量卸奉。

當(dāng)運行時常量池中的某些常量沒有被對象引用钝诚,同時也沒有被變量引用,那么就需要垃圾收集器回收榄棵。

6. 直接內(nèi)存

接內(nèi)存是除Java虛擬機之外的內(nèi)存凝颇,但也有可能被Java使用

在NIO中引入了一種基于通道和緩沖的IO方式秉继。它可以通過調(diào)用本地方法直接分配Java虛擬機之外的內(nèi)存祈噪,然后通過一個存儲在Java堆中的DirectByteBuffer對象直接操作該內(nèi)存,而無需先將外面內(nèi)存中的數(shù)據(jù)復(fù)制到堆中再操作尚辑,從而提升了數(shù)據(jù)操作的效率辑鲤。

直接內(nèi)存的大小不受Java虛擬機控制,但既然是內(nèi)存杠茬,當(dāng)內(nèi)存不足時就會拋出OOM異常月褥。

綜上所述

  1. Java虛擬機的內(nèi)存模型中一共有兩個“棧”瓢喉,分別是:Java虛擬機棧和本地方法棧宁赤。
    兩個“棧”的功能類似栓票,都是方法運行過程的內(nèi)存模型决左。并且兩個“棧”內(nèi)部構(gòu)造相同走贪,都是線程私有佛猛。
    只不過Java虛擬機棧描述的是Java方法運行過程的內(nèi)存模型,而本地方法棧是描述Java本地方法運行過程的內(nèi)存模型坠狡。
  2. Java虛擬機的內(nèi)存模型中一共有兩個“堆”继找,一個是原本的堆,一個是方法區(qū)逃沿。方法區(qū)本質(zhì)上是屬于堆的一個邏輯部分婴渡。堆中存放對象幻锁,方法區(qū)中存放類信息、常量边臼、靜態(tài)變量哄尔、即時編譯器編譯的代碼
  3. 堆是Java虛擬機中最大的一塊內(nèi)存區(qū)域柠并,也是垃圾收集器主要的工作區(qū)域究飞。
  4. 程序計數(shù)器、Java虛擬機棧堂鲤、本地方法棧是線程私有的亿傅,即每個線程都擁有各自的程序計數(shù)器、Java虛擬機棧瘟栖、本地方法區(qū)葵擎。并且他們的生命周期和所屬的線程一樣
    而堆半哟、方法區(qū)是線程共享的酬滤,在Java虛擬機中只有一個堆、一個方法棧寓涨。并在JVM啟動的時候就創(chuàng)建盯串,JVM停止才銷毀
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市戒良,隨后出現(xiàn)的幾起案子体捏,更是在濱河造成了極大的恐慌,老刑警劉巖糯崎,帶你破解...
    沈念sama閱讀 206,126評論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件几缭,死亡現(xiàn)場離奇詭異,居然都是意外死亡沃呢,警方通過查閱死者的電腦和手機年栓,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,254評論 2 382
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來薄霜,“玉大人某抓,你說我怎么就攤上這事《韫希” “怎么了否副?”我有些...
    開封第一講書人閱讀 152,445評論 0 341
  • 文/不壞的土叔 我叫張陵,是天一觀的道長鸵熟。 經(jīng)常有香客問我副编,道長负甸,這世上最難降的妖魔是什么流强? 我笑而不...
    開封第一講書人閱讀 55,185評論 1 278
  • 正文 為了忘掉前任痹届,我火速辦了婚禮,結(jié)果婚禮上打月,老公的妹妹穿的比我還像新娘队腐。我一直安慰自己,他們只是感情好奏篙,可當(dāng)我...
    茶點故事閱讀 64,178評論 5 371
  • 文/花漫 我一把揭開白布柴淘。 她就那樣靜靜地躺著,像睡著了一般秘通。 火紅的嫁衣襯著肌膚如雪为严。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 48,970評論 1 284
  • 那天肺稀,我揣著相機與錄音第股,去河邊找鬼。 笑死话原,一個胖子當(dāng)著我的面吹牛夕吻,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播繁仁,決...
    沈念sama閱讀 38,276評論 3 399
  • 文/蒼蘭香墨 我猛地睜開眼涉馅,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了黄虱?” 一聲冷哼從身側(cè)響起稚矿,我...
    開封第一講書人閱讀 36,927評論 0 259
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎捻浦,沒想到半個月后盐捷,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 43,400評論 1 300
  • 正文 獨居荒郊野嶺守林人離奇死亡默勾,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 35,883評論 2 323
  • 正文 我和宋清朗相戀三年碉渡,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片母剥。...
    茶點故事閱讀 37,997評論 1 333
  • 序言:一個原本活蹦亂跳的男人離奇死亡滞诺,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出环疼,到底是詐尸還是另有隱情习霹,我是刑警寧澤,帶...
    沈念sama閱讀 33,646評論 4 322
  • 正文 年R本政府宣布炫隶,位于F島的核電站淋叶,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏伪阶。R本人自食惡果不足惜煞檩,卻給世界環(huán)境...
    茶點故事閱讀 39,213評論 3 307
  • 文/蒙蒙 一处嫌、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧斟湃,春花似錦熏迹、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,204評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至墓猎,卻和暖如春捆昏,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背毙沾。 一陣腳步聲響...
    開封第一講書人閱讀 31,423評論 1 260
  • 我被黑心中介騙來泰國打工屡立, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人搀军。 一個月前我還...
    沈念sama閱讀 45,423評論 2 352
  • 正文 我出身青樓膨俐,卻偏偏與公主長得像,于是被迫代替她去往敵國和親罩句。 傳聞我的和親對象是個殘疾皇子焚刺,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 42,722評論 2 345

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