Java核心篇-JVM內(nèi)存模型

JVM是我們成為一名架構(gòu)師必須要掌握的一個(gè)知識(shí)體系,也是我們和一般只會(huì)敲代碼的程序員特別能體現(xiàn)差距的地方。而JVM的數(shù)據(jù)結(jié)構(gòu)基礎(chǔ)织中,也就是它的內(nèi)存模型掘猿,是它入門(mén)的第一課病游。下面我將分成3個(gè)方面向大家介紹JVM內(nèi)存模型。

  1. JVM介紹

  2. JVM整體架構(gòu)

  3. JVM內(nèi)存結(jié)構(gòu)

  4. 后記

JVM介紹

1.虛擬機(jī)是啥

虛擬機(jī)(Virtual Machine)指通過(guò)軟件模擬的具有完整硬件系統(tǒng)功能的稠通、運(yùn)行在一個(gè)完全隔離環(huán)境中的完整計(jì)算機(jī)系統(tǒng)衬衬。通俗的講就是用軟件模擬的一臺(tái)物理機(jī)。

很多時(shí)候改橘,在我們需要用到多臺(tái)電腦的時(shí)候滋尉,但是手頭緊,就可以使用虛擬機(jī)模擬出新的電腦去使用飞主。

常用的虛擬機(jī)有VMWare(一般多用模擬linux系統(tǒng))狮惜,Virtual Box(做App的模擬),Java Virtual Machine(JVM)

2.JVM是啥

JVM全稱(chēng)是Java Virtual Machine(java虛擬機(jī))碌识,你可以這樣理解:JVM是以java字節(jié)碼(class文件)為機(jī)器碼的物理機(jī)碾篡。java通過(guò)它實(shí)現(xiàn)了一處編譯、處處運(yùn)行的豪言壯語(yǔ)筏餐,任何機(jī)器上只要裝了JVM开泽,我都可以把編譯打包好的java代碼放上去運(yùn)行!?伞穆律!。

3.市面上的JVM

Sun HotSpot VM佩番、BEA JRockit VM众旗、IBM J9 VM、Azul VM趟畏、Apache Harmony贡歧、Google Dalvik VM、Microsoft JVM

這里面用的很多的有Sun HotSpot VM赋秀、BEA JRockit VM利朵、IBM J9 VM,其中前兩個(gè)已經(jīng)被Oracle收購(gòu)了猎莲,后面的那個(gè)绍弟,聽(tīng)說(shuō)Oracle也想收購(gòu)來(lái)著,可是想了想著洼,太貴了樟遣,也就放棄了而叼。

JVM整體架構(gòu)

1.JVM的內(nèi)部結(jié)構(gòu)

JVM分成3個(gè)部分,如下:

image
  1. 類(lèi)加載器:負(fù)責(zé)加載.class文件存入運(yùn)行時(shí)數(shù)據(jù)區(qū)

  2. 運(yùn)行時(shí)數(shù)據(jù)區(qū)(內(nèi)存結(jié)構(gòu)):負(fù)責(zé)存儲(chǔ)運(yùn)行時(shí)的數(shù)據(jù)的地方

  3. 執(zhí)行引擎:輸入字節(jié)碼豹悬,執(zhí)行相應(yīng)的指令葵陵,輸出結(jié)果

我們可以把他們3者的關(guān)系看成是,CPU(執(zhí)行引擎)瞻佛,內(nèi)存(運(yùn)行時(shí)數(shù)據(jù)區(qū))脱篙,文件系統(tǒng)驅(qū)動(dòng)(類(lèi)加載器),首先由文件系統(tǒng)的驅(qū)動(dòng)(類(lèi)加載器)去讀取.class文件伤柄,存入內(nèi)存(運(yùn)行時(shí)數(shù)據(jù)區(qū))中绊困,CPU(執(zhí)行引擎)通過(guò)和內(nèi)存(運(yùn)行時(shí)數(shù)據(jù)區(qū))交互,得到計(jì)算結(jié)果适刀。

2.運(yùn)行時(shí)數(shù)據(jù)區(qū)結(jié)構(gòu)

運(yùn)行時(shí)數(shù)據(jù)區(qū)在java設(shè)計(jì)規(guī)范中分成了五個(gè)部分秤朗,分別是程序計(jì)數(shù)器,Java棧蔗彤,本地方法棧川梅,Java堆以及方法區(qū),介紹如下:

