JVM區(qū)域劃分詳解

轉(zhuǎn):wx公眾號 ::石衫的架構(gòu)筆記?

jvm區(qū)域劃分:

jvm的區(qū)域劃分如下所示:

大致就是分為:程序計數(shù)器渴庆,虛擬機(jī)棧,堆,方法區(qū)襟雷,本地方法棧刃滓,這幾個部分。

接下來我們從自己寫好的Java代碼如何通過JVM來運(yùn)行的角度耸弄,來分析一下JVM里這些區(qū)域是如何支撐我們的Java代碼跑起來的咧虎。

程序計數(shù)器

假設(shè)我們有如下的一個類,就是最最基本的一個HelloWorld而已:

public class HelloWorld {

? ? ? ? public static void main(String[] args) {

? ? ? ? ? ?System.out.println("Hello World");

? ? ? ? }

}

上面那段代碼首先會存在于 “.java” 后綴的文件里计呈,這個文件就是java源代碼文件老客,但是這個文件是面向我們程序員的,計算機(jī)看不懂這段代碼

所以此時就得通過編譯器震叮,把“.java”后綴的源代碼文件編譯為“.class”后綴的字節(jié)碼文件。

這個“.class”后綴的字節(jié)碼文件里鳍鸵,存放的就是對你寫出來的代碼編譯好的字節(jié)碼了苇瓣。

這個字節(jié)碼才是計算器可以理解的一種語言,而不是我們寫出來的那一堆代碼偿乖。

這個字節(jié)碼看起來大概是下面這樣的:

說明一下:這段字節(jié)碼并不是完全對照著HelloWorld那個類來寫的击罪,就是給一段示例,讓大家知道“.java”翻譯成的“.class”是大概什么樣子贪薪。

比如這里的“0: aload_0”這樣的東西媳禁,就是“字節(jié)碼指令”,他對應(yīng)了一條一條的機(jī)器指令画切,計算機(jī)只有讀到這種機(jī)器碼指令竣稽,才知道具體應(yīng)該要干什么。

比如說字節(jié)碼指令可能會讓計算機(jī)從內(nèi)存里讀取某個數(shù)據(jù)霍弹,或者把某個數(shù)據(jù)寫入到內(nèi)存里去毫别。

總之,各種各樣的指令典格,就會指示計算機(jī)去干各種各樣的事情岛宦。

所以現(xiàn)在首先明白一點(diǎn):我們寫好的Java代碼是會被翻譯成字節(jié)碼的,對應(yīng)各種字節(jié)碼指令耍缴。那么Java代碼通過JVM跑起來的第一件事情就明確了砾肺。

接下來,在執(zhí)行字節(jié)碼指令時防嗡,JVM里的程序計數(shù)器就是用來記錄每個線程當(dāng)前執(zhí)行的字節(jié)碼指令的位置的变汪,記錄當(dāng)前線程目前執(zhí)行到了哪一條字節(jié)碼指令。

因?yàn)闀卸鄠€線程來并發(fā)的執(zhí)行各種不同的代碼本鸣,所以每個線程都有自己的一個程序計數(shù)器疫衩,專門記錄當(dāng)前這個線程目前執(zhí)行到了哪一條字節(jié)碼指令了

下圖更加清晰的展示出了他們之間的關(guān)系。

Java虛擬機(jī)棧

Java代碼在執(zhí)行的時候,一定是線程來執(zhí)行某個方法中的代碼闷煤,哪怕上面那個最基礎(chǔ)的HelloWorld代碼童芹,也會有一個main線程來執(zhí)行main方法里的代碼。

在方法里鲤拿,經(jīng)常會定義一些方法內(nèi)的局部變量假褪,比如下面這樣,就在方法里定義了一個局部變量“name”近顷。

public void sayHello() {

? ? ? ? String name = "hello";

}

所以JVM必須有一塊區(qū)域來保存每個方法內(nèi)的局部變量等數(shù)據(jù)生音,這個區(qū)域就是Java虛擬機(jī)棧

每個線程都會去執(zhí)行各種方法的代碼,方法內(nèi)還會嵌套調(diào)用其他的方法窒升,所以每個線程都有自己的Java虛擬機(jī)棧缀遍。

如果線程執(zhí)行了一個方法,那么就會為這個方法調(diào)用創(chuàng)建對應(yīng)的一個棧幀

