故事:走進JVM的世界(圖文并茂)

原文:故事:走進JVM的世界(圖文并茂)

走進JVM的世界
  1. 注意康栈!本文較長众弓,建議先收藏再閱讀煎娇。更多文章可以關注作者公眾號:碼上實戰(zhàn)
  2. 你也可以 star 我的 GitHub上本文所屬倉庫:https://github.com/flyhero/MarkNote
  3. 說明:本文在 Java 8 Hotspot 64位操作系統(tǒng)下構思

小強是一個工作3年有余的開發(fā)工程師根盒,從他的發(fā)量你就可以知道纠拔,小強資歷還尚淺。

程序員驚人發(fā)量

最近公司沒什么事蜜氨,他也開始無聊起來了械筛。這天下午,同事們在激烈的討論這業(yè)務飒炎,但他沒有參與埋哟,于是他決定學習些什么知識,無聊的翻著各個網(wǎng)頁郎汪,發(fā)現(xiàn)JVM是各位大神們推薦過的知識赤赊,于是決定好好看一看。

5分鐘過后……

小強感到這知識有些枯燥乏味怒竿,怪不得是大神們能看的砍鸠!又看了幾分鐘,小強倦意襲來耕驰,揉了揉睡眼惺忪的眼睛爷辱。

然而就在這一刻,他突然發(fā)現(xiàn)周圍同事激烈討論的聲音聽不到了朦肘,安靜到了極致饭弓。

1. 入界

小強努力的睜開眼睛,才發(fā)現(xiàn)自己竟然身處一個白茫茫的空間中媒抠,嚇得一跳弟断,心想我這是怎么了,穿越了趴生?但穿越也得穿越到一個人間如畫阀趴,美女如云的地方啊……,這境地……


JVM幻境

突然前方走來一個白胡子老頭苍匆,小強正想開口刘急,老頭捷足先登:你好,我是這個JVM世界的締造者浸踩,你可以叫我 “HotSpot”叔汁,不過這無所謂,因為我所創(chuàng)造的這個世界检碗,是按照 “JVM規(guī)范” 來完成的据块。我正在休息時,發(fā)現(xiàn)來了一位客人折剃,原來是你另假。

小強:我是想問……

老頭: 不用問,我知道怕犁,你是想了解一下我創(chuàng)造的這個世界吧边篮!跟我來吧开睡。

這老頭,我還沒說話苟耻,這就結束了!好吧扶檐,跟你看看且說凶杖。

老頭邊走邊道:JVM 的世界 空間是有限的,我們堅持一個原則 : 各司其職款筑,不留無用之人智蝠!

小強: 啊奈梳!好殘酷杈湾。

老頭: 不,這不是殘酷攘须,我們這個世界生來就是為客戶提供服務漆撞,為客戶發(fā)光發(fā)熱的,每個人奉獻出了自己的能力就是圓滿完成任務于宙,退出舞臺是理所應當?shù)母〔担彩撬麄冏詈玫臍w宿。

小強:也是捞魁,這樣這個世界才不會那么擁擠至会,才能井然有序的工作,我怎么這么不開竅呢……

2. 布局

過來谱俭,帶你先看看我們世界的整體組成和中心區(qū)如何布局奉件。


整體布局

先來看看我們最主要的日常工作區(qū)(運行時數(shù)據(jù)區(qū)),為了讓我們工作起來更有效率昆著,我們將世界空間劃分為這幾個板塊县貌。

居住區(qū)-堆

這里是人們工作外的居住區(qū),居住區(qū)我們基于人們的年齡也進一步分出了宣吱,伊甸區(qū)窃这,幸存者區(qū),老年區(qū)征候。


居住區(qū)

工作區(qū)-棧

每個任務來臨時杭攻,都會在工作區(qū)單獨開辟出一個地方來用于完成這個任務。


棧幀

記錄者-程序計數(shù)器

由于我們同時能做的任務有限疤坝,所以我們需要為不同的任務劃分出不同的時間片兆解,我們在切換任務的時候,需要一個記錄者跑揉,能夠記錄我們這個任務做到了哪里锅睛,下次回來能夠繼續(xù)做埠巨。

倉庫管理區(qū)-方法區(qū)

這里存放著工人的模板以及常用的不變的工具等。

