Java學(xué)習(xí)筆記:JVM內(nèi)存區(qū)域劃分?

原文鏈接:https://www.cnblogs.com/dolphin0520/p/3613043.html
JVM的內(nèi)存區(qū)域劃分:

學(xué)過(guò)C語(yǔ)言的朋友都知道C編譯器在劃分內(nèi)存區(qū)域的時(shí)候經(jīng)常將管理的區(qū)域劃分為數(shù)據(jù)段和代碼段履磨,數(shù)據(jù)段包括堆联四、棧以及靜態(tài)數(shù)據(jù)區(qū)凯肋。那么在Java語(yǔ)言當(dāng)中境蜕,內(nèi)存又是如何劃分的呢蝙场?

由于Java程序是交由JVM執(zhí)行的,所以我們?cè)谡凧ava內(nèi)存區(qū)域劃分的時(shí)候事實(shí)上是指JVM內(nèi)存區(qū)域劃分粱年。在討論JVM內(nèi)存區(qū)域劃分之前售滤,先來(lái)看一下Java程序具體執(zhí)行的過(guò)程:

image

如上圖所示,首先Java源代碼文件(.java后綴)會(huì)被Java編譯器編譯為字節(jié)碼文件(.class后綴)台诗,然后由JVM中的類(lèi)加載器加載各個(gè)類(lèi)的字節(jié)碼文件完箩,加載完畢之后,交由JVM執(zhí)行引擎執(zhí)行拉队。在整個(gè)程序執(zhí)行過(guò)程中弊知,JVM會(huì)用一段空間來(lái)存儲(chǔ)程序執(zhí)行期間需要用到的數(shù)據(jù)和相關(guān)信息,這段空間一般被稱作為Runtime Data Area(運(yùn)行時(shí)數(shù)據(jù)區(qū))氏仗,也就是我們常說(shuō)的JVM內(nèi)存吉捶。因此,在Java中我們常常說(shuō)到的內(nèi)存管理就是針對(duì)這段空間進(jìn)行管理(如何分配和回收內(nèi)存空間)皆尔。

在知道了JVM內(nèi)存是什么東西之后,下面我們就來(lái)討論一下這段空間具體是如何劃分區(qū)域的币励,是不是也像C語(yǔ)言中一樣也存在棧和堆呢慷蠕?

一.運(yùn)行時(shí)數(shù)據(jù)區(qū)包括哪幾部分?

根據(jù)《Java虛擬機(jī)規(guī)范》的規(guī)定食呻,運(yùn)行時(shí)數(shù)據(jù)區(qū)通常包括這幾個(gè)部分:程序計(jì)數(shù)器(Program Counter Register)流炕、Java棧(VM Stack)澎现、本地方法棧(Native Method Stack)、方法區(qū)(Method Area)每辟、堆(Heap)剑辫。

image

如上圖所示,JVM中的運(yùn)行時(shí)數(shù)據(jù)區(qū)應(yīng)該包括這些部分渠欺。在JVM規(guī)范中雖然規(guī)定了程序在執(zhí)行期間運(yùn)行時(shí)數(shù)據(jù)區(qū)應(yīng)該包括這幾部分妹蔽,但是至于具體如何實(shí)現(xiàn)并沒(méi)有做出規(guī)定,不同的虛擬機(jī)廠商可以有不同的實(shí)現(xiàn)方式挠将。

二.運(yùn)行時(shí)數(shù)據(jù)區(qū)的每部分到底存儲(chǔ)了哪些數(shù)據(jù)胳岂?

下面我們來(lái)了解一下運(yùn)行時(shí)數(shù)據(jù)區(qū)的每部分具體用來(lái)存儲(chǔ)程序執(zhí)行過(guò)程中的哪些數(shù)據(jù)。

1.程序計(jì)數(shù)器

程序計(jì)數(shù)器(Program Counter Register)舔稀,也有稱作為PC寄存器乳丰。想必學(xué)過(guò)匯編語(yǔ)言的朋友對(duì)程序計(jì)數(shù)器這個(gè)概念并不陌生,在匯編語(yǔ)言中内贮,程序計(jì)數(shù)器是指CPU中的寄存器产园,它保存的是程序當(dāng)前執(zhí)行的指令的地址(也可以說(shuō)保存下一條指令的所在存儲(chǔ)單元的地址),當(dāng)CPU需要執(zhí)行指令時(shí)夜郁,需要從程序計(jì)數(shù)器中得到當(dāng)前需要執(zhí)行的指令所在存儲(chǔ)單元的地址什燕,然后根據(jù)得到的地址獲取到指令,在得到指令之后拂酣,程序計(jì)數(shù)器便自動(dòng)加1或者根據(jù)轉(zhuǎn)移指針得到下一條指令的地址秋冰,如此循環(huán),直至執(zhí)行完所有的指令婶熬。

