一蛔糯、通勤路上搞定 JVM 面試(1)

漫談面試系列

前言

JVM可以說是下到應屆生拯腮,上到高級開發(fā)都是面試必考的知識,只是深淺的不同罷了蚁飒,但是百變不離其中动壤,了解JVM的基本原理與作用,大部分的面試題也能對答如流淮逻。為避免閱讀疲勞琼懊,該系列會將JVM分為兩個部分,第一部分主要介紹JVM的內(nèi)存劃分以及類加載過程爬早,第二部分則是主要講解GC以及JMM相關(guān)問題哼丈。

本系列章節(jié)面向的用戶群體主要是應付面試,因此本文章不會深入講解相關(guān)底層原理筛严,主要以簡單理解的方式為讀者提供應對面試的學習思路醉旦,方便讀者快速理清JVM面試相關(guān)知識,輕松走過面試第一關(guān)桨啃。

我們通過以下常見的JVM面試問題作為學習的入口:

1. JVM運行時數(shù)據(jù)區(qū)的內(nèi)存怎么進行劃分车胡?
2. JVM的類加載是怎么樣的?
3. 如何針對JVM內(nèi)存參數(shù)進行調(diào)優(yōu)优幸?

以上三個問題可以說是jvm面試的基本問題吨拍,接下來我會以總結(jié)式的方式進行問題的解答,讓讀者快速上手這類問題网杆。


1. JVM運行時數(shù)據(jù)區(qū)

其實JVM運行時數(shù)據(jù)區(qū)可以通過分類進行快速記憶羹饰,其中可以分為線程共享以及線程私有

1.  線程共享的區(qū)域有:堆(感覺只要是學java的這個不可能答不出來)、方法區(qū)
2.  線程私有的區(qū)域有:虛擬機棧(java方法)碳却、本地方法棧(c/c++方法)队秩、程序計數(shù)器

大體可以通過下圖進行一個大概的了解:

運行時數(shù)據(jù)區(qū)

上圖已經(jīng)很好的詮釋了相應的內(nèi)存劃分,以及某些數(shù)據(jù)具體存儲在哪昼浦,接下來我們根據(jù)這個圖進行一個簡單的總結(jié):

  1. 程序計數(shù)器是占用空間最小的內(nèi)存區(qū)域馍资,不會出現(xiàn)OOM,主要記錄當前線程正在執(zhí)行的方法的指令地址关噪,方便線程切換后能恢復到下一條指令的位置鸟蟹,如果是執(zhí)行native方法乌妙,則該計數(shù)器為空。(由于這塊老是被遺忘建钥,寫在第一處讓讀者記憶深刻點)

  2. 虛擬機棧是用來存放棧幀的藤韵,說白了棧幀就是方法運行時數(shù)據(jù)存儲的空間,這棧幀主要由四個部分組成:

    Ⅰ. 局部變量熊经,方法體里面包含的變量泽艘,如基本變量 int , float 等以及對象的引用如Student s

    Ⅱ. 操作數(shù)棧,對數(shù)據(jù)的運算需要一個棧來進行镐依,可以理解為自己開發(fā)一個算術(shù)運算時使用的棧結(jié)構(gòu)匹涮,如果有數(shù)據(jù)進行計算的時候會將數(shù)據(jù)放入,然后計算得出的結(jié)果也會存到這里面

    Ⅲ. 動態(tài)鏈接槐壳,存儲了指向class常量池的方法符號引用(一個字符串)然低,說白了這個東西就是查找方法具體位置的一種懶加載機制。在第一次運行會通過這個字符串找到相應方法所在位置务唐,之后將這個位置替換掉符號引用脚翘,變?yōu)橹苯右谩?/p>

    Ⅳ. 返回地址,這個應該很好理解绍哎,我得知道方法運行完后要回去哪,這個地址便是指向進入這個方法時候的地址鞋真,方便返回

  3. 本地方法棧崇堰,與虛擬機棧差不多,只不過運行的是native(c/c++)方法

  4. 涩咖,存儲對象以及數(shù)組的區(qū)域海诲,基本上是jvm內(nèi)存里面最大的區(qū)域。

PS:如果方法里面的一個對象不存在被外界調(diào)用檩互,那么jvm可能會將這個對象存放在棧里面特幔,不過目前怎么判斷一個對象不怎么被外界調(diào)用(即逃逸分析)不太成熟,知道這個的人也不多(面試就遇到一回問這個)闸昨。

  1. 方法區(qū)蚯斯,主要存儲虛擬機加載的類信息、常量饵较、靜態(tài)變量拍嵌,例如上面說的符號引用也存在這。

PS: 讀者對于方法區(qū)最大的疑惑可能就是jdk1.8后的變化循诉,其實jdk1.8前方法區(qū)屬于堆的一個子集横辆,只不過1.8之后變成了和堆的并交(如圖中所示),其中類的元信息存儲在直接內(nèi)存茄猫,而常量池狈蚤、靜態(tài)變量的引用對象還是存在堆中困肩。