image
  • 程序計(jì)數(shù)器(線程私有):是一個(gè)指針然遏,指向下一條指令的地址贫途,也就是告訴執(zhí)行引擎,該線程下一步要執(zhí)行的指令待侵,需要空間很小

  • Java棧(線程私有):Java線程執(zhí)行方法的內(nèi)存模型丢早,一個(gè)線程對(duì)應(yīng)一個(gè)棧,用于存儲(chǔ)java方法中的私有數(shù)據(jù)秧倾,它的生命周期和線程一致怨酝。只要線程一結(jié)束該棧就會(huì)釋放,不需要垃圾回收那先。

  • 本地方法棧(線程私有):和Java棧類(lèi)似农猬,本地方法(native方法),也就是早期用C/C++實(shí)現(xiàn)的方法也有棧售淡,在Execution Engine執(zhí)行時(shí)加載本地方法庫(kù)

  • Java堆(線程共有):存儲(chǔ)那些對(duì)于占用地址較大斤葱,創(chuàng)建成本比較高的數(shù)據(jù),也就是我們創(chuàng)建的對(duì)象實(shí)例揖闸。

  • 方法區(qū)(線程共有):類(lèi)的所有字段和方法字節(jié)碼揍堕,以及一些特殊方法如構(gòu)造函數(shù),接口代碼也在此定義汤纸。簡(jiǎn)單說(shuō)衩茸,所有定義的方法的信息都保存在該區(qū)域,是類(lèi)加載器存儲(chǔ)class文件信息的地方贮泞,靜態(tài)變量+常量+類(lèi)信息(構(gòu)造方法/接口定義)+運(yùn)行時(shí)常量池都存在方法區(qū)中楞慈。

大家可以發(fā)現(xiàn)幔烛,這里面提到了線程私有和線程共有,指的是對(duì)于每一個(gè)新的線程囊蓝,都會(huì)創(chuàng)建一個(gè)程序技術(shù)器说贝、java棧和本地方法棧,一旦線程結(jié)束慎颗,這些都會(huì)被銷(xiāo)毀,而java堆和方法區(qū)只有在所有的線程都執(zhí)行完的時(shí)候才會(huì)被銷(xiāo)毀的言询。

3.Java棧的內(nèi)存模型

棧俯萎,是一個(gè)先進(jìn)先出的數(shù)據(jù)結(jié)構(gòu)。在java棧內(nèi)运杭,會(huì)對(duì)每一個(gè)執(zhí)行到的java方法都會(huì)創(chuàng)建一個(gè)棧幀夫啊,放入棧內(nèi),一旦棧幀執(zhí)行完畢就會(huì)出棧辆憔,繼續(xù)執(zhí)行最外層的棧幀撇眯,直到所有的棧幀都出棧了,線程也就執(zhí)行完畢了虱咧。

對(duì)于每一個(gè)棧幀熊榛,里面都有4個(gè)部分,分別是局部變量表腕巡、操作數(shù)棧玄坦、動(dòng)態(tài)鏈接以及返回地址;

image
  • 局部變量表:記錄當(dāng)前方法參數(shù)以及內(nèi)部定義的局部變量

  • 操作數(shù)棧:記錄當(dāng)前的操作數(shù)

  • 動(dòng)態(tài)鏈接:表示對(duì)內(nèi)部方法的調(diào)用绘沉,無(wú)法在類(lèi)加載階段或第一次使用時(shí)直接確定的煎楣,由每一次調(diào)用所確定方法引用,稱(chēng)之為動(dòng)態(tài)鏈接

  • 返回地址:方法結(jié)束车伞,返回上層方法以及恢復(fù)上層方法執(zhí)行狀態(tài)所需的信息

4. Java堆介紹

為了能夠更好的對(duì)對(duì)象進(jìn)行垃圾回收择懂,java設(shè)計(jì)對(duì)堆進(jìn)行了分代,這樣可以方便對(duì)存活時(shí)間不同的對(duì)象進(jìn)行處理另玖,分成了2個(gè)部分:

image
  1. 年輕代:用于存放新產(chǎn)生的對(duì)象困曙。年輕代分為兩部分: 伊甸區(qū)(Eden space)和幸存者區(qū)(Survivor pace) 。所有的類(lèi)都是在伊甸區(qū)被new出來(lái)的日矫。幸存區(qū)有兩個(gè): 0區(qū)(Survivor 0 space)和1區(qū)(Survivor 1 space)赂弓。當(dāng)伊甸園的空間用完時(shí),程序又需要?jiǎng)?chuàng)建對(duì)象哪轿,JVM的垃圾回收器將對(duì)伊甸園區(qū)進(jìn)行垃圾回收(Minor GC)盈魁,將伊甸園區(qū)中的不再被其他對(duì)象所引用的對(duì)象進(jìn)行銷(xiāo)毀。然后將伊甸園中的剩余對(duì)象移動(dòng)到幸存 0區(qū)窃诉。若幸存 0區(qū)也滿(mǎn)了杨耙,再對(duì)該區(qū)進(jìn)行垃圾回收赤套,然后移動(dòng)到1區(qū),如果還是滿(mǎn)了珊膜,就到老年代容握。

  2. 老年代:用于存放被長(zhǎng)期引用的對(duì)象。新生區(qū)經(jīng)過(guò)多次GC仍然存活的對(duì)象移動(dòng)到老年區(qū)车柠。若老年區(qū)也滿(mǎn)了剔氏,那么這個(gè)時(shí)候?qū)a(chǎn)生MajorGC(FullGC),進(jìn)行老年區(qū)的內(nèi)存清理竹祷。若老年區(qū)執(zhí)行了Full GC之后發(fā)現(xiàn)依然無(wú)法進(jìn)行對(duì)象的保存谈跛,就會(huì)產(chǎn)生OOM異常“OutOfMemoryError塑陵。

5. 方法區(qū)介紹

雖然Java虛擬機(jī)規(guī)范把方法區(qū)描述為堆的一個(gè)邏輯部分感憾,但是它卻有一個(gè)別名叫做 Non-Heap(非堆),目的應(yīng)該是與 Java 堆區(qū)分開(kāi)來(lái)令花。所以這一部分我也就單獨(dú)拿出來(lái)說(shuō)明了阻桅。

可能大家對(duì)這一個(gè)名字聽(tīng)的不是很多,但可能大家聽(tīng)過(guò)永久代或持久代的會(huì)更多一點(diǎn)兼都,永久代是HotSpot JVM 在java8之前對(duì)方法區(qū)的實(shí)現(xiàn)嫂沉,這個(gè)名稱(chēng)也是相對(duì)年輕代和老年代來(lái)說(shuō),他們的FullGC也會(huì)對(duì)永生代進(jìn)行垃圾回收扮碧。

在java8之后输瓜,永久代被代替了,換成了元空間區(qū)芬萍,兩者本質(zhì)都是對(duì)JVM規(guī)范中方法區(qū)的實(shí)現(xiàn)尤揣,區(qū)別在于元數(shù)據(jù)區(qū)并不在虛擬機(jī)中,而是使用本地物理內(nèi)存柬祠,這樣的話北戏,方法區(qū)的大小也就不那么容易收到限制,而永久代在虛擬機(jī)中漫蛔,永久代邏輯結(jié)構(gòu)上屬于堆嗜愈,但是物理上不屬于堆,堆大小=新生代+老年代莽龟。元數(shù)據(jù)區(qū)也有可能發(fā)生OutOfMemory異常蠕嫁,

元數(shù)據(jù)區(qū)的動(dòng)態(tài)擴(kuò)展,默認(rèn)–XX:MetaspaceSize值為21MB的高水位線毯盈。一旦觸及則Full GC將被觸發(fā)并卸載沒(méi)有用的類(lèi)(類(lèi)對(duì)應(yīng)的類(lèi)加載器不再存活)剃毒,然后高水位線將會(huì)重置。新的高水位線的值取決于GC后釋放的元空間。如果釋放的空間少赘阀,這個(gè)高水位線則上升益缠。如果釋放空間過(guò)多,則高水位線下降基公。

后記

1.為什么jdk1.8用元數(shù)據(jù)區(qū)取代了永久代幅慌?

首先我們來(lái)看看官方解釋?zhuān)阂瞥谰么菫槿诤螲otSpot JVM與 JRockit VM而做出的努力,因?yàn)镴Rockit沒(méi)有永久代轰豆,不需要配置永久代胰伍;

除此之外,我覺(jué)得應(yīng)該還有其他考慮:去除永久代后分代GC可以減少?gòu)?fù)雜性酸休,不用考慮永久代的gc喇辽;不用指定PermSize,指定太小容易造成永久代OOM

2.既然有動(dòng)態(tài)鏈接雨席,那靜態(tài)鏈接呢?

解析調(diào)用一定是個(gè)靜態(tài)過(guò)程吠式,在編譯期間就完全確定陡厘,在類(lèi)加載的解析階段就會(huì)把涉及的符號(hào)引用轉(zhuǎn)化為可確定的直接引用,不會(huì)延遲到運(yùn)行期再去完成特占,這也就是Java中的靜態(tài)鏈接糙置。