雖然JVM中的程序計(jì)數(shù)器并不像匯編語(yǔ)言中的程序計(jì)數(shù)器一樣是物理概念上的CPU寄存器剑勾,但是JVM中的程序計(jì)數(shù)器的功能跟匯編語(yǔ)言中的程序計(jì)數(shù)器的功能在邏輯上是等同的,也就是說(shuō)是用來(lái)指示 執(zhí)行哪條指令的赵颅。

由于在JVM中虽另,多線程是通過(guò)線程輪流切換來(lái)獲得CPU執(zhí)行時(shí)間的,因此饺谬,在任一具體時(shí)刻捂刺,一個(gè)CPU的內(nèi)核只會(huì)執(zhí)行一條線程中的指令,因此募寨,為了能夠使得每個(gè)線程都在線程切換后能夠恢復(fù)在切換之前的程序執(zhí)行位置族展,每個(gè)線程都需要有自己獨(dú)立的程序計(jì)數(shù)器,并且不能互相被干擾拔鹰,否則就會(huì)影響到程序的正常執(zhí)行次序仪缸。因此,可以這么說(shuō)列肢,程序計(jì)數(shù)器是每個(gè)線程所私有的恰画。

在JVM規(guī)范中規(guī)定宾茂,如果線程執(zhí)行的是非native方法,則程序計(jì)數(shù)器中保存的是當(dāng)前需要執(zhí)行的指令的地址拴还;如果線程執(zhí)行的是native方法跨晴,則程序計(jì)數(shù)器中的值是undefined。

由于程序計(jì)數(shù)器中存儲(chǔ)的數(shù)據(jù)所占空間的大小不會(huì)隨程序的執(zhí)行而發(fā)生改變片林,因此端盆,對(duì)于程序計(jì)數(shù)器是不會(huì)發(fā)生內(nèi)存溢出現(xiàn)象(OutOfMemory)的。

2.Java棧

Java棧也稱作虛擬機(jī)棧(Java Vitual Machine Stack)拇厢,也就是我們常常所說(shuō)的棧爱谁,跟C語(yǔ)言的數(shù)據(jù)段中的棧類(lèi)似。事實(shí)上孝偎,Java棧是Java方法執(zhí)行的內(nèi)存模型访敌。為什么這么說(shuō)呢?下面就來(lái)解釋一下其中的原因衣盾。

Java棧中存放的是一個(gè)個(gè)的棧幀寺旺,每個(gè)棧幀對(duì)應(yīng)一個(gè)被調(diào)用的方法,在棧幀中包括局部變量表(Local Variables)势决、操作數(shù)棧(Operand Stack)阻塑、指向當(dāng)前方法所屬的類(lèi)的運(yùn)行時(shí)常量池(運(yùn)行時(shí)常量池的概念在方法區(qū)部分會(huì)談到)的引用(Reference to runtime constant pool)、方法返回地址(Return Address)和一些額外的附加信息果复。當(dāng)線程執(zhí)行一個(gè)方法時(shí)陈莽,就會(huì)隨之創(chuàng)建一個(gè)對(duì)應(yīng)的棧幀,并將建立的棧幀壓棧虽抄。當(dāng)方法執(zhí)行完畢之后走搁,便會(huì)將棧幀出棧。因此可知迈窟,線程當(dāng)前執(zhí)行的方法所對(duì)應(yīng)的棧幀必定位于Java棧的頂部喜庞。講到這里缅茉,大家就應(yīng)該會(huì)明白為什么 在 使用 遞歸方法的時(shí)候容易導(dǎo)致棧內(nèi)存溢出的現(xiàn)象了以及為什么棧區(qū)的空間不用程序員去管理了(當(dāng)然在Java中锄贼,程序員基本不用關(guān)系到內(nèi)存分配和釋放的事情榴都,因?yàn)镴ava有自己的垃圾回收機(jī)制),這部分空間的分配和釋放都是由系統(tǒng)自動(dòng)實(shí)施的湖员。對(duì)于所有的程序設(shè)計(jì)語(yǔ)言來(lái)說(shuō)贫悄,棧這部分空間對(duì)程序員來(lái)說(shuō)是不透明的。下圖表示了一個(gè)Java棧的模型:

