如何應對阿里、美團、Oracle等大廠的面試刁難?

有代碼的地方,就有江湖。

程序員,就是「一人,一鍵,二機」行走其間的孤獨劍客。在江湖中狂蕩,必然要練就絕世武功,則須要內外兼備: 精妙的招式,加之深厚的內功。 武功的基礎是內功,一個內功低的人招式再奇妙,也打不過一個內功深厚之人。一樣二者也是相輔相成,內功深厚,原來的一招一式威力也會倍增。

對於開發者來講,其道理也是同樣。 流行的框架愈來愈多,封裝也愈來愈完善,各類框架能夠搞定一切。

初級程序員只要熟悉基本的使用方法,幾乎不用關注底層的實現,即可以快速地開發上線。
但對於想要進階的你來講,更要注重內功,好比算法、設計模式、底層原理等等。 只有把基礎打紮實,才能知其然知其因此然,出現Bug能快速發現問題本質。

JVM是內功心法很重要的一塊。上線出現性能問題,JVM調優更是不可迴避的事情。但又因Java虛擬機封裝得太好,讓咱們幾乎感受不到它的存在,可 學習Java虛擬機對於高級程序員來講,其重要性是不言而喻的。

我司在面試高級開發的時候,JVM相關知識也一定是考覈的標準之一。

下面這篇文章集錦了阿里、美團、Oracle等大廠的JVM考點,你看看是否會能答得上來?

  1. 爲何Java被稱做是「平臺無關的編程語言」?
  2. Java代碼是怎麼運行的?
  3. Java虛擬機是如何加載Java類的?
  4. 如何監控和診斷JVM堆內和堆外內存使用?
  5. 如何理解JVM內置的編譯或GC日誌?
  6. JVM的永久代中會發生垃圾回收麼?
  7. Java中的兩種異常類型是什麼?他們有什麼區別?
  8. JVM是如何實現同步的?
  9. Java內在模型是什麼?
  10. 即時編譯器有哪些優化? 在什麼狀況下重複讀寫操做會被優化?
  11. 什麼樣的垃圾才被回收? 何時會致使垃圾回收?
  12. 如何利用字節碼注入爲已有代碼加料?

我挑選了幾個問題進行解答,但願能對你們面試起到幫助。順便提一句:更多精彩JVM以及Java相關技術講解能夠加羣:1017599436獲取,包括電子書,PDF文檔以及視頻精講。


一、Java代碼是怎麼運行的?

這個問題能夠分三塊來回答:
  • 爲何Java要在虛擬機裏運行?
  • Java虛擬機具體是怎樣運行Java字節碼的?
  • Java虛擬機的運行效率到底是怎麼樣的?

Java之因此要在虛擬機中運行,是由於它提供了可移植性。一旦Java代碼被編譯爲Java字節碼,即可以在不一樣平臺上的Java虛擬機實現上運行。此外,虛擬機還提供了一個代碼託管的環境,代替咱們處理部分冗長並且容易出錯的事務,例如內存管理。

Java虛擬機將運行時內存區域劃分爲五個部分,分別爲方法區、堆、PC寄存器、Java方法棧和本地方法棧。Java程序編譯而成的class文件,須要先加載至方法區中,方能在Java虛擬機中運行。

爲了提升運行效率,標準JDK中的HotSpot虛擬機採用的是一種混合執行的策略。首先,它會解釋執行Java字節碼,而後會將其中反覆執行的熱點代碼,以方法爲單位進行即時編譯,翻譯成機器碼後直接運行在底層硬件之上。HotSpot裝載了多個不一樣的即時編譯器,以便在編譯時間和生成代碼的執行效率之間作取捨。

二、Java虛擬機是如何加載Java類的?

