Java虛擬機(jī)基礎(chǔ)知識

作者:@wsztrush
原文地址:WsztRush

寫在前面

之前老大讓做一些外包面試籍嘹,我的問題很簡單:

  1. 介紹一下工作中解決過比較有意思的問題慈鸠。
  2. HashMap使用中需要注意的點(diǎn)忿墅。

第一個問題主要是想了解一下對方項(xiàng)目經(jīng)驗(yàn)的含金量,第二個問題則是測試下是否知道一些細(xì)節(jié),比如HashMap是線程不安全的斥黑、用HashMap來做緩存的話可能導(dǎo)致內(nèi)存泄露等弟胀,自我感覺問題設(shè)計(jì)的還可以:D~ 但是看了其他同事的題目就淚崩了:

  1. 設(shè)計(jì)模式XXX
  2. 垃圾回收XXX

擦楷力,怎么感覺這個問題我也不會。孵户。萧朝。

虛擬機(jī)給人的感覺像是操作系統(tǒng)、編譯器:非常高大上夏哭。但是Java程序就跑在上面检柬,遇到問題還得去排查,性能不行還得去優(yōu)化竖配,基礎(chǔ)的知識還是需要的何址!

內(nèi)存管理

Java虛擬機(jī)在執(zhí)行的過程中會把它所管理的內(nèi)存劃分為若干個不同的數(shù)據(jù)區(qū)域,大致如下:

各部分的功能如下:

在內(nèi)存管理部分比較大的一塊內(nèi)容是GC(垃圾回收)进胯,所謂垃圾回收就是將垃圾占用的內(nèi)存回收掉用爪。那么第一個問題:什么是垃圾?

  1. 引用計(jì)數(shù)算法:被引用次數(shù)為0的對象胁镐。
  2. 根搜索算法:從GC Roots沿著引用找不到的對象偎血。

這里都提到了引用,在JDK 1.2之后Java就已經(jīng)對引用的概念進(jìn)行了擴(kuò)充盯漂,那么第二個問題:有哪些類型的引用烁巫?

  • 強(qiáng)引用:Object o = new Object()這種都是強(qiáng)引用。
  • 軟引用:還有用但非必須的宠能,在OOM之前被回收亚隙。
  • 弱引用:更弱的引用,在下次GC的時(shí)候被回收违崇。
  • 虛引用:最弱的阿弃,唯一的作用是在對象被回收的時(shí)候可以收到通知诊霹。

這里只有強(qiáng)引用才能對對象的生命周期造成影響。在虛擬機(jī)發(fā)展的過程中進(jìn)化出不少垃圾回收算法渣淳,比如:

  • 標(biāo)記-清除算法
  • 復(fù)制算法
  • 標(biāo)記-整理算法
  • 分代收集算法

在實(shí)際中用到的回收器都是這幾種算法的組合脾还,比如從VisualVM中看到的內(nèi)存是這樣的(需要明白各部分都是怎樣互相配合的):

整體上來看是分代收集算法,而S0入愧、S1這兩部分可以看做是標(biāo)記-整理算法鄙漏。那么第三個問題:常見的CMS垃圾回收器的執(zhí)行流程是怎樣的?

  1. 初始標(biāo)記:GC Roots直接關(guān)聯(lián)的對象棺蛛。
  2. 并發(fā)標(biāo)記:Root Tracing怔蚌。
  3. 重新標(biāo)記:修復(fù)由于程序運(yùn)行導(dǎo)致標(biāo)記產(chǎn)生變動。
  4. 并發(fā)清除

具體如下圖所示:

可以看到只有在初始標(biāo)記和重新標(biāo)記的時(shí)候才需要Stop The World旁赊,其他都是和用戶線程一起執(zhí)行桦踊,不要以為這就完美了,并行執(zhí)行的過程會消耗掉一些CPU資源终畅。

代碼執(zhí)行

把Java源碼丟給JVM肯定是不能執(zhí)行的籍胯,需要先用javac編譯成class文件才行,那么第一個問題:class文件的結(jié)構(gòu)是怎樣的离福?

  • 常量池
  • 訪問標(biāo)志
  • 類索引杖狼、父類索引和接口索引
  • 字段表
  • 方法表
  • 屬性表

虛擬機(jī)規(guī)范并沒有規(guī)定在什么時(shí)候要加載類,但是規(guī)定了在遇到new妖爷、反射本刽、父類、Main的時(shí)候需要初始化完成赠涮。整個類的生命周期如下:

在虛擬機(jī)中通過ClassLoader來進(jìn)行類的加載,這地方需要明白:

  • 兩個類是否相同暗挑,除了類名外還需要判斷ClassLoader是否相同笋除。
  • 雙親委派模式并不是一個強(qiáng)制約束。

在類加載完成之后就可以開始執(zhí)行了炸裆,和線程運(yùn)轉(zhuǎn)相關(guān)的東西都放在棧幀中垃它,其結(jié)構(gòu)如下:

執(zhí)行中具體調(diào)用哪個方法是個頭疼的問題,需要處理:

  • 靜態(tài)分派:相同名稱烹看、不同參數(shù)類型的方法国拇。
  • 動態(tài)分派:繼承中復(fù)寫的方法。

字節(jié)碼中的指令都是基于棧的操作惯殊,比如要完成1+1這樣的計(jì)算酱吝,對應(yīng)的指令如下:

iconst_1 // 將常量1壓入棧
iconst_1
iadd // 把棧頂?shù)膬蓚€值相加并出棧,然后把結(jié)果放回棧
istore_0 // 將棧頂?shù)闹捣诺骄植孔兞勘淼?個Solt

解釋執(zhí)行的好處是下載后啟動速度快土思,但是確定也非常明顯:運(yùn)行速度慢务热。JIT正是用來解決這個問題的忆嗜,能夠?qū)?strong>多次調(diào)用的方法、多次執(zhí)行的循環(huán)體編譯成本地代碼崎岂。

優(yōu)化是個很好玩的題目捆毫,記得在參加一次變成比賽的時(shí)候用gcc -O3編譯之后的代碼把printf()都沒輸出了。冲甘。在JIT中比較常見的優(yōu)化手段有:

程序執(zhí)行一定會涉及到內(nèi)存操作绩卤,在Java中定義了八種操作來完成:

這里有必要講一下volatile的作用,在使用到的時(shí)候能明白下面兩條即可:

  • 保證變量對所有線程是可見的江醇。
  • 禁止指令重排優(yōu)化濒憋。

如果Java中所有的操作都需要程序員來控制的話,會有大量的重復(fù)代碼嫁审,而且寫起來很累跋炕,那么我們可以通過先行發(fā)生原則來判斷并行的兩個操作是否存在沖突:

  • 程序次序規(guī)則:單線程內(nèi)按照程序書寫順序。
  • 管程鎖定規(guī)則:unlock必須在lock之前律适。
  • volatile變量規(guī)則:寫操作先行發(fā)生于讀操作辐烂。
  • 線程啟動規(guī)則:Thread.start()先于線程的其他任意方法。
  • 線程終止規(guī)則:線程中所有的操作都先于對此線程的終止檢測捂贿。
  • 線程中斷規(guī)則:interrupt()先于中斷檢測纠修。
  • 對象終結(jié)規(guī)則:對象的初始化完成先于它的finalize()方法。
  • 傳遞規(guī)則:如果A先于B厂僧、B先于C扣草,那么A先于C。

Thread的底層實(shí)現(xiàn)還是比較麻煩的颜屠,但是最起碼應(yīng)該知道Thread的狀態(tài)是如何進(jìn)行轉(zhuǎn)換:

最后辰妙,常見的同步方式是synchronized或者aqs的各種實(shí)現(xiàn),這里就不講了甫窟,因?yàn)槊總€都足夠?qū)懸淮笃?/p>

附: JVM常用的參數(shù)和工具

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末密浑,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子粗井,更是在濱河造成了極大的恐慌尔破,老刑警劉巖,帶你破解...
    沈念sama閱讀 219,188評論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件浇衬,死亡現(xiàn)場離奇詭異懒构,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)耘擂,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,464評論 3 395
  • 文/潘曉璐 我一進(jìn)店門胆剧,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人醉冤,你說我怎么就攤上這事赞赖」龆洌” “怎么了?”我有些...
    開封第一講書人閱讀 165,562評論 0 356
  • 文/不壞的土叔 我叫張陵前域,是天一觀的道長辕近。 經(jīng)常有香客問我,道長匿垄,這世上最難降的妖魔是什么移宅? 我笑而不...
    開封第一講書人閱讀 58,893評論 1 295
  • 正文 為了忘掉前任,我火速辦了婚禮椿疗,結(jié)果婚禮上漏峰,老公的妹妹穿的比我還像新娘。我一直安慰自己届榄,他們只是感情好浅乔,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,917評論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著铝条,像睡著了一般靖苇。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上班缰,一...
    開封第一講書人閱讀 51,708評論 1 305
  • 那天贤壁,我揣著相機(jī)與錄音,去河邊找鬼埠忘。 笑死脾拆,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的莹妒。 我是一名探鬼主播名船,決...
    沈念sama閱讀 40,430評論 3 420
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼旨怠!你這毒婦竟也來了渠驼?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,342評論 0 276
  • 序言:老撾萬榮一對情侶失蹤运吓,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后疯趟,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體拘哨,經(jīng)...
    沈念sama閱讀 45,801評論 1 317
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,976評論 3 337
  • 正文 我和宋清朗相戀三年信峻,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了倦青。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 40,115評論 1 351
  • 序言:一個原本活蹦亂跳的男人離奇死亡盹舞,死狀恐怖产镐,靈堂內(nèi)的尸體忽然破棺而出隘庄,到底是詐尸還是另有隱情,我是刑警寧澤癣亚,帶...
    沈念sama閱讀 35,804評論 5 346
  • 正文 年R本政府宣布丑掺,位于F島的核電站,受9級特大地震影響述雾,放射性物質(zhì)發(fā)生泄漏街州。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,458評論 3 331
  • 文/蒙蒙 一玻孟、第九天 我趴在偏房一處隱蔽的房頂上張望唆缴。 院中可真熱鬧,春花似錦黍翎、人聲如沸面徽。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,008評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽趟紊。三九已至,卻和暖如春旺聚,著一層夾襖步出監(jiān)牢的瞬間织阳,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,135評論 1 272
  • 我被黑心中介騙來泰國打工砰粹, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留唧躲,地道東北人。 一個月前我還...
    沈念sama閱讀 48,365評論 3 373
  • 正文 我出身青樓碱璃,卻偏偏與公主長得像弄痹,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子嵌器,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,055評論 2 355

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