下面這篇文章匯集了阿里、美團(tuán)、Oracle等大廠的JVM考點(diǎn),你是否能回答得上來?
什么是Java虛擬機(jī)?為什么Java被稱作是“平臺(tái)無關(guān)的編程語言”?
Java代碼是怎么運(yùn)行的?
Java虛擬機(jī)是如何加載Java類的?
JVM運(yùn)行內(nèi)存的分類
如何監(jiān)控和診斷JVM堆內(nèi)和堆外內(nèi)存使用?
Java四引用是什么?
如何理解JVM內(nèi)置的編譯或GC日志?
JVM的永久代中會(huì)發(fā)生垃圾回收么?
Java中的兩種異常類型是什么?他們有什么區(qū)別?
JVM是如何實(shí)現(xiàn)同步的?
Java內(nèi)在模型是什么?
即使編譯器有哪些優(yōu)化?
在什么情況下重復(fù)讀寫操作會(huì)被優(yōu)化?
什么樣的垃圾才被回收?
什么時(shí)候會(huì)導(dǎo)致垃圾回收?
如何利用JFR和JMC監(jiān)控Java程序?
如何利用UnsafeAPI繞開JVM的控制?
如何利用字節(jié)碼注入為已有代碼加料?
1、什么是Java虛擬機(jī)?為什么Java被稱作是“平臺(tái)無關(guān)的編程語言”?
Java虛擬機(jī)是一個(gè)可以執(zhí)行Java字節(jié)碼的虛擬機(jī)進(jìn)程。Java源文件被編譯成能被Java虛擬機(jī)執(zhí)行的字節(jié)碼文件。
Java被設(shè)計(jì)成允許應(yīng)用程序可以運(yùn)行在任意的平臺(tái),而不需要程序員為每一個(gè)平臺(tái)單獨(dú)重寫或者是重新編譯。Java虛擬機(jī)讓這個(gè)變?yōu)榭赡?,因?yàn)樗赖讓佑布脚_(tái)的指令長度和其他特性。
2、Java代碼是怎么運(yùn)行的?
這個(gè)問題可以分三塊來回答:
為什么Java要在虛擬機(jī)里運(yùn)行?
Java虛擬機(jī)具體是怎樣運(yùn)行Java字節(jié)碼的?
Java虛擬機(jī)的運(yùn)行效率究竟是怎么樣的?
Java之所以要在虛擬機(jī)中運(yùn)行,是因?yàn)樗峁┝丝梢浦残?。一旦Java代碼被編譯為Java字節(jié)碼,便可以在不同平臺(tái)上的Java虛擬機(jī)實(shí)現(xiàn)上運(yùn)行。此外,虛擬機(jī)還提供了一個(gè)代碼托管的環(huán)境,代替我們處理部分冗長而且容易出錯(cuò)的事務(wù),例如內(nèi)存管理。
Java虛擬機(jī)將運(yùn)行時(shí)內(nèi)存區(qū)域劃分為五個(gè)部分,分別為方法區(qū)、堆、PC寄存器、Java方法棧和本地方法棧。Java程序編譯而成的class文件,需要先加載至方法區(qū)中,方能在Java虛擬機(jī)中運(yùn)行。
為了提高運(yùn)行效率,標(biāo)準(zhǔn)JDK中的HotSpot虛擬機(jī)采用的是一種混合執(zhí)行的策略。首先,它會(huì)解釋執(zhí)行Java字節(jié)碼,然后會(huì)將其中反復(fù)執(zhí)行的熱點(diǎn)代碼,以方法為單位進(jìn)行即時(shí)編譯,翻譯成機(jī)器碼后直接運(yùn)行在底層硬件之上。HotSpot裝載了多個(gè)不同的即時(shí)編譯器,以便在編譯時(shí)間和生成代碼的執(zhí)行效率之間做取舍。
3、Java虛擬機(jī)是如何加載Java類的?
Java虛擬機(jī)將字節(jié)流轉(zhuǎn)化為Java類的過程,可分為加載、鏈接以及初始化三大步驟。也可以用蓋房子來類比Java虛擬機(jī)中的類加載。
加載是指查找字節(jié)流,并且據(jù)此創(chuàng)建類的過程。以蓋房子為例,村里的Tony要蓋個(gè)房子,那么按照流程他得先找個(gè)建筑師,跟他說想要設(shè)計(jì)一個(gè)房型,比如說“一房、一廳、四衛(wèi)”。這里的房型相當(dāng)于類,而建筑師,就相當(dāng)于類加載器。村里有許多建筑師,他們等級(jí)森嚴(yán),但有著共同的祖師爺,叫啟動(dòng)類加載器(bootclassloader)。
加載需要借助類加載器,在Java虛擬機(jī)中,類加載器使用了雙親委派模型,即接收到加載請(qǐng)求時(shí),會(huì)先將請(qǐng)求轉(zhuǎn)發(fā)給父類加載器。
鏈接,是指將創(chuàng)建成的類合并至Java虛擬機(jī)中,使之能夠執(zhí)行的過程。鏈接還分驗(yàn)證、準(zhǔn)備和解析三個(gè)階段。其中,解析階段為非必須的。
初始化,則是為標(biāo)記為常量值的字段賦值,以及執(zhí)行
4、如何監(jiān)控和診斷JVM堆內(nèi)和堆外內(nèi)存使用?
了解JVM內(nèi)存的方法有很多,具體能力范圍也有區(qū)別,簡單總結(jié)如下:
可以使用綜合性的圖形化工具,如JConsole、VisualVM(注意,從OracleJDK9開始,VisualVM已經(jīng)不再包含在JDK安裝包中)等。這些工具具體使用起來相對(duì)比較直觀,直接連接到Java進(jìn)程,然后就可以在圖形化界面里掌握內(nèi)存使用情況。以JConsole為例,其內(nèi)存頁面可以顯示常見的堆內(nèi)存和各種堆外部分使用狀態(tài)。
也可以使用命令行工具進(jìn)行運(yùn)行時(shí)查詢,如jstat和jmap等工具都提供了一些選項(xiàng),可以查看堆、方法區(qū)等使用數(shù)據(jù)。
或者,也可以使用jmap等提供的命令,生成堆轉(zhuǎn)儲(chǔ)(HeapDump)文件,然后利用jhat或EclipseMAT等堆轉(zhuǎn)儲(chǔ)分析工具進(jìn)行詳細(xì)分析。
如果你使用的是Tomcat、Weblogic等JavaEE服務(wù)器,這些服務(wù)器同樣提供了內(nèi)存管理相關(guān)的功能。
另外,從某種程度上來說,GC日志等輸出,同樣包含著豐富的信息。
這里有一個(gè)相對(duì)特殊的部分,就是是堆外內(nèi)存中的直接內(nèi)存,前面的工具基本不適用,可以使用JDK自帶的NativeMemoryTracking(NMT)特性,它會(huì)從JVM本地內(nèi)存分配的角度進(jìn)行解讀。
5、JVM的永久代中會(huì)發(fā)生垃圾回收么?
垃圾回收不會(huì)發(fā)生在永久代,如果永久代滿了或者是超過了臨界值,會(huì)觸發(fā)完全垃圾回收(FullGC)。如果你仔細(xì)查看垃圾收集器的輸出信息,就會(huì)發(fā)現(xiàn)永久代也是被回收的。這就是為什么正確的永久代大小對(duì)避免FullGC是非常重要的原因。
(注:Java8中已經(jīng)移除了永久代,新加了一個(gè)叫做元數(shù)據(jù)區(qū)的native內(nèi)存區(qū))
6、在Java中,對(duì)象什么時(shí)候可以被垃圾回收?
當(dāng)對(duì)象對(duì)當(dāng)前使用這個(gè)對(duì)象的應(yīng)用程序變得不可觸及的時(shí)候,這個(gè)對(duì)象就可以被回收了。
7、Java中的兩種異常類型是什么?他們有什么區(qū)別?
Java中有兩種異常:受檢查的(checked)異常和不受檢查的(unchecked)異常。不受檢查的異常不需要在方法或者是構(gòu)造函數(shù)上聲明,就算方法或者是構(gòu)造函數(shù)的執(zhí)行可能會(huì)拋出這樣的異常,并且不受檢查的異??梢詡鞑サ椒椒ɑ蛘呤菢?gòu)造函數(shù)的外面。相反,受檢查的異常必須要用throws語句在方法或者是構(gòu)造函數(shù)上聲明。還有一些Java異常處理的小建議,我的專欄里都有提到。
8、JVM垃圾回收算法
標(biāo)記-清除算法:首先標(biāo)記出所有需要回收的對(duì)象,在標(biāo)記完成后統(tǒng)一回收所有被標(biāo)記的對(duì)象。
復(fù)制算法:將可用內(nèi)存按容量劃分為大小相等的兩塊,每次只使用其中的一塊。當(dāng)一塊內(nèi)存用完了,將還存另外一塊上面,然后在把已使用過的內(nèi)存空間一次清理掉。
標(biāo)記-整理算法:標(biāo)記過程與“標(biāo)記-清除”算法一樣,但后續(xù)步驟不是直接對(duì)可回收對(duì)象進(jìn)行清理,而是讓所一端移動(dòng),然后直接清理掉端邊界以外的內(nèi)存。
分代收集算法:一般是把Java堆分為新生代和老年代,根據(jù)各個(gè)年代的特點(diǎn)采用最適當(dāng)?shù)氖占惴?。新生代都發(fā)現(xiàn)有大批對(duì)象死去,選用復(fù)制算法。老年代中因?yàn)閷?duì)象存活率高,必須使用“標(biāo)記-清理”或“標(biāo)記-整理”算法來進(jìn)行回收。
以上就是北大青鳥長沙麓谷校區(qū)java培訓(xùn)機(jī)構(gòu)小編介紹的“JVM考點(diǎn):高級(jí)Java工程師面試必備”的內(nèi)容,希望對(duì)大家有幫助,如有疑問,請(qǐng)?jiān)诰€咨詢,有專業(yè)老師隨時(shí)為你服務(wù)。
相關(guān)推薦
面試題總結(jié)—高級(jí)Java工程師面試題
Java高級(jí)開發(fā)工程師面試題
秋招中高級(jí)Java面試題,10道詳解,死磕就對(duì)了
最新Java工程師面試題整理[社招篇]
大家都在收藏的中級(jí)常見Java工程師面試題
騰訊Java高級(jí)工程師高頻面試題