3. 生與死

這里工作的人們都會經(jīng)歷生與死现拒,大部分人們活不到老年辣垒,但這不重要,重要的是他為我們做出了貢獻印蔬。

3.1 出生

老頭:這里的每個人都有一個模板(類)勋桶,看到那個正在居住區(qū)休息的高個嗎?他叫張三侥猬,他是根據(jù)外部客戶給定的模板 “ User Class” 創(chuàng)造的例驹,他可是客戶最喜愛的工人了。你知道客戶的這些模板(類)是如何進入的到我們的世界中的嗎退唠?

小強:這個我知道點鹃锈,之前看過一點點。這個過程還是有些復雜的瞧预,客戶的模板(類)是通過一個翻譯工廠(編譯器) 將它翻譯成class 字節(jié)碼屎债,因為你們這個世界只認識字節(jié)碼,然后有你們的加載系統(tǒng)將它們加載到這里松蒜。

加載過程中有這些階段:


loading-class.png

其中加載階段是由加載器來完成的扔茅。

老頭:是的,我們提供了三種工廠秸苗,啟動類加載器召娜,擴展類加載器,應用類加載器惊楼,當然客戶也可以自定義加載器玖瘸。


parents-delegation.png

小強:他們遵循著雙親委派模型,但是我一直不太理解這個詞檀咙!

老頭: 這是由于你們語言翻譯的問題導致雅倒,這個模式叫 “parents delegation”,知道了吧弧可!它是指有你的父輩們來幫你完成蔑匣。

小強:那雙親委派模式 有什么好處呢?

老頭:

  1. 具有優(yōu)先級層次的關系可以避免模板(類)的重復加載
  2. 安全考慮可以防止Java核心api被替換

老頭繼續(xù)道:那連接過程中的三步棕诵,你知道是做什么嗎裁良?

小強:具體的我就不知道了哎……

老頭笑了笑:對于客戶定義的模板(類),我們可不是來者不拒的校套,為了我們這個世界的安全以及能提供更好的服務价脾,我們會對模板做一些驗證及后續(xù)操作。

驗證包括格式驗證笛匙,元數(shù)據(jù)驗證侨把,字節(jié)碼驗證犀变,符號驗證。當驗證通過后秋柄,我們會為模板所依賴的東西(類變量)分配空間获枝,最后將符號引用替換為直接引用。

老頭看了看小強眉頭緊皺骇笔,于是繼續(xù)補充:你可能不了解什么是符號引用和直接引用映琳!

符號引用就是在編譯時,并不知道模板(類)所依賴的其他東西蜘拉,會在我們的空間中的哪個位置,只能用符號來表示有鹿。

直接引用就是 所有東西被加載到這里后會有自己的真實空間地址旭旭,然后去替換符號引用。這樣運行時就能找到它們所依賴的東西了葱跋。

最后就是初始化了持寄,這個階段主要是對類變量初始化,是執(zhí)行類構造器的過程娱俺。

小強:我怎么沒看到這些模板呢稍味?

老頭:這些模板我把他們隱藏在世界的后方,大多數(shù)人是見不到的荠卷,他們統(tǒng)稱為 Klass模庐。

小強:不對啊油宜!你是不是搞錯了掂碱?不應該叫 Class嗎?

老頭:哈哈慎冤!我剛才說了疼燥,大多數(shù)人見不到,你就是其中之一耙系獭醉者!你們平時見到的 Class只是對 Klass的一種封裝而已,真正記錄模板中的具體元信息的就是 Klass披诗。這回要記住了胳施,年輕人。

3.2 工人

小強: 為什么你的工人是等量差的身高呢伯复?


obj-data.png

老頭:你的觀察還是挺仔細的嘛撵溃!是的,他們確實是等量差的掂咒,想要知道為什么才沧,要先了解這些工人有哪些部分組成迈喉。


obj-length.png

它們頭部大小是固定的,身體大小是由自己的屬性數(shù)據(jù)決定的温圆,而最后的腳部卻是我來決定的挨摸,如果前面兩個數(shù)據(jù)的大小沒有達到 8 的倍數(shù),那么我就會來填充岁歉,所以就是這里的填充使得他們擁有了等量的身高差(內(nèi)存對齊)得运。