Java虛擬機將字節流轉化爲Java類的過程,可分爲加載、連接以及初始化三大步驟。也能夠用蓋房子來類比Java虛擬機中的類加載。

  • 加載是指查找字節流,而且據此建立類的過程。 以蓋房子爲例,村裏的Tony要蓋個房子,那麼按照流程他得先找個建築師,跟他說想要設計一個房型,好比說「一房、一廳、四衛」。這裏的房型至關於類,而建築師,就至關於類加載器。村裏有許多建築師,他們等級森嚴,但有着共同的祖師爺,叫啓動類加載器(boot class loader)。
加載須要藉助類加載器,在Java虛擬機中,類加載器使用了雙親委派模型,即接收到加載請求時,會先將請求轉發給父類加載器。

  • 連接,是指將建立成的類合併至Java虛擬機中,使之可以執行的過程。 連接還分驗證、準備和解析三個階段。其中,解析階段爲非必須的。

  • 初始化,則是爲標記爲常量值的字段賦值,以及執行 <clinit> 方法的過程。 類的初始化僅會被執行一次,這個特性被用來實現單例的延遲初始化。這放在咱們蓋房子的例子中就是,只有當房子裝修事後,Tony才能真正地住進去。


三、異常捕獲是如何實現的?


在編譯生成的Java字節碼中,每一個方法都附帶一個異常表。異常表中的每一行均定義了一條異常執行路徑,其中包括規定捕獲範圍的起始字節碼索引、終止(不包含)字節碼索引,異常處理代碼的起始字節碼索引,以及所捕獲的異常類型。

當程序觸發異常時,JVM會從上至下遍歷異常表中的全部條目。當觸發異常的字節碼的索引值在某行異常表條目的捕獲範圍內,JVM會判斷所拋出的異常和該條目想要捕獲的異常是否匹配。若是匹配,JVM會將控制流轉移至該條目所指向的異常處理代碼。

上述異常捕獲機制還被用於finally從句的實現。一般,Java程序的編譯器javac會複製多份finally代碼塊,放置於生成的Java字節碼之中,而後經過生成多行異常表條目,來實現完整的finally邏輯。

四、垃圾回收的基礎思想是什麼?


目前JVM的主流垃圾回收器採起的都是可達性分析算法 。該算法的實質是將一系列被稱爲GC Roots的對象做爲初始的存活對象合集,而後從該合集出發探索全部可以被該集合引用到的對象,並 標記 爲存活對象。當標記階段結束以後,未被標記到的對象即是能夠 清除 的。

傳統的垃圾回收算法在標記、清除過程當中須要停止其餘應用線程,即所謂的Stop-The-World。新型的垃圾回收算法,如CMS、G1以及ZGC,儘量地實現 併發 標記、清除,從而讓Stop-The-World的時間長度可控。垃圾回收的另外一基礎思想則是 分代回收 。 JVM會將新生成的對象劃爲新生代,而將在屢次垃圾回收中存活下來的對象劃爲老年代。JVM會爲不一樣的分代設置不一樣的回收算法,從而達到新生代多收集、快收集,老年代少收集、全收集的目標。

五、JVM垃圾回收算法

  • 標記-清除算法: 首先標記出全部須要回收的對象,在標記完成後統一回收全部被標記的對象。
  • 複製算法: 將可用內存按容量劃分爲大小相等的兩塊,每次只使用其中的一塊。當一塊內存用完了,將還存另一塊上面,而後在把已使用過的內存空間一次清理掉。
  • 標記-整理算法: 標記過程與「標記-清除」算法同樣,但後續步驟不是直接對可回收對象進行清理,而是讓所一端移動,而後直接清理掉端邊界之外的內存。
  • 分代收集算法: 通常是把Java堆分爲新生代和老年代,根據各個年代的特色採用最適當的收集算法。新生代都發現有大批對象死去,選用複製算法。老年代中由於對象存活率高,必須使用「標記-清理」或「標記-整理」算法來進行回收。

…… 更多精彩JVM以及Java相關技術講解能夠加羣:1017599436獲取,包括電子書,PDF文檔以及視頻精講。



相關文章
相關標籤/搜索