8張圖 帶你理解Java內(nèi)存區(qū)域

很多人會誤以為Java內(nèi)存區(qū)域和內(nèi)存模型是同一個東西访递,其實(shí)并不是鞋既。

Java內(nèi)存區(qū)域是指 JVM運(yùn)行時將數(shù)據(jù)分區(qū)域存儲 ,簡單的說就是不同的數(shù)據(jù)放在不同的地方棕兼。通常又叫 運(yùn)行時數(shù)據(jù)區(qū)域抵乓。

Java內(nèi)存模型(JMM)定義了程序中各個變量的訪問規(guī)則灾炭,即在虛擬機(jī)中將變量存儲到內(nèi)存和從內(nèi)存中取出變量這樣的底層細(xì)節(jié)。

1田弥、Java內(nèi)存區(qū)域

1.8 之前:
Java內(nèi)存區(qū)域 1.8之前
JDK1.8(含)之后:
Java內(nèi)存區(qū)域 1.8

區(qū)別就是 1.8有一個元數(shù)據(jù)區(qū)替代方法區(qū)了偷厦。

JDK 1.7 其實(shí)是并沒完全移除方法區(qū)只泼,但是不會像1.6以前報 “java.lang.OutOfMemoryError: PermGen space”卵洗,而是報 java.lang.OutOfMemoryError: Java heap space

1.7部分內(nèi)容(比如 常量池过蹂、靜態(tài)變量有方法區(qū)轉(zhuǎn)移到了堆)

演變

那么榴啸,Java 8 中 PermGen 為什么被移出 HotSpot JVM 了?我總結(jié)了兩個主要原因(詳見:JEP 122: Remove the Permanent Generation):

  1. 由于 PermGen 內(nèi)存經(jīng)常會溢出勋功,引發(fā)惱人的 java.lang.OutOfMemoryError: PermGen库说,因此 JVM 的開發(fā)者希望這一塊內(nèi)存可以更靈活地被管理潜的,不要再經(jīng)常出現(xiàn)這樣的 OOM
  2. 移除 PermGen 可以促進(jìn) HotSpot JVM 與 JRockit VM 的融合,因?yàn)?JRockit 沒有永久代信不。

根據(jù)上面的各種原因抽活,PermGen 最終被移除,方法區(qū)移至 Metaspace丁逝,字符串常量移至 Java Heap梭姓。

引用自https://www.sczyh30.com/posts/Java/jvm-metaspace/

下面逐一介紹一下jvm管轄的這幾種內(nèi)存區(qū)域誉尖。

2、程序計數(shù)器

程序計數(shù)器(Program Counter Register)是一塊較小的內(nèi)存空間萝衩,由于JVM可以并發(fā)執(zhí)行線程,因此會存在線程之間的切換千劈,而這個時候就程序計數(shù)器會記錄下當(dāng)前程序執(zhí)行到的位置墙牌,以便在其他線程執(zhí)行完畢后,恢復(fù)現(xiàn)場繼續(xù)執(zhí)行捉捅。

JVM會為每個線程分配一個程序計數(shù)器棒口,與線程的生命周期相同辜膝。

如果線程正在執(zhí)行的是應(yīng)該Java方法厂抖,這個計數(shù)器記錄的是正在執(zhí)行虛擬機(jī)字節(jié)碼指令的地址。

如果正在執(zhí)行的是Native方法七蜘,計數(shù)器的值則為空(undefined)

程序計數(shù)器是唯一一個在 Java 虛擬機(jī)規(guī)范中沒有規(guī)定任何 OutOfMemoryError 情況的區(qū)域。

3扮念、Java虛擬機(jī)棧

虛擬機(jī)棧 描述的是 Java 方法執(zhí)行的內(nèi)存模型:

每個方法在執(zhí)行的同時都會創(chuàng)建一個棧幀(Stack Frame扔亥,是方法運(yùn)行時的基礎(chǔ)數(shù)據(jù)結(jié)構(gòu))用于存儲局部變量表谈为、操作數(shù)棧伞鲫、動態(tài)鏈接、方法出口等信息柒瓣。每一個方法從調(diào)用直至執(zhí)行完成的過程芙贫,就對應(yīng)著一個棧幀在虛擬機(jī)棧中入棧到出棧的過程傍药。

虛擬機(jī)棧是每個線程獨(dú)有的拐辽,隨著線程的創(chuàng)建而存在,線程結(jié)束而死亡菠劝。

在虛擬機(jī)棧內(nèi)存不夠的時候會OutOfMemoryError赶诊,在線程運(yùn)行中需要更大的虛擬機(jī)棧時會出現(xiàn)StackOverFlowError介袜。