image

局部變量表娘摔,顧名思義清女,想必不用解釋大家應(yīng)該明白它的作用了吧。就是用來(lái)存儲(chǔ)方法中的局部變量(包括在方法中聲明的非靜態(tài)變量以及函數(shù)形參)晰筛。對(duì)于基本數(shù)據(jù)類(lèi)型的變量嫡丙,則直接存儲(chǔ)它的值,對(duì)于引用類(lèi)型的變量读第,則存的是指向?qū)ο蟮囊檬锊>植孔兞勘淼拇笮≡诰幾g器就可以確定其大小了,因此在程序執(zhí)行期間局部變量表的大小是不會(huì)改變的怜瞒。

操作數(shù)棧父泳,想必學(xué)過(guò)數(shù)據(jù)結(jié)構(gòu)中的棧的朋友想必對(duì)表達(dá)式求值問(wèn)題不會(huì)陌生,棧最典型的一個(gè)應(yīng)用就是用來(lái)對(duì)表達(dá)式求值吴汪。想想一個(gè)線程執(zhí)行方法的過(guò)程中惠窄,實(shí)際上就是不斷執(zhí)行語(yǔ)句的過(guò)程,而歸根到底就是進(jìn)行計(jì)算的過(guò)程漾橙。因此可以這么說(shuō)杆融,程序中的所有計(jì)算過(guò)程都是在借助于操作數(shù)棧來(lái)完成的。

指向運(yùn)行時(shí)常量池的引用霜运,因?yàn)樵诜椒▓?zhí)行的過(guò)程中有可能需要用到類(lèi)中的常量脾歇,所以必須要有一個(gè)引用指向運(yùn)行時(shí)常量。

方法返回地址淘捡,當(dāng)一個(gè)方法執(zhí)行完畢之后藕各,要返回之前調(diào)用它的地方,因此在棧幀中必須保存一個(gè)方法返回地址焦除。

由于每個(gè)線程正在執(zhí)行的方法可能不同激况,因此每個(gè)線程都會(huì)有一個(gè)自己的Java棧,互不干擾膘魄。

3.本地方法棧

本地方法棧與Java棧的作用和原理非常相似乌逐。區(qū)別只不過(guò)是Java棧是為執(zhí)行Java方法服務(wù)的,而本地方法棧則是為執(zhí)行本地方法(Native Method)服務(wù)的瓣距。在JVM規(guī)范中黔帕,并沒(méi)有對(duì)本地方發(fā)展的具體實(shí)現(xiàn)方法以及數(shù)據(jù)結(jié)構(gòu)作強(qiáng)制規(guī)定,虛擬機(jī)可以自由實(shí)現(xiàn)它蹈丸。在HotSopt虛擬機(jī)中直接就把本地方法棧和Java棧合二為一成黄。

4.堆

在C語(yǔ)言中,堆這部分空間是唯一一個(gè)程序員可以管理的內(nèi)存區(qū)域逻杖。程序員可以通過(guò)malloc函數(shù)和free函數(shù)在堆上申請(qǐng)和釋放空間奋岁。那么在Java中是怎么樣的呢?

Java中的堆是用來(lái)存儲(chǔ)對(duì)象本身的以及數(shù)組(當(dāng)然荸百,數(shù)組引用是存放在Java棧中的)闻伶。只不過(guò)和C語(yǔ)言中的不同,在Java中够话,程序員基本不用去關(guān)心空間釋放的問(wèn)題蓝翰,Java的垃圾回收機(jī)制會(huì)自動(dòng)進(jìn)行處理光绕。因此這部分空間也是Java垃圾收集器管理的主要區(qū)域。另外畜份,堆是被所有線程共享的诞帐,在JVM中只有一個(gè)堆。

5.方法區(qū)

方法區(qū)在JVM中也是一個(gè)非常重要的區(qū)域爆雹,它與堆一樣停蕉,是被線程共享的區(qū)域。在方法區(qū)中钙态,存儲(chǔ)了每個(gè)類(lèi)的信息(包括類(lèi)的名稱慧起、方法信息、字段信息)册倒、靜態(tài)變量蚓挤、常量以及編譯器編譯后的代碼等。

在Class文件中除了類(lèi)的字段剩失、方法屈尼、接口等描述信息外,還有一項(xiàng)信息是常量池拴孤,用來(lái)存儲(chǔ)編譯期間生成的字面量和符號(hào)引用脾歧。