棧幀里有這個方法的局部變量表 饱须、操作數(shù)棧域醇、動態(tài)鏈接、方法出口等東西蓉媳,但是這里別的不太好理解譬挚,先理解一個局部變量就可以。

舉例酪呻,比如一個線程調(diào)用了上面寫的 “sayHello” 方法减宣,那么就會為“sayHello”方法創(chuàng)建一個棧幀,壓入線程自己的Java虛擬機(jī)棧里面去玩荠。

在棧幀的局部變量表里就會有“name”這個局部變量漆腌。

下圖展示了這個過程。

接著如果“sayHello”方法調(diào)用了另外一個“greeting”方法 姨蟋,比如下面那樣的代碼:

這時會給“greeting”方法又創(chuàng)建一個棧幀屉凯,壓入線程的Java虛擬機(jī)棧里,因?yàn)殚_始執(zhí)行“greeting”方法了眼溶。

而且“greeting”方法的棧幀的局部變量表里會有一個“greet”變量悠砚,這是“greeting”方法的局部變量。

接著如果“greeting”方法執(zhí)行完畢了堂飞,就會把“greeting”方法對應(yīng)的棧幀從Java虛擬機(jī)棧里給出棧灌旧。

然后接下來如果“sayHello”方法也執(zhí)行完畢了,就會把“sayHello”方法也從Java虛擬機(jī)棧里出棧绰筛。

這就是JVM中的 “Java虛擬機(jī)棧?” 這個組件的作用:調(diào)用執(zhí)行任何方法的時候枢泰,都會給方法創(chuàng)建棧幀,然后入棧铝噩。

而在棧幀里存放了這個方法對應(yīng)的局部變量之類的數(shù)據(jù)衡蚂,包括這個方法執(zhí)行的其他相關(guān)的信息,方法執(zhí)行完畢之后就出棧。

Java堆內(nèi)存

JVM中有另外一個非常關(guān)鍵的區(qū)域毛甲,就是Java堆年叮,這里就是存放我們在代碼中創(chuàng)建的各種對象的,比如說下面的代碼:

public void sayHello(String name) {

? ? Student student = new Student(name);

? ? student.study();

}

上面的 “new Student(name)” 這個代碼玻募,就是創(chuàng)建了一個Student類型的對象實(shí)例只损,這個對象實(shí)例里面會包含一些數(shù)據(jù)。

比如說這個Student的“name”就是屬于這個對象實(shí)例的數(shù)據(jù)七咧,類似Student這樣的對象跃惫,就會存放在Java堆內(nèi)存里。

Java堆內(nèi)存區(qū)域里會放入類似Student的對象艾栋,然后方法的棧幀的局部變量表里爆存,會存放這個引用類型的“student”局部變量,即存放Student對象的地址蝗砾。

相當(dāng)于你可以認(rèn)為局部變量表里的“student”指向了Java堆里的Student對象终蒂。

看下圖會更加清晰一些。

方法區(qū) / Metaspace

這個方法區(qū)是在JDK 1.8以前的版本里遥诉,代表JVM中的一塊區(qū)域.

他主要是放類似Student類自己的信息的,平時用到的各種類的信息噪叙,都是放在這個區(qū)域里矮锈,還會有一些類似常量池的東西放在這個區(qū)域里。

但是在JDK 1.8以后睁蕾,這塊區(qū)域的名字改了苞笨,叫做“Metaspace”,可以認(rèn)為是“元數(shù)據(jù)空間”這樣的意思子眶,當(dāng)然他主要還是存放我們自己寫的各種類相關(guān)的信息瀑凝。

本地方法棧

其實(shí)在JDK很多底層API里,比如IO相關(guān)的臭杰,NIO相關(guān)的粤咪,網(wǎng)絡(luò)Socket相關(guān)的,如果去看他內(nèi)部的源碼渴杆,會發(fā)現(xiàn)很多地方都不是Java代碼了寥枝。

很多地方都會去走native方法,去調(diào)用本地操作系統(tǒng)里面的一些方法磁奖,可能調(diào)用的都是c語言寫的方法囊拜,或者一些底層類庫,比如下面這樣的:

public native int hashCode();

在調(diào)用這種 native 方法時比搭,就會有線程對應(yīng)的本地方法棧冠跷,這個里面也是跟Java虛擬機(jī)棧類似的,也是存放各種native方法的局部變量表之類的信息。

堆外內(nèi)存