虛擬機(jī)棧包含很多棧幀遇伞,每個方法執(zhí)行的同時會創(chuàng)建一個棧幀,棧幀又存儲了方法的局部變量表巍耗、操作數(shù)棧炬太、動態(tài)連接和方法返回地址等信息。

在活動線程中炒考,只有位于棧頂?shù)臈攀怯行У恼啵Q為當(dāng)前棧幀知给,與這個棧幀相關(guān)聯(lián)的方法稱為當(dāng)前方法涩赢。

1)局部變量表

局部變量表是存放方法參數(shù)局部變量的區(qū)域。

全局變量是放在堆的怯邪,有兩次賦值的階段擎颖,一次在類加載的準(zhǔn)備階段观游,賦予系統(tǒng)初始值懂缕;另外一次在類加載的初始化階段王凑,賦予代碼定義的初始值索烹。

而局部變量沒有賦初始值是不能使用的百姓。

2)操作數(shù)棧

一個先入后出的棧。

當(dāng)一個方法剛剛開始執(zhí)行的時候旬迹,這個方法的操作數(shù)棧是空的奔垦,在方法的執(zhí)行過程中,會有各種字節(jié)碼指令往操作數(shù)棧中寫入和提取內(nèi)容惶岭,也就是出棧/入棧操作按灶。

3) 動態(tài)連接

每個棧幀都包含一個指向運(yùn)行時常量池中該棧幀所屬方法的引用阔逼。持有這個引用是為了支持方法調(diào)用過程中的動態(tài)連接(Dynamic Linking)嗜浮。

常量池可以便于指令的識別

    public void methodA(){
        
    }
    public void methodB(){
        methodA();//methodB()調(diào)用methodA(),先找到調(diào)用methodA()的版本符號危融,再變?yōu)橹苯右?    }

方法調(diào)用并不等同于方法執(zhí)行,方法調(diào)用階段唯一的任務(wù)就是確定被調(diào)用方法的版本(即調(diào)用哪一個方法)辞居,這也是Java強(qiáng)大的擴(kuò)展能力瓦灶,在運(yùn)行期間才能確定目標(biāo)方法的直接引用贼陶。

所有方法調(diào)用中的目標(biāo)方法在Class文件里面都是一個常量池中的符號引用巧娱,在類加載的解析階段禁添,會將其中的一部分符號引用轉(zhuǎn)化為直接引用。

4)方法返回地址(方法出口)

返回分為 正常返回 和 異常退出芹啥。

無論何種退出情況叁征,都將返回至方法當(dāng)前被調(diào)用的位置,這也程序才能繼續(xù)執(zhí)行疏虫。

一般來說卧秘,方法正常退出時翅敌,調(diào)用者的PC計數(shù)器的值可以作為返回地址惕蹄,棧幀中會保存這個計數(shù)器值。

方法退出的過程相當(dāng)于彈出當(dāng)前棧幀遭顶。

4棒旗、本地方法棧

Java虛擬機(jī)棧是調(diào)用Java方法铣揉;本地方法棧是調(diào)用本地native方法餐曹,可以認(rèn)為是通過 JNI (Java Native Interface) 直接調(diào)用本地 C/C++ 庫台猴,不受JVM控制卿吐。

Native方法
Java虛擬機(jī)棧與本地方法棧的調(diào)用過程

本地方法棧也會拋出 StackOverflowErrorOutOfMemoryError 異常

5嗡官、Java堆

Java 堆是被所有線程共享的一塊內(nèi)存區(qū)域,在虛擬機(jī)啟動時創(chuàng)建毯焕。此內(nèi)存區(qū)域的唯一目的就是存放對象實(shí)例衍腥,幾乎所有的對象實(shí)例都在這里分配內(nèi)存磺樱。

堆是垃圾收集器管理的主要區(qū)域,又稱為“GC堆”婆咸,可以說是Java虛擬機(jī)管理的內(nèi)存中最大的一塊竹捉。

現(xiàn)在的虛擬機(jī)(包括HotSpot VM)都是采用分代回收算法。在分代回收的思想中尚骄, 把堆分為:新生代+老年代+永久代(1.8沒有了)块差; 新生代 又分為 Eden + From Survivor + To Survivor區(qū)倔丈。

6憨闰、方法區(qū)

方法區(qū)(Method Area)與 Java 堆一樣,是所有線程共享的內(nèi)存區(qū)域需五。

方法區(qū)用于存儲已經(jīng)被虛擬機(jī)加載的類信息(即加載類時需要加載的信息鹉动,包括版本、field宏邮、方法泽示、接口等信息)、final常量蜜氨、靜態(tài)變量械筛、編譯器即時編譯的代碼等。

方法區(qū)邏輯上屬于堆的一部分记劝,但是為了與堆進(jìn)行區(qū)分变姨,通常又叫“非堆”。