我是基于兩點原因來這個締造他們的:

  1. 平臺原因:不是所有的硬件平臺都能訪問任意地址上的任意數(shù)據(jù)的;某些硬件平臺只能在某些地址處取某些特定類型的數(shù)據(jù)锅移,否則拋出硬件異常熔掺。
  2. 性能原因:中央大腦(CPU)訪問內(nèi)存是有內(nèi)存訪問粒度的,就是每次訪問內(nèi)存的長度是固定的非剃,如果不這樣做置逻,那么中央大腦起需要訪問兩次內(nèi)存,而對齊后只需要一次备绽。

小強:嗯券坞,明白了!那能給我說說這些工人在居住區(qū)為什么要不斷的搬遷呢肺素?

3.3 成長

老頭:經(jīng)過長時間的觀察恨锚,我發(fā)現(xiàn)每個工人的生命長短是不一樣的。所以我把居住區(qū)分為新生代倍靡,老年代猴伶,然后讓他們合理的搬遷,這樣能有效的利用空間而且讓垃圾小分隊工作更有效率塌西。


堆區(qū)分代

工人誕生后會分配到Eden區(qū)蜗顽,當Eden區(qū)人員快滿時,垃圾小分隊會來清掃雨让,清掃后如果工人還活著雇盖,那么他們將搬遷至Survivor區(qū)中的其中一個,當這個Survivor快滿時栖忠,垃圾小分隊會將還活著的工人搬遷至另一個Survivor區(qū)中崔挖,就這樣重復著,每經(jīng)歷一次垃圾小分隊的清掃庵寞,活著的工人就會長大一歲狸相,直到工人的年齡達到15歲,到達后會將他們搬遷至老年代生活的地方捐川。但也有例外脓鹃,如果某個工人吃的太胖,新生代容不下他古沥,那么他將直接去老年代住下瘸右。當老年代快住滿時娇跟,將會有垃圾大掃除(full gc)。

小強:原來如此疤苞俘!從此我再也不是只知道堆區(qū)棧區(qū)的菜鳥啦!哈哈哈哈……

老頭:小伙子龄章,不要高興太早吃谣!你到目前為止所了解的仍是九牛一毛。

3.4 死亡證明

小強:如何確定工人是否到達生命的盡頭呢做裙?

第一種:引用計數(shù)法

給每個工人添加一個引用計數(shù)器岗憋,就是只要有人需要這個工人幫忙,那么就給這個工人的計數(shù)加1锚贱,反之澜驮,別人不再需要這個工人的幫忙,那么計數(shù)就減1惋鸥,直到這個計數(shù)為0,那么表示這個工人生命到了盡頭悍缠。

但這種方法有個問題:如果A工人和B工人相互需要幫忙卦绣,但沒有任何其他工人或任務需要他們兩個,那么他們兩個會永遠活下飞蚓!所以這種方法我們不會采取的滤港。

第二種:可達性分析法

我們找出被稱為 “GC roots”的工人作為起點,依次尋找他們工作中依賴的工人趴拧,這就可以知道哪些工人是沒有必要在存在下去了溅漾。

小強:我怎么知道哪些是 “GC roots”工人呢?

老頭:

  1. 工作區(qū)(棧)中的需要用到的工人
  2. 倉庫(方法區(qū))中模板(類)本身需要的工人(靜態(tài)著榴,常量)
  3. 世界后方(native方法)需要的工人

小強:Got it!

4. 回收

老頭:下面我?guī)闳フJ識一下垃圾小分隊的人物吧添履!不過在認識他們之前你最好了解一下,垃圾清除的基本方法論脑又。

4.1 基本方法論

收集垃圾遵循的基本方法論有以下幾種:

  • 標記-清除

    首先標記出所有需要回收的工人(對象)暮胧,在標記完成后統(tǒng)一回收所有被標記的工人。

    但這個有兩個缺點:1. 效率不高 2. 會產(chǎn)生許多碎片空間

  • 復制

    將可用的空間一分為二问麸,每次只使用其中一塊往衷,當快使用完時,小分隊回收严卖,然后將活著的工人搬遷至另一塊席舍。

    這雖然解決了標記-清除的效率問題,但此種方法卻縮小了一半空間哮笆。

  • 標記-整理

    首先標記出所有需要回收的工人(對象)来颤,然后將存活的工人移動到空間的一端汰扭,然后清理掉邊界以外的工人。