在方法區(qū)中有一個(gè)非常重要的部分就是運(yùn)行時(shí)常量池,它是每一個(gè)類(lèi)或接口的常量池的運(yùn)行時(shí)表示形式演熟,在類(lèi)和接口被加載到JVM后鞭执,對(duì)應(yīng)的運(yùn)行時(shí)常量池就被創(chuàng)建出來(lái)。當(dāng)然并非Class文件常量池中的內(nèi)容才能進(jìn)入運(yùn)行時(shí)常量池芒粹,在運(yùn)行期間也可將新的常量放入運(yùn)行時(shí)常量池中兄纺,比如String的intern方法。

在JVM規(guī)范中化漆,沒(méi)有強(qiáng)制要求方法區(qū)必須實(shí)現(xiàn)垃圾回收估脆。很多人習(xí)慣將方法區(qū)稱為“永久代”,是因?yàn)镠otSpot虛擬機(jī)以永久代來(lái)實(shí)現(xiàn)方法區(qū)座云,從而JVM的垃圾收集器可以像管理堆區(qū)一樣管理這部分區(qū)域疙赠,從而不需要專門(mén)為這部分設(shè)計(jì)垃圾回收機(jī)制。不過(guò)自從JDK7之后朦拖,Hotspot虛擬機(jī)便將運(yùn)行時(shí)常量池從永久代移除了圃阳。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市璧帝,隨后出現(xiàn)的幾起案子捍岳,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 211,348評(píng)論 6 491
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件锣夹,死亡現(xiàn)場(chǎng)離奇詭異页徐,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī)晕城,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,122評(píng)論 2 385
  • 文/潘曉璐 我一進(jìn)店門(mén)泞坦,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人砖顷,你說(shuō)我怎么就攤上這事≡呶啵” “怎么了滤蝠?”我有些...
    開(kāi)封第一講書(shū)人閱讀 156,936評(píng)論 0 347
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)授嘀。 經(jīng)常有香客問(wèn)我物咳,道長(zhǎng),這世上最難降的妖魔是什么蹄皱? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 56,427評(píng)論 1 283
  • 正文 為了忘掉前任览闰,我火速辦了婚禮,結(jié)果婚禮上巷折,老公的妹妹穿的比我還像新娘压鉴。我一直安慰自己,他們只是感情好锻拘,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,467評(píng)論 6 385
  • 文/花漫 我一把揭開(kāi)白布油吭。 她就那樣靜靜地躺著,像睡著了一般署拟。 火紅的嫁衣襯著肌膚如雪婉宰。 梳的紋絲不亂的頭發(fā)上,一...
    開(kāi)封第一講書(shū)人閱讀 49,785評(píng)論 1 290
  • 那天推穷,我揣著相機(jī)與錄音心包,去河邊找鬼。 笑死馒铃,一個(gè)胖子當(dāng)著我的面吹牛蟹腾,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播骗露,決...
    沈念sama閱讀 38,931評(píng)論 3 406
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼岭佳,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了萧锉?” 一聲冷哼從身側(cè)響起珊随,我...
    開(kāi)封第一講書(shū)人閱讀 37,696評(píng)論 0 266
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒(méi)想到半個(gè)月后叶洞,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體鲫凶,經(jīng)...
    沈念sama閱讀 44,141評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,483評(píng)論 2 327
  • 正文 我和宋清朗相戀三年衩辟,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了螟炫。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 38,625評(píng)論 1 340
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡艺晴,死狀恐怖昼钻,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情封寞,我是刑警寧澤然评,帶...
    沈念sama閱讀 34,291評(píng)論 4 329
  • 正文 年R本政府宣布,位于F島的核電站狈究,受9級(jí)特大地震影響碗淌,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜抖锥,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,892評(píng)論 3 312
  • 文/蒙蒙 一亿眠、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧磅废,春花似錦纳像、人聲如沸。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 30,741評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至谜喊,卻和暖如春潭兽,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背斗遏。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 31,977評(píng)論 1 265
  • 我被黑心中介騙來(lái)泰國(guó)打工山卦, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人诵次。 一個(gè)月前我還...
    沈念sama閱讀 46,324評(píng)論 2 360
  • 正文 我出身青樓账蓉,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親逾一。 傳聞我的和親對(duì)象是個(gè)殘疾皇子铸本,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,492評(píng)論 2 348