最后總結(jié)一下,JVM每遇到一個線程脆侮,就為其分配一個程序計數(shù)器锌畸,虛擬機棧和本地方法棧,棧里面指向的對象一般都在堆中他嚷,線程終止的時候便會清空這些內(nèi)存 ( 以上都是線程私有蹋绽,因此和線程共存亡 ) ,而堆中的對象則根據(jù)可達性分析算法進行生死判斷筋蓖,這個會在下一章節(jié)進行講解卸耘。

2. JVM的類加載流程

廢話不多說,大體流程看圖:

類加載流程

讓我們來一句話總結(jié)一下類的加載過程:將 Class 文件的字節(jié)流轉(zhuǎn)換為方法區(qū)中的 Class 對象(加載)粘咖,檢查該 Class 文件的字節(jié)流是否規(guī)范蚣抗、合法(驗證),為該 Class 的類變量( static )進行空間分配(準備)瓮下,對該 Class 中的符號引用轉(zhuǎn)換為直接引用(解析)翰铡,最后執(zhí)行用戶編寫的構(gòu)造器代碼(初始化)

PS : 其中準備階段和解析階段有些小細節(jié),準備階段如果是類常量( static final )讽坏,則會直接進行賦值操作锭魔,否則賦予初始值( int 就賦值0,對象就賦值 null 等)路呜,在初始化階段才會進行具體賦值迷捧;而解析階段則可能是一個懶加載情況,有可能是在初始化后被其他對象進行調(diào)用才會將符號引用轉(zhuǎn)為直接引用胀葱。


類加載還有一個重要的考點就是類加載機制 漠秋,也就是所謂的雙親委派機制,即從下往上拋類的信息抵屿,優(yōu)先由上層負責加載庆锦,如果上層加載失敗,則往下拋轧葛,如果最底層的加載器也無法加載,則拋出 ClassNotFoundException 異常朝群;這個機制的作用就是為了防止核心類被第三方類進行調(diào)包操作,防止多個系統(tǒng)級別的 Class 生成誉帅。

然而,這個機制也挖了不少坑蚜锨,例如A類調(diào)用B類,則B類的加載得由加載A類的類加載器完成郭膛;但是 jdbc 核心類由 bootstrap類加載器 加載氛悬,而這個加載器只會加載lib/rt.jar而無法加載第三方的jar類,便會出現(xiàn)第三方數(shù)據(jù)庫廠商jar無法被動加載的情況棍现。
所謂的主動加載其實就是我們用戶通過 Class.forName() 進行類加載镜遣,被動加載則是無需我們通過編寫這類代碼進行該類的加載
這個時候就引入SPI 和線程上下文類加載器( Thread Context ClassLoader )來加載第三方的jar,所以為什么新版的 mysql 驅(qū)動包無需我們手動進行類加載也可以自動加載(舊版的沒有用上面提到的加載器)谎僻。一般來說這個線程上下文類加載器就是 Application-ClassLoader寓辱,所以可以直接加載,但是這種用法從某種意義上屬于打破雙親委派機制的一種情況秫筏,因為需要由啟動類加載器進行加載的類,由應用程序類加載器去進行加載了。

3. JVM內(nèi)存參數(shù)調(diào)優(yōu)

JVM內(nèi)存調(diào)優(yōu)主要表現(xiàn)在對JVM內(nèi)存參數(shù)的設(shè)定上鹅颊,通過設(shè)置符合生產(chǎn)情況來穩(wěn)定項目的運行墓造,而不是提高運行性能,我們主要看設(shè)置的最頻繁的參數(shù)列表觅闽,其余參數(shù)目前來說大部分內(nèi)存參數(shù)的默認情況可以基本符合線上需求

示例參數(shù) 描述
-Xms20m 堆初始值20M ,等同于-XX:InitalHeapSize=20m尸闸,默認為物理內(nèi)存的1/64
-Xmx20m 堆最大可用值20M ,等同于-XX:MaxHeapSize=20m苞尝,默認為物理內(nèi)存的1/4
-Xss1m 單個線程棧的大小宦芦,等同于-XX:ThreadStackSize,一般默認512k~1024k

  1. 我們盡量將堆的初始值和最大值設(shè)置一樣调卑,這樣做的好處是為了防止JVM在內(nèi)存不夠的時候向OS申請內(nèi)存以及GC回收后JVM釋放部分內(nèi)存導致的性能下降恬涧,在初始化的時候限制死JVM的大小,具體設(shè)置多大看具體的項目情況气破。如果經(jīng)常出現(xiàn)OOM或FULL GC,可以考慮是否為JVM堆設(shè)置的過小低匙,或者是否發(fā)生內(nèi)存泄漏碳锈。

  2. xss參數(shù)設(shè)置的越大,那么可創(chuàng)建的線程數(shù)量便越少强重,因為每個線程棧占用的空間越多贸人,導致可用的內(nèi)存越少;同時艺智,如果設(shè)置堆的內(nèi)存越大,可創(chuàng)建的線程也會變少十拣,因為線程不在堆內(nèi)存上創(chuàng)建,JVM只是創(chuàng)建了一個Thread對象泽西,線程在堆內(nèi)存之外的內(nèi)存上創(chuàng)建缰趋,由OS具體生成陕见,堆給的內(nèi)存越多糠溜,那么OS可使用的內(nèi)存越少。所以如果項目比較少用到遞歸或者深度較大的方法蜕着,那么這個值可以相對設(shè)置小一點红柱,以免出現(xiàn)無法創(chuàng)建線程的OOM。