小強笑了笑:原來是這三種算法敖旁东且!我知道!

老頭:既然知道本讥,那跟我來認識一下垃圾清掃隊的人吧珊泳!

4.2 主要成員

垃圾清掃隊有好幾個小隊組成,客戶喜歡哪個小隊可以指定讓誰來工作拷沸,他們各個隊伍的清掃方式各不相同也各有優(yōu)劣色查。

我給你介紹一下兩個主要成員吧,CMS撞芍,G1兩個小隊出列秧了。

CMS:到,我們是CMS分隊序无,全稱叫 “Concurrent Mark Sweep”验毡,顧名思義,我們是采用標記清除算法的并發(fā)小分隊帝嗡,我們以獲取最短回收停頓時間為目標晶通。

小強:那你說說你們是如何工作的?

CMS:我們主要分四個步驟工作哟玷,1. 初始標記 2.并發(fā)標記 3.重新標記 4.并發(fā)清除

小強:算啦狮辽,這么多步驟太需要時間來了解了,我現(xiàn)在知道你的優(yōu)點了巢寡,那你的缺點有什么呢喉脖?

CMS:這怎么還帶揭人傷疤的……

老頭這時嚴肅的咳嗽了兩聲,其意CMS立馬捕獲到了抑月,委屈的說:

我有三個缺點:

  1. 當資源不是很充足時树叽,占用過多的資源,導致任務變慢
  2. 無法處理浮動垃圾谦絮,我們清理的時候菱皆,工人同時也在工作,我們標記后挨稿,正好有些工人不在需要了
  3. 我們分隊遵循的是“標記-清除”算法仇轻,所以會產(chǎn)生大量碎片空間,導致世界大掃除(full gc)提前到來

心直口快的小強來了句:原來你的問題這么嚴重奶甘,老頭竟然沒把你們小分隊辭掉……

CMS:你…… 想當年我們分隊可是紅極一時的……

那么我猜G1是不是可以彌補CMS的不足呢篷店?

G1: 說實話,我們分隊的目標就是替換CMS分隊…… (JDK14 CMS正式落下帷幕)

小強不懷好意的笑了起來,哈哈……疲陕,CMS翻著白眼躲到一旁的角落暗自傷感去了方淤。

角落哭.jpeg

小強:那G1說說你的能耐吧!

G1: 我們隊是基于標記整理算法的蹄殃,因此不會產(chǎn)生大量碎片空間

  • 我們同時引入了分區(qū)的思路携茂,弱化了分代的概念

  • 我們的停頓時間是可控的,可避免雪崩現(xiàn)象

  • 我們也能充分利用客戶給我們的資源诅岩,減少停頓時間

這是我們隊的優(yōu)勢讳苦,接下來我給你詳細介紹下我們隊的情況……

小強:好的!你繼續(xù)……

回歸

就在小強聽的興趣濃濃時吩谦,天空中突然出現(xiàn)一只巨大無比的手向他襲來鸳谜,小強躲閃不開,啊……

巴掌.png

小強捂著自己的頭式廷,有點恍惚咐扭,抬頭一看,擦滑废,技術總監(jiān)……你怎么也在這蝗肪?

總監(jiān):我不在這我在哪?在家睡大覺嗎蠕趁!

這時小強才回過神來薛闪,原來自己還在辦公室,大事不妙捌薜肌!

總監(jiān):小強怀各,回家多爽倔韭,明天就不用來了吧!

小強一慌瓢对,腦袋靈機一動:總監(jiān)寿酌,知道我剛才在做什么嗎?那可不是在睡覺硕蛹,我有一個故事你且聽聽再做決定醇疼。

吧啦吧啦……

最后我將本文知識總結成了思維導圖:


思維導圖

說明:

  1. 【作者】:flyhero
  2. 【公眾號】:碼上實戰(zhàn)。
  3. 【簡介】:想做個擁有理論的實戰(zhàn)派法焰。
  4. 【福利】:關注微信公眾號秧荆,回復:“JVM” 獲取思維導圖
  5. 【轉(zhuǎn)載】:轉(zhuǎn)載請說明出處,謝謝合作埃仪!
