JVM

一. 先來(lái)看看JVM運(yùn)行時(shí)候的內(nèi)存區(qū)域

image.png

大多數(shù) JVM 將內(nèi)存區(qū)域劃分為 Method Area(Non-Heap)(方法區(qū)),Heap(堆),Program Counter Register(程序計(jì)數(shù)器), VM Stack(虛擬機(jī)棧建钥,也有翻譯成JAVA 方法棧的),Native Method Stack (本地方法棧)只盹,其中Method Area和Heap是線程共享的蝴韭,VM Stack峭状,Native Method Stack 和Program Counter Register是非線程共享的。為什么分為線程共享和非線程共享的呢?請(qǐng)繼續(xù)往下看。

首先我們熟悉一下一個(gè)一般性的 Java 程序的工作過(guò)程。一個(gè) Java 源程序文件,會(huì)被編譯為字節(jié)碼文件(以 class 為擴(kuò)展名)捺檬,每個(gè)java程序都需要運(yùn)行在自己的JVM上,然后告知 JVM 程序的運(yùn)行入口贸铜,再被 JVM 通過(guò)字節(jié)碼解釋器加載運(yùn)行堡纬。那么程序開(kāi)始運(yùn)行后,都是如何涉及到各內(nèi)存區(qū)域的呢蒿秦?

概括地說(shuō)來(lái)烤镐,JVM初始運(yùn)行的時(shí)候都會(huì)分配好Method Area(方法區(qū))和Heap(堆),而JVM 每遇到一個(gè)線程棍鳖,就為其分配一個(gè)Program Counter Register(程序計(jì)數(shù)器), VM Stack(虛擬機(jī)棧)和Native Method Stack (本地方法棧)炮叶,當(dāng)線程終止時(shí),三者(虛擬機(jī)棧渡处,本地方法棧和程序計(jì)數(shù)器)所占用的內(nèi)存空間也會(huì)被釋放掉镜悉。這也是為什么我把內(nèi)存區(qū)域分為線程共享和非線程共享的原因,非線程共享的那三個(gè)區(qū)域的生命周期與所屬線程相同医瘫,而線程共享的區(qū)域與JAVA程序運(yùn)行的生命周期相同侣肄,所以這也是系統(tǒng)垃圾回收的場(chǎng)所只發(fā)生在線程共享的區(qū)域(實(shí)際上對(duì)大部分虛擬機(jī)來(lái)說(shuō)知發(fā)生在Heap上)的原因。
1.  程序計(jì)數(shù)器

程序計(jì)數(shù)器是一塊較小的內(nèi)存區(qū)域醇份,作用可以看做是當(dāng)前線程執(zhí)行的字節(jié)碼的位置指示器稼锅。分支吼具、循環(huán)、跳轉(zhuǎn)矩距、異常處理和線程恢復(fù)等基礎(chǔ)功能都需要依賴這個(gè)計(jì)算器來(lái)完成拗盒,不多說(shuō)。

2.VM Strack

先來(lái)了解下JAVA指令的構(gòu)成:

JAVA指令由 操作碼 (方法本身)和 操作數(shù) (方法內(nèi)部變量) 組成锥债。

1)方法本身是指令的操作碼部分陡蝇,保存在Stack中;
2)方法內(nèi)部變量(局部變量)作為指令的操作數(shù)部分哮肚,跟在指令的操作碼之后毅整,保存在Stack中(實(shí)際上是簡(jiǎn)單類型(int,byte,short 等)保存在Stack中,對(duì)象類型在Stack中保存地址绽左,在Heap 中保存值);
  虛擬機(jī)棧也叫棧內(nèi)存艇潭,是在線程創(chuàng)建時(shí)創(chuàng)建拼窥,它的生命期是跟隨線程的生命期,線程結(jié)束棧內(nèi)存也就釋放蹋凝,對(duì)于棧來(lái)說(shuō)不存在垃圾回收問(wèn)題鲁纠,只要線程一結(jié)束,該棧就 Over鳍寂,所以不存在垃圾回收改含。也有一些資料翻譯成JAVA方法棧,大概是因?yàn)樗枋龅氖莏ava方法執(zhí)行的內(nèi)存模型迄汛,每個(gè)方法執(zhí)行的同時(shí)創(chuàng)建幀棧(Strack Frame)用于存儲(chǔ)局部變量表(包含了對(duì)應(yīng)的方法參數(shù)和局部變量)捍壤,操作棧(Operand Stack,記錄出棧鞍爱、入棧的操作)鹃觉,動(dòng)態(tài)鏈接、方法出口等信息睹逃,每個(gè)方法被調(diào)用直到執(zhí)行完畢的過(guò)程盗扇,對(duì)應(yīng)這幀棧在虛擬機(jī)棧的入棧和出棧的過(guò)程。