還有一個區(qū)域蜜托,是不屬于JVM的抄囚,通過NIO中的 allocateDirect 這種API,可以在Java堆外分配內(nèi)存空間盗冷。

然后通過Java虛擬機(jī)里的 DirectByteBuffer 來引用和操作堆外內(nèi)存空間怠苔,其實(shí)很多技術(shù)都會用這種方式,因?yàn)樵谝恍﹫鼍跋乱翘牵淹鈨?nèi)存分配可以提升性能柑司。

總結(jié)

最后做一點(diǎn)總結(jié),我們的Java代碼通過JVM來運(yùn)行時:

首先一定會一行一行執(zhí)行編譯好的字節(jié)碼指令锅劝。

然后在執(zhí)行的過程中攒驰,對于方法的調(diào)用,會通過Java虛擬機(jī)棧來為每個方法創(chuàng)建棧幀來入棧和出棧故爵,而且棧幀里有方法的局部變量表玻粪。

接著對于對象的創(chuàng)建,會分配到Java堆內(nèi)存里去

對于類信息的存儲诬垂,會放在方法區(qū) / Metaspace這樣的區(qū)域里劲室。

另外有兩塊特殊的區(qū)域:

本地方法棧,是執(zhí)行native方法時候用的棧结窘,跟Java虛擬機(jī)棧是類似的

堆外內(nèi)存很洋,可以在Java堆外分配內(nèi)存空間來存儲一些對象

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市隧枫,隨后出現(xiàn)的幾起案子喉磁,更是在濱河造成了極大的恐慌,老刑警劉巖官脓,帶你破解...
    沈念sama閱讀 219,366評論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件协怒,死亡現(xiàn)場離奇詭異,居然都是意外死亡卑笨,警方通過查閱死者的電腦和手機(jī)孕暇,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,521評論 3 395
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來赤兴,“玉大人芭商,你說我怎么就攤上這事〔蟛” “怎么了铛楣?”我有些...
    開封第一講書人閱讀 165,689評論 0 356
  • 文/不壞的土叔 我叫張陵,是天一觀的道長艺普。 經(jīng)常有香客問我簸州,道長鉴竭,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,925評論 1 295
  • 正文 為了忘掉前任岸浑,我火速辦了婚禮搏存,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘矢洲。我一直安慰自己璧眠,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,942評論 6 392
  • 文/花漫 我一把揭開白布读虏。 她就那樣靜靜地躺著责静,像睡著了一般。 火紅的嫁衣襯著肌膚如雪盖桥。 梳的紋絲不亂的頭發(fā)上灾螃,一...
    開封第一講書人閱讀 51,727評論 1 305
  • 那天,我揣著相機(jī)與錄音揩徊,去河邊找鬼腰鬼。 笑死,一個胖子當(dāng)著我的面吹牛塑荒,可吹牛的內(nèi)容都是我干的熄赡。 我是一名探鬼主播,決...
    沈念sama閱讀 40,447評論 3 420
  • 文/蒼蘭香墨 我猛地睜開眼齿税,長吁一口氣:“原來是場噩夢啊……” “哼本谜!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起偎窘,我...
    開封第一講書人閱讀 39,349評論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎溜在,沒想到半個月后陌知,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,820評論 1 317
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡掖肋,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,990評論 3 337
  • 正文 我和宋清朗相戀三年仆葡,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片志笼。...
    茶點(diǎn)故事閱讀 40,127評論 1 351
  • 序言:一個原本活蹦亂跳的男人離奇死亡沿盅,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出纫溃,到底是詐尸還是另有隱情腰涧,我是刑警寧澤,帶...
    沈念sama閱讀 35,812評論 5 346
  • 正文 年R本政府宣布紊浩,位于F島的核電站窖铡,受9級特大地震影響疗锐,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜费彼,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,471評論 3 331
  • 文/蒙蒙 一滑臊、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧箍铲,春花似錦雇卷、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,017評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至芙粱,卻和暖如春祭玉,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背春畔。 一陣腳步聲響...
    開封第一講書人閱讀 33,142評論 1 272
  • 我被黑心中介騙來泰國打工脱货, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人律姨。 一個月前我還...
    沈念sama閱讀 48,388評論 3 373
  • 正文 我出身青樓振峻,卻偏偏與公主長得像,于是被迫代替她去往敵國和親择份。 傳聞我的和親對象是個殘疾皇子扣孟,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,066評論 2 355

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