阿里、美团、Oracle等大厂的Java虚拟机面试题集锦
?
程序員,就是“一人,一鍵,二機”行走其間的孤獨劍客。在江湖中狂蕩,必然要練就絕世武功,則需要內外兼備:精妙的招式,加之深厚的內功。武功的基礎是內功,一個內功低的人招式再奇妙,也打不過一個內功深厚之人。同樣兩者也是相輔相成,內功深厚,原來的一招一式威力也會倍增。
?
對于開發者來說,其道理也是一樣。流行的框架越來越多,封裝也越來越完善,各種框架可以搞定一切。
初級程序員只要熟悉基本的使用方法,幾乎不用關注底層的實現,便可以快速地開發上線。
但對于想要進階的你來說,更要注重內功,比如算法、設計模式、底層原理等等。只有把基礎打扎實,才能知其然知其所以然,出現Bug能快速發現問題本質。
?
作者鄭雨迪在Java虛擬機性能優化方面有著多年的研究,深知JVM是內功心法很重要的一塊。上線出現性能問題,JVM調優更是不可回避的事情。但又因Java虛擬機封裝得太好,讓我們幾乎感覺不到它的存在,可學習Java虛擬機對于高級程序員來說,其重要性是不言而喻的。
我司在面試高級開發的時候,JVM相關知識也必定是考核的標準之一。
?
下面這篇文章集錦了阿里、美團、Oracle等大廠的JVM考點,你看看是否會能答得上來?
?
為什么Java被稱作是“平臺無關的編程語言”?
Java代碼是怎么運行的?
Java虛擬機是如何加載Java類的?
如何監控和診斷JVM堆內和堆外內存使用?
如何理解JVM內置的編譯或GC日志?
JVM的永久代中會發生垃圾回收么?
Java中的兩種異常類型是什么?他們有什么區別?
JVM是如何實現同步的?
Java內在模型是什么?
即時編譯器有哪些優化?在什么情況下重復讀寫操作會被優化?
什么樣的垃圾才被回收?什么時候會導致垃圾回收?
如何利用字節碼注入為已有代碼加料?
……
?
根據鄭雨迪專欄《深入拆解Java虛擬機》的內容,我挑選了幾個問題進行解答,希望能對大家面試起到幫助。順便提一句,《深入拆解Java虛擬機》已有?2.6?w+訂閱,今天也有特惠活動。
畫外音:
特意向極客時間運營小姐姐申請了福利,《深入拆解Java虛擬機》限時優惠79,原價99,僅限今天一天,有興趣的可以拉到后面。
?
1、Java代碼是怎么運行的?
?
這個問題可以分三塊來回答:
為什么Java要在虛擬機里運行?
Java虛擬機具體是怎樣運行Java字節碼的?
Java虛擬機的運行效率究竟是怎么樣的?
?
Java之所以要在虛擬機中運行,是因為它提供了可移植性。一旦Java代碼被編譯為Java字節碼,便可以在不同平臺上的Java虛擬機實現上運行。此外,虛擬機還提供了一個代碼托管的環境,代替我們處理部分冗長而且容易出錯的事務,例如內存管理。
?
Java虛擬機將運行時內存區域劃分為五個部分,分別為方法區、堆、PC寄存器、Java方法棧和本地方法棧。Java程序編譯而成的class文件,需要先加載至方法區中,方能在Java虛擬機中運行。
為了提高運行效率,標準JDK中的HotSpot虛擬機采用的是一種混合執行的策略。首先,它會解釋執行Java字節碼,然后會將其中反復執行的熱點代碼,以方法為單位進行即時編譯,翻譯成機器碼后直接運行在底層硬件之上。HotSpot裝載了多個不同的即時編譯器,以便在編譯時間和生成代碼的執行效率之間做取舍。
畫外音:
參考《深入拆解Java虛擬機》的文章:「Java代碼是怎么運行的?」
?
2、Java虛擬機是如何加載Java類的?
?
Java虛擬機將字節流轉化為Java類的過程,可分為加載、鏈接以及初始化三大步驟。也可以用蓋房子來類比Java虛擬機中的類加載。
?
加載是指查找字節流,并且據此創建類的過程。以蓋房子為例,村里的Tony要蓋個房子,那么按照流程他得先找個建筑師,跟他說想要設計一個房型,比如說“一房、一廳、四衛”。這里的房型相當于類,而建筑師,就相當于類加載器。村里有許多建筑師,他們等級森嚴,但有著共同的祖師爺,叫啟動類加載器(boot class loader)。
?
加載需要借助類加載器,在Java虛擬機中,類加載器使用了雙親委派模型,即接收到加載請求時,會先將請求轉發給父類加載器。
?
鏈接,是指將創建成的類合并至Java虛擬機中,使之能夠執行的過程。鏈接還分驗證、準備和解析三個階段。其中,解析階段為非必須的。
?
初始化,則是為標記為常量值的字段賦值,以及執行<clinit>方法的過程。類的初始化僅會被執行一次,這個特性被用來實現單例的延遲初始化。這放在我們蓋房子的例子中就是,只有當房子裝修過后,Tony才能真正地住進去。
?
3、異常捕獲是如何實現的?
在編譯生成的Java字節碼中,每個方法都附帶一個異常表。異常表中的每一行均定義了一條異常執行路徑,其中包括規定捕獲范圍的起始字節碼索引、終止(不包含)字節碼索引,異常處理代碼的起始字節碼索引,以及所捕獲的異常類型。
?
當程序觸發異常時,JVM會從上至下遍歷異常表中的所有條目。當觸發異常的字節碼的索引值在某行異常表條目的捕獲范圍內,JVM會判斷所拋出的異常和該條目想要捕獲的異常是否匹配。如果匹配,JVM會將控制流轉移至該條目所指向的異常處理代碼。
?
上述異常捕獲機制還被用于finally從句的實現。通常,Java程序的編譯器javac會復制多份finally代碼塊,放置于生成的Java字節碼之中,然后通過生成多行異常表條目,來實現完整的finally邏輯。
?
畫外音:
這個問題可以看下《深入拆解Java虛擬機》的「JVM是如何處理異常的?」,有做更加詳細的講解。
4、垃圾回收的基礎思想是什么?
?
目前JVM的主流垃圾回收器采取的都是可達性分析算法。該算法的實質是將一系列被稱為GC Roots的對象作為初始的存活對象合集,然后從該合集出發探索所有能夠被該集合引用到的對象,并標記為存活對象。當標記階段結束之后,未被標記到的對象便是可以清除的。
?
傳統的垃圾回收算法在標記、清除過程中需要中止其他應用線程,即所謂的Stop-The-World。新型的垃圾回收算法,如CMS、G1以及ZGC,盡可能地實現并發標記、清除,從而讓Stop-The-World的時間長度可控。
?
垃圾回收的另一基礎思想則是分代回收。JVM會將新生成的對象劃為新生代,而將在多次垃圾回收中存活下來的對象劃為老年代。JVM會為不同的分代設置不同的回收算法,從而達到新生代多收集、快收集,老年代少收集、全收集的目標。
畫外音:
這里可以看下《深入拆解Java虛擬機》的「?垃圾回收(上)」這篇文章,有做更加詳細的講解。
?
5、JVM垃圾回收算法
標記-清除算法:首先標記出所有需要回收的對象,在標記完成后統一回收所有被標記的對象。
復制算法:將可用內存按容量劃分為大小相等的兩塊,每次只使用其中的一塊。當一塊內存用完了,將還存另外一塊上面,然后在把已使用過的內存空間一次清理掉。
標記-整理算法:標記過程與“標記-清除”算法一樣,但后續步驟不是直接對可回收對象進行清理,而是讓所一端移動,然后直接清理掉端邊界以外的內存。
分代收集算法:一般是把Java堆分為新生代和老年代,根據各個年代的特點采用最適當的收集算法。新生代都發現有大批對象死去,選用復制算法。老年代中因為對象存活率高,必須使用“標記-清理”或“標記-整理”算法來進行回收。
?
……更多精彩JVM講解,推薦訂閱他的專欄《深入拆解Java虛擬機》,手把手帶你掌握JVM,打通Java最底層。
先簡單介紹下作者:鄭雨迪,?Oracle Labs 高級研究員,主要負責研究如何通過程序分析技術以及動態編譯技術讓程序語言跑得更快。他也是 Graal 編譯器的核心開發者之一,同時在為 HotSpot 虛擬機項目“添磚加瓦”。
可以說,在JVM領域,雨迪確實有著極深的研究經驗,這樣子的牛人能出來開課,真的是難得。
《深入拆解Java虛擬機》這個專欄訂閱量一直穩居極客時間 top 5,現在已經?2.6?w+訂閱。
雨迪從底層出發,通過揭秘 Java 虛擬機的工作原理及運行機制,掌握診斷手法和題調優方式。通過這個專欄的學習,你將了解如何編寫高效的代碼,如何對 Bug 達到最優處理,以及如何針對自己的應用調整虛擬機的運營參數。
今兒特意刷臉給大家要了一個限時?24 小時的優惠福利,限時優惠只要 79 元,原價 99 元,立省 20。
這個專欄除了內容硬核外,互動和反饋也是非常吸引人的兩個點。換句接地氣的話說:“就是找到組織的感覺”。
1、每篇文章作者都會留下一個思考題,幫助大家更好吸收知識。
舉個例子,在「第 6 篇 | JVM 是如何處理異常的?」中,作者講解了 Java 虛擬機異常處理的機制,并留下了思考題:
2、在留言區,你能看到大家各種各樣的解題思路,其中有的你可能會意想不到,可以說,在留言區你也能學到很多。鄭雨迪也會留言回復,解答大家提出的問題,或者給予及時反饋。
下面給大家截了部分讀者評價,你可以參考。
可以點擊看大圖
再強調一遍,《深入拆解Java虛擬機》僅限今天優惠 79,已有超過?2.5?w人加入學習,想認真進階 Java 的同學,請抓緊搭上這趟福利車。
???
優惠僅今天一天
限時優惠 79,原價 99
一場電影的價格
跟著 Oracle 大佬系統掌握 Java 虛擬機!
點擊「閱讀原文」,免費試看!
總結
以上是生活随笔為你收集整理的阿里、美团、Oracle等大厂的Java虚拟机面试题集锦的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 下一个母亲节
- 下一篇: C语言的进制转换以及算法实现