最后編輯于
?著作權歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末乙濒,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌颁股,老刑警劉巖么库,帶你破解...
    沈念sama閱讀 219,427評論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異甘有,居然都是意外死亡诉儒,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,551評論 3 395
  • 文/潘曉璐 我一進店門亏掀,熙熙樓的掌柜王于貴愁眉苦臉地迎上來忱反,“玉大人,你說我怎么就攤上這事幌氮$允埽” “怎么了?”我有些...
    開封第一講書人閱讀 165,747評論 0 356
  • 文/不壞的土叔 我叫張陵该互,是天一觀的道長米者。 經(jīng)常有香客問我,道長宇智,這世上最難降的妖魔是什么蔓搞? 我笑而不...
    開封第一講書人閱讀 58,939評論 1 295
  • 正文 為了忘掉前任,我火速辦了婚禮随橘,結果婚禮上喂分,老公的妹妹穿的比我還像新娘。我一直安慰自己机蔗,他們只是感情好蒲祈,可當我...
    茶點故事閱讀 67,955評論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著萝嘁,像睡著了一般梆掸。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上牙言,一...
    開封第一講書人閱讀 51,737評論 1 305
  • 那天酸钦,我揣著相機與錄音,去河邊找鬼咱枉。 笑死卑硫,一個胖子當著我的面吹牛,可吹牛的內(nèi)容都是我干的蚕断。 我是一名探鬼主播欢伏,決...
    沈念sama閱讀 40,448評論 3 420
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼亿乳!你這毒婦竟也來了颜懊?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,352評論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎河爹,沒想到半個月后匠璧,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,834評論 1 317
  • 正文 獨居荒郊野嶺守林人離奇死亡咸这,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,992評論 3 338
  • 正文 我和宋清朗相戀三年夷恍,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片媳维。...
    茶點故事閱讀 40,133評論 1 351
  • 序言:一個原本活蹦亂跳的男人離奇死亡酿雪,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出侄刽,到底是詐尸還是另有隱情指黎,我是刑警寧澤,帶...
    沈念sama閱讀 35,815評論 5 346
  • 正文 年R本政府宣布州丹,位于F島的核電站醋安,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏墓毒。R本人自食惡果不足惜吓揪,卻給世界環(huán)境...
    茶點故事閱讀 41,477評論 3 331
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望所计。 院中可真熱鬧柠辞,春花似錦、人聲如沸主胧。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,022評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽踪栋。三九已至焙格,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間己英,已是汗流浹背间螟。 一陣腳步聲響...
    開封第一講書人閱讀 33,147評論 1 272
  • 我被黑心中介騙來泰國打工吴旋, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留损肛,地道東北人。 一個月前我還...
    沈念sama閱讀 48,398評論 3 373
  • 正文 我出身青樓荣瑟,卻偏偏與公主長得像治拿,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子笆焰,可洞房花燭夜當晚...
    茶點故事閱讀 45,077評論 2 355

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

  • Java和C++之間有一堵由內(nèi)存動態(tài)分配和垃圾收集技術所圍成的“高墻”劫谅,墻外面的人想進來,墻里面的人想出來。 對象...
    胡二囧閱讀 1,089評論 0 4
  • 《深入理解Java虛擬機》筆記_第一遍 先取看完這本書(JVM)后必須掌握的部分捏检。 第一部分 走近 Java 從傳...
    xiaogmail閱讀 5,097評論 1 34
  • JVM有哪些分區(qū)荞驴?程序計數(shù)器,java虛擬機棧贯城,本地方法棧熊楼,堆,方法區(qū)能犯。 java棧中存放的是一個個棧幀鲫骗,每一個棧...
    irckwk1閱讀 695評論 0 0
  • 介紹JVM中7個區(qū)域,然后把每個區(qū)域可能造成內(nèi)存的溢出的情況說明 程序計數(shù)器:看做當前線程所執(zhí)行的字節(jié)碼行號指示器...
    jemmm閱讀 2,229評論 0 9
  • 0. 前言 JVM筆記系列踩晶,以JDK1.7為基準执泰,主要以《深入理解Java虛擬機》(第二版)和《Java虛擬機規(guī)范...
    郭尋撫閱讀 910評論 0 3