局部變量表存放了編譯期可知的各種基本數(shù)據(jù)類型(boolean沉填、byte疗隶、char、short翼闹、int斑鼻、float、long橄碾、double)卵沉、對(duì)象的引用(reference類型颠锉,不等同于對(duì)象本身,根據(jù)不同的虛擬機(jī)實(shí)現(xiàn)史汗,可能是一個(gè)指向?qū)ο笃鹗嫉刂返囊弥羔樓砺樱部赡苁且粋€(gè)代表對(duì)象的句柄或者其他與對(duì)象相關(guān)的位置)和 returnAdress類型(指向下一條字節(jié)碼指令的地址)。局部變量表所需的內(nèi)存空間在編譯期間完成分配停撞,在方法在運(yùn)行之前瓷蛙,該局部變量表所需要的內(nèi)存空間是固定的,運(yùn)行期間也不會(huì)改變戈毒。

棧幀是一個(gè)內(nèi)存區(qū)塊艰猬,是一個(gè)數(shù)據(jù)集,是一個(gè)有關(guān)方法(Method)和運(yùn)行期數(shù)據(jù)的數(shù)據(jù)集埋市,當(dāng)一個(gè)方法 A 被調(diào)用時(shí)就產(chǎn)生了一個(gè)棧幀 F1冠桃,并被壓入到棧中,A 方法又調(diào)用了 B 方法道宅,于是產(chǎn)生棧幀 F2 也被壓入棧食听,執(zhí)行完畢后,先彈出 F2棧幀污茵,再?gòu)棾?F1 棧幀樱报,遵循“先進(jìn)后出”原則。光說(shuō)比較枯燥泞当,我們看一個(gè)圖來(lái)理解一下 Java棧迹蛤,如下圖所示:

image.png

3.Heap

Heap(堆)是JVM的內(nèi)存數(shù)據(jù)區(qū)。Heap 的管理很復(fù)雜襟士,是被所有線程共享的內(nèi)存區(qū)域盗飒,在JVM啟動(dòng)時(shí)候創(chuàng)建,專門用來(lái)保存對(duì)象的實(shí)例陋桂。在Heap 中分配一定的內(nèi)存來(lái)保存對(duì)象實(shí)例箩兽,實(shí)際上也只是保存對(duì)象實(shí)例的屬性值,屬性的類型和對(duì)象本身的類型標(biāo)記等章喉,并不保存對(duì)象的方法(以幀棧的形式保存在Stack中),在Heap 中分配一定的內(nèi)存保存對(duì)象實(shí)例汗贫。而對(duì)象實(shí)例在Heap 中分配好以后,需要在Stack中保存一個(gè)4字節(jié)的Heap 內(nèi)存地址秸脱,用來(lái)定位該對(duì)象實(shí)例在Heap 中的位置落包,便于找到該對(duì)象實(shí)例,是垃圾回收的主要場(chǎng)所摊唇。java堆處于物理不連續(xù)的內(nèi)存空間中咐蝇,只要邏輯上連續(xù)即可。

4.Method Area

Object Class Data(加載類的類定義數(shù)據(jù)) 是存儲(chǔ)在方法區(qū)的巷查。除此之外有序,常量抹腿、靜態(tài)變量、JIT(即時(shí)編譯器)編譯后的代碼也都在方法區(qū)旭寿。正因?yàn)榉椒▍^(qū)所存儲(chǔ)的數(shù)據(jù)與堆有一種類比關(guān)系警绩,所以它還被稱為 Non-Heap。方法區(qū)也可以是內(nèi)存不連續(xù)的區(qū)域組成的盅称,并且可設(shè)置為固定大小肩祥,也可以設(shè)置為可擴(kuò)展的,這點(diǎn)與堆一樣缩膝。
  垃圾回收在這個(gè)區(qū)域會(huì)比較少出現(xiàn)混狠,這個(gè)區(qū)域內(nèi)存回收的目的主要針對(duì)常量池的回收和類的卸載。
5.運(yùn)行時(shí)常量池(Runtime Constant Pool)
  方法區(qū)內(nèi)部有一個(gè)非常重要的區(qū)域疾层,叫做運(yùn)行時(shí)常量池(Runtime Constant Pool将饺,簡(jiǎn)稱 RCP)。在字節(jié)碼文件(Class文件)中痛黎,除了有類的版本俯逾、字段、方法舅逸、接口等先關(guān)信息描述外,還有常量池(Constant Pool Table)信息皇筛,用于存儲(chǔ)編譯器產(chǎn)生的字面量和符號(hào)引用琉历。這部分內(nèi)容在類被加載后,都會(huì)存儲(chǔ)到方法區(qū)中的RCP水醋。值得注意的是旗笔,運(yùn)行時(shí)產(chǎn)生的新常量也可以被放入常量池中,比如 String 類中的 intern() 方法產(chǎn)生的常量拄踪。
  常量池就是這個(gè)類型用到的常量的一個(gè)有序集合蝇恶。包括直接常量(基本類型,String)和對(duì)其他類型惶桐、方法撮弧、字段的符號(hào)引用.例如:
◆類和接口的全限定名;
◆字段的名稱和描述符姚糊;
◆方法和名稱和描述符贿衍。
  池中的數(shù)據(jù)和數(shù)組一樣通過(guò)索引訪問(wèn)。由于常量池包含了一個(gè)類型所有的對(duì)其他類型救恨、方法贸辈、字段的符號(hào)引用,所以常量池在Java的動(dòng)態(tài)鏈接中起了核心作用
6.Native Method Stack
  與VM Strack相似肠槽,VM Strack為JVM提供執(zhí)行JAVA方法的服務(wù)擎淤,Native Method Stack則為JVM提供使用native 方法的服務(wù)奢啥。
7.直接內(nèi)存區(qū)
  直接內(nèi)存區(qū)并不是 JVM 管理的內(nèi)存區(qū)域的一部分,而是其之外的嘴拢。該區(qū)域也會(huì)在 Java 開(kāi)發(fā)中使用到桩盲,并且存在導(dǎo)致內(nèi)存溢出的隱患。如果你對(duì) NIO 有所了解炊汤,可能會(huì)知道 NIO 是可以使用 Native Methods 來(lái)使用直接內(nèi)存區(qū)的正驻。
小結(jié):
  在此,你對(duì)JVM的內(nèi)存區(qū)域有了一定的理解抢腐,JVM內(nèi)存區(qū)域可以分為線程共享和非線程共享兩部分姑曙,線程共享的有堆和方法區(qū),非線程共享的有虛擬機(jī)棧迈倍,本地方法棧和程序計(jì)數(shù)器伤靠。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市啼染,隨后出現(xiàn)的幾起案子宴合,更是在濱河造成了極大的恐慌,老刑警劉巖迹鹅,帶你破解...
    沈念sama閱讀 206,482評(píng)論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件卦洽,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡斜棚,警方通過(guò)查閱死者的電腦和手機(jī)阀蒂,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,377評(píng)論 2 382
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)弟蚀,“玉大人蚤霞,你說(shuō)我怎么就攤上這事∫宥ぃ” “怎么了昧绣?”我有些...
    開(kāi)封第一講書(shū)人閱讀 152,762評(píng)論 0 342
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)捶闸。 經(jīng)常有香客問(wèn)我夜畴,道長(zhǎng),這世上最難降的妖魔是什么删壮? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 55,273評(píng)論 1 279
  • 正文 為了忘掉前任斩启,我火速辦了婚禮,結(jié)果婚禮上醉锅,老公的妹妹穿的比我還像新娘兔簇。我一直安慰自己,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,289評(píng)論 5 373
  • 文/花漫 我一把揭開(kāi)白布垄琐。 她就那樣靜靜地躺著边酒,像睡著了一般。 火紅的嫁衣襯著肌膚如雪狸窘。 梳的紋絲不亂的頭發(fā)上墩朦,一...
    開(kāi)封第一講書(shū)人閱讀 49,046評(píng)論 1 285
  • 那天,我揣著相機(jī)與錄音翻擒,去河邊找鬼氓涣。 笑死,一個(gè)胖子當(dāng)著我的面吹牛陋气,可吹牛的內(nèi)容都是我干的劳吠。 我是一名探鬼主播,決...
    沈念sama閱讀 38,351評(píng)論 3 400
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼巩趁,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼痒玩!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起议慰,我...
    開(kāi)封第一講書(shū)人閱讀 36,988評(píng)論 0 259
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤蠢古,失蹤者是張志新(化名)和其女友劉穎,沒(méi)想到半個(gè)月后别凹,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體草讶,經(jīng)...
    沈念sama閱讀 43,476評(píng)論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 35,948評(píng)論 2 324
  • 正文 我和宋清朗相戀三年炉菲,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了堕战。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 38,064評(píng)論 1 333
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡颁督,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出浇雹,到底是詐尸還是另有隱情沉御,我是刑警寧澤,帶...
    沈念sama閱讀 33,712評(píng)論 4 323
  • 正文 年R本政府宣布昭灵,位于F島的核電站吠裆,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏烂完。R本人自食惡果不足惜试疙,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,261評(píng)論 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望抠蚣。 院中可真熱鬧祝旷,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 30,264評(píng)論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至吻谋,卻和暖如春忠蝗,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背漓拾。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 31,486評(píng)論 1 262
  • 我被黑心中介騙來(lái)泰國(guó)打工阁最, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人骇两。 一個(gè)月前我還...
    沈念sama閱讀 45,511評(píng)論 2 354
  • 正文 我出身青樓速种,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親脯颜。 傳聞我的和親對(duì)象是個(gè)殘疾皇子哟旗,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,802評(píng)論 2 345

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