總結(jié)

由于篇幅原因韧骗,本章節(jié)只是粗略概括目前JVM內(nèi)存區(qū)域劃分以及類加載的基本知識內(nèi)容以及基本的面試題零聚,如果讀者想要更進一步,可以通過閱讀相關(guān)書籍與博客來加深相應的技術(shù)深度政模。

接下來蚂会,我們回到最初的三個問題

1. JVM運行時數(shù)據(jù)區(qū)的內(nèi)存怎么進行劃分胁住?
2. JVM的類加載是怎么樣的彪见?
3. 如何針對JVM內(nèi)存參數(shù)進行調(diào)優(yōu)?

如果你們可以很流暢的回答這些問題枫慷,那么恭喜你浪规,該章節(jié)的內(nèi)容已經(jīng)全部掌握探孝,如果不行,希望可以回到對應問題講解的地方缸濒,或者對某個不了解的點進行額外的知識搜索,盡量用自己組織的語言回答這些問題斩跌。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末捞慌,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子袖订,更是在濱河造成了極大的恐慌嗅虏,老刑警劉巖皮服,帶你破解...
    沈念sama閱讀 218,284評論 6 506
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異硫眯,居然都是意外死亡蜀细,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,115評論 3 395
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來归斤,“玉大人脏里,你說我怎么就攤上這事》撸” “怎么了矾踱?”我有些...
    開封第一講書人閱讀 164,614評論 0 354
  • 文/不壞的土叔 我叫張陵呛讲,是天一觀的道長。 經(jīng)常有香客問我吗氏,道長,這世上最難降的妖魔是什么污尉? 我笑而不...
    開封第一講書人閱讀 58,671評論 1 293
  • 正文 為了忘掉前任坦袍,我火速辦了婚禮,結(jié)果婚禮上蛮放,老公的妹妹穿的比我還像新娘奠宜。我一直安慰自己,他們只是感情好娩嚼,可當我...
    茶點故事閱讀 67,699評論 6 392
  • 文/花漫 我一把揭開白布岳悟。 她就那樣靜靜地躺著泼差,像睡著了一般堆缘。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上录平,一...
    開封第一講書人閱讀 51,562評論 1 305
  • 那天斗这,我揣著相機與錄音啤斗,去河邊找鬼。 笑死燃逻,一個胖子當著我的面吹牛臂痕,可吹牛的內(nèi)容都是我干的伯襟。 我是一名探鬼主播,決...
    沈念sama閱讀 40,309評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼姆怪,長吁一口氣:“原來是場噩夢啊……” “哼稽揭!你這毒婦竟也來了肥卡?” 一聲冷哼從身側(cè)響起步鉴,我...
    開封第一講書人閱讀 39,223評論 0 276
  • 序言:老撾萬榮一對情侶失蹤氛琢,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后骚勘,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體俏讹,經(jīng)...
    沈念sama閱讀 45,668評論 1 314
  • 正文 獨居荒郊野嶺守林人離奇死亡藐石,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,859評論 3 336
  • 正文 我和宋清朗相戀三年于微,在試婚紗的時候發(fā)現(xiàn)自己被綠了青自。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片延窜。...
    茶點故事閱讀 39,981評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡荠藤,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出吻育,到底是詐尸還是另有隱情淤井,我是刑警寧澤币狠,帶...
    沈念sama閱讀 35,705評論 5 347
  • 正文 年R本政府宣布漩绵,位于F島的核電站渐行,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏肴沫。R本人自食惡果不足惜颤芬,卻給世界環(huán)境...
    茶點故事閱讀 41,310評論 3 330
  • 文/蒙蒙 一站蝠、第九天 我趴在偏房一處隱蔽的房頂上張望菱魔。 院中可真熱鬧吟孙,春花似錦杰妓、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,904評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽钩乍。三九已至,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間排作,已是汗流浹背妄痪。 一陣腳步聲響...
    開封第一講書人閱讀 33,023評論 1 270
  • 我被黑心中介騙來泰國打工衫生, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留罪针,地道東北人黄伊。 一個月前我還...
    沈念sama閱讀 48,146評論 3 370
  • 正文 我出身青樓墓阀,卻偏偏與公主長得像拓轻,于是被迫代替她去往敵國和親扶叉。 傳聞我的和親對象是個殘疾皇子辜梳,可洞房花燭夜當晚...
    茶點故事閱讀 44,933評論 2 355