方法區(qū)比較重要的一部分是運(yùn)行時常量池(Runtime Constant Pool)厌丑,為什么叫運(yùn)行時常量池呢定欧?是因?yàn)檫\(yùn)行期間可能會把新的常量放入池中,比如說常見的String的intern()方法怒竿。

String a = "I am HaC";
Integer b = 100;

在編譯階段就把所有的字符串文字放到一個常量池中砍鸠,復(fù)用同一個(比如說上述的“I am HaC”),節(jié)省空間耕驰。

關(guān)于方法區(qū)和元空間的關(guān)系:

方法區(qū)是JVM規(guī)范概念爷辱,而永久代則是Hotspot虛擬機(jī)特有的概念,簡單點(diǎn)理解:方法區(qū)和堆內(nèi)存的永久代其實(shí)一個東西朦肘,但是方法區(qū)是包含了永久代饭弓。

只有 HotSpot 才有 “PermGen space”,而對于其他類型的虛擬機(jī)媒抠,如 JRockit(Oracle)弟断、J9(IBM) 并沒有“PermGen space”

7、元空間

1.8就把方法區(qū)改用元空間了趴生。類的元信息被存儲在元空間中阀趴。元空間沒有使用堆內(nèi)存昏翰,而是與堆不相連的本地內(nèi)存區(qū)域。所以刘急,理論上系統(tǒng)可以使用的內(nèi)存有多大棚菊,元空間就有多大,所以不會出現(xiàn)永久代存在時的內(nèi)存溢出問題叔汁。

可以通過 -XX:MetaspaceSize-XX:MaxMetaspaceSize 來指定元空間的大小统求。

8、總結(jié):

Java內(nèi)存區(qū)域

參考:

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末攻柠,一起剝皮案震驚了整個濱河市球订,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌瑰钮,老刑警劉巖冒滩,帶你破解...
    沈念sama閱讀 217,734評論 6 505
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異浪谴,居然都是意外死亡开睡,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,931評論 3 394
  • 文/潘曉璐 我一進(jìn)店門苟耻,熙熙樓的掌柜王于貴愁眉苦臉地迎上來篇恒,“玉大人,你說我怎么就攤上這事凶杖⌒布瑁” “怎么了?”我有些...
    開封第一講書人閱讀 164,133評論 0 354
  • 文/不壞的土叔 我叫張陵智蝠,是天一觀的道長腾么。 經(jīng)常有香客問我,道長杈湾,這世上最難降的妖魔是什么解虱? 我笑而不...
    開封第一講書人閱讀 58,532評論 1 293
  • 正文 為了忘掉前任,我火速辦了婚禮漆撞,結(jié)果婚禮上殴泰,老公的妹妹穿的比我還像新娘。我一直安慰自己浮驳,他們只是感情好悍汛,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,585評論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著至会,像睡著了一般员凝。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上奋献,一...
    開封第一講書人閱讀 51,462評論 1 302
  • 那天健霹,我揣著相機(jī)與錄音,去河邊找鬼瓶蚂。 笑死糖埋,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的窃这。 我是一名探鬼主播瞳别,決...
    沈念sama閱讀 40,262評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼杭攻!你這毒婦竟也來了祟敛?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,153評論 0 276
  • 序言:老撾萬榮一對情侶失蹤兆解,失蹤者是張志新(化名)和其女友劉穎馆铁,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體锅睛,經(jīng)...
    沈念sama閱讀 45,587評論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡埠巨,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,792評論 3 336
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了现拒。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片辣垒。...
    茶點(diǎn)故事閱讀 39,919評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖印蔬,靈堂內(nèi)的尸體忽然破棺而出勋桶,到底是詐尸還是另有隱情,我是刑警寧澤侥猬,帶...
    沈念sama閱讀 35,635評論 5 345
  • 正文 年R本政府宣布例驹,位于F島的核電站,受9級特大地震影響陵究,放射性物質(zhì)發(fā)生泄漏眠饮。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,237評論 3 329
  • 文/蒙蒙 一铜邮、第九天 我趴在偏房一處隱蔽的房頂上張望仪召。 院中可真熱鬧,春花似錦松蒜、人聲如沸扔茅。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,855評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽召娜。三九已至,卻和暖如春惊楼,著一層夾襖步出監(jiān)牢的瞬間玖瘸,已是汗流浹背秸讹。 一陣腳步聲響...
    開封第一講書人閱讀 32,983評論 1 269
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留雅倒,地道東北人璃诀。 一個月前我還...
    沈念sama閱讀 48,048評論 3 370
  • 正文 我出身青樓,卻偏偏與公主長得像蔑匣,于是被迫代替她去往敵國和親劣欢。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,864評論 2 354

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