在Class文件中的常量持中存有大量的符號(hào)引用。字節(jié)碼中的方法調(diào)用指令就以常量池中指向方法的符號(hào)引用作為參數(shù)是目。這些符號(hào)引用一部分在類(lèi)的加載階段(解析)或第一次使用的時(shí)候就轉(zhuǎn)化為了直接引用(指向數(shù)據(jù)所存地址的指針或句柄等)谤饭,這種轉(zhuǎn)化稱(chēng)為靜態(tài)鏈接。而相反的懊纳,另一部分在運(yùn)行期間轉(zhuǎn)化為直接引用揉抵,就稱(chēng)為動(dòng)態(tài)鏈接。

通俗一點(diǎn)就是說(shuō)能在類(lèi)加載階段就能確定的方法調(diào)用嗤疯,是靜態(tài)鏈接冤今,如果要在運(yùn)行時(shí)確定的話,那就是動(dòng)態(tài)鏈接了茂缚,我們通過(guò)這樣的特性可以實(shí)現(xiàn)多態(tài)戏罢。

后面我們將繼續(xù)編寫(xiě)幾篇jvm類(lèi)加載以及調(diào)優(yōu)等相關(guān)知識(shí),敬請(qǐng)期待哦脚囊。如果我有寫(xiě)的不對(duì)的地方龟糕,歡迎大家來(lái)指正,讓我們?cè)诨ヂ?lián)網(wǎng)架構(gòu)師之路上越走越遠(yuǎn)悔耘,感謝大家的陪伴讲岁,謝謝大家啦~

qrcode_for_gh_ee1395d75e06_344.jpg

文章轉(zhuǎn)載自微信公眾號(hào),互聯(lián)網(wǎng)架構(gòu)師學(xué)習(xí)之路,歡迎大家的關(guān)注催首,我們?cè)倩ヂ?lián)網(wǎng)架構(gòu)師學(xué)習(xí)之路上等你扶踊!

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市郎任,隨后出現(xiàn)的幾起案子秧耗,更是在濱河造成了極大的恐慌,老刑警劉巖舶治,帶你破解...
    沈念sama閱讀 206,602評(píng)論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件分井,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡霉猛,警方通過(guò)查閱死者的電腦和手機(jī)尺锚,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,442評(píng)論 2 382
  • 文/潘曉璐 我一進(jìn)店門(mén),熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)惜浅,“玉大人瘫辩,你說(shuō)我怎么就攤上這事√诚ぃ” “怎么了伐厌?”我有些...
    開(kāi)封第一講書(shū)人閱讀 152,878評(píng)論 0 344
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)裸影。 經(jīng)常有香客問(wèn)我挣轨,道長(zhǎng),這世上最難降的妖魔是什么轩猩? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 55,306評(píng)論 1 279
  • 正文 為了忘掉前任卷扮,我火速辦了婚禮,結(jié)果婚禮上均践,老公的妹妹穿的比我還像新娘晤锹。我一直安慰自己,他們只是感情好彤委,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,330評(píng)論 5 373
  • 文/花漫 我一把揭開(kāi)白布抖甘。 她就那樣靜靜地躺著,像睡著了一般葫慎。 火紅的嫁衣襯著肌膚如雪衔彻。 梳的紋絲不亂的頭發(fā)上,一...
    開(kāi)封第一講書(shū)人閱讀 49,071評(píng)論 1 285
  • 那天偷办,我揣著相機(jī)與錄音艰额,去河邊找鬼。 笑死椒涯,一個(gè)胖子當(dāng)著我的面吹牛柄沮,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 38,382評(píng)論 3 400
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼祖搓,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼狱意!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起拯欧,我...
    開(kāi)封第一講書(shū)人閱讀 37,006評(píng)論 0 259
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤详囤,失蹤者是張志新(化名)和其女友劉穎,沒(méi)想到半個(gè)月后镐作,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體藏姐,經(jīng)...
    沈念sama閱讀 43,512評(píng)論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 35,965評(píng)論 2 325
  • 正文 我和宋清朗相戀三年该贾,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了羔杨。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 38,094評(píng)論 1 333
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡杨蛋,死狀恐怖兜材,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情逞力,我是刑警寧澤曙寡,帶...
    沈念sama閱讀 33,732評(píng)論 4 323
  • 正文 年R本政府宣布,位于F島的核電站掏击,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏秩铆。R本人自食惡果不足惜砚亭,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,283評(píng)論 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望殴玛。 院中可真熱鬧捅膘,春花似錦、人聲如沸滚粟。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 30,286評(píng)論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)凡壤。三九已至署尤,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間亚侠,已是汗流浹背曹体。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 31,512評(píng)論 1 262
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留硝烂,地道東北人箕别。 一個(gè)月前我還...
    沈念sama閱讀 45,536評(píng)論 2 354
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親串稀。 傳聞我的和親對(duì)象是個(gè)殘疾皇子除抛,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,828評(píng)論 2 345