阿里、美团、Oracle凭这套题不知道刷了多少人
一、為什么Java被稱作是“平臺無關的編程語言”?
程序員所需要的知識體系
前言
有代碼的地方,就有江湖。
程序員,就是“一人,一鍵,二機”行走其間的孤獨劍客。在江湖中狂蕩,必然要練就絕世武功,則需要內外兼備: 精妙的招式,加之深厚的內功。 武功的基礎是內功,一個內功低的人招式再奇妙,也打不過一個內功深厚之人。同樣兩者也是相輔相成,內功深厚,原來的一招一式威力也會倍增。
對于開發者來說,其道理也是一樣。 流行的框架越來越多,封裝也越來越完善,各種框架可以搞定一切。
初級程序員只要熟悉基本的使用方法,幾乎不用關注底層的實現,便可以快速地開發上線。
但對于想要進階的你來說,更要注重內功,比如算法、設計模式、底層原理等等。 只有把基礎打扎實,才能知其然知其所以然,出現Bug能快速發現問題本質。
作者鄭雨迪在Java虛擬機性能優化方面有著多年的研究,深知JVM是內功心法很重要的一塊。上線出現性能問題,JVM調優更是不可回避的事情。但又因Java虛擬機封裝得太好,讓我們幾乎感覺不到它的存在,可 學習Java虛擬機對于高級程序員來說,其重要性是不言而喻的。
我司在面試高級開發的時候,JVM相關知識也必定是考核的標準之一。
下面這篇文章集錦了阿里、美團、Oracle等大廠的JVM考點,你看看是否會能答得上來?
根據鄭雨迪專欄《深入拆解Java虛擬機》的內容,我挑選了幾個問題進行解答,希望能對大家面試起到幫助。
1、Java代碼是怎么運行的?
這個問題可以分三塊來回答:
- 為什么Java要在虛擬機里運行?
- Java虛擬機具體是怎樣運行Java字節碼的?
- Java虛擬機的運行效率究竟是怎么樣的?
Java之所以要在虛擬機中運行,是因為它提供了可移植性。一旦Java代碼被編譯為Java字節碼,便可以在不同平臺上的Java虛擬機實現上運行。此外,虛擬機還提供了一個代碼托管的環境,代替我們處理部分冗長而且容易出錯的事務,例如內存管理。
Java虛擬機將運行時內存區域劃分為五個部分,分別為方法區、堆、PC寄存器、Java方法棧和本地方法棧。Java程序編譯而成的class文件,需要先加載至方法區中,方能在Java虛擬機中運行。
為了提高運行效率,標準JDK中的HotSpot虛擬機采用的是一種混合執行的策略。首先,它會解釋執行Java字節碼,然后會將其中反復執行的熱點代碼,以方法為單位進行即時編譯,翻譯成機器碼后直接運行在底層硬件之上。HotSpot裝載了多個不同的即時編譯器,以便在編譯時間和生成代碼的執行效率之間做取舍。
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邏輯。
4、垃圾回收的基礎思想是什么?
目前JVM的主流垃圾回收器采取的都是可達性分析算法 。該算法的實質是將一系列被稱為GC Roots的對象作為初始的存活對象合集,然后從該合集出發探索所有能夠被該集合引用到的對象,并 標記 為存活對象。當標記階段結束之后,未被標記到的對象便是可以 清除 的。
傳統的垃圾回收算法在標記、清除過程中需要中止其他應用線程,即所謂的Stop-The-World。新型的垃圾回收算法,如CMS、G1以及ZGC,盡可能地實現 并發 標記、清除,從而讓Stop-The-World的時間長度可控。
垃圾回收的另一基礎思想則是 分代回收 。 JVM會將新生成的對象劃為新生代,而將在多次垃圾回收中存活下來的對象劃為老年代。JVM會為不同的分代設置不同的回收算法,從而達到新生代多收集、快收集,老年代少收集、全收集的目標。
5、JVM垃圾回收算法
- 標記-清除算法: 首先標記出所有需要回收的對象,在標記完成后統一回收所有被標記的對象。
- 復制算法: 將可用內存按容量劃分為大小相等的兩塊,每次只使用其中的一塊。當一塊內存用完了,將還存另外一塊上面,然后在把已使用過的內存空間一次清理掉。
- 標記-整理算法: 標記過程與“標記-清除”算法一樣,但后續步驟不是直接對可回收對象進行清理,而是讓所一端移動,然后直接清理掉端邊界以外的內存。
- 分代收集算法: 一般是把Java堆分為新生代和老年代,根據各個年代的特點采用最適當的收集算法。新生代都發現有大批對象死去,選用復制算法。老年代中因為對象存活率高,必須使用“標記-清理”或“標記-整理”算法來進行回收。
轉載于:https://juejin.im/post/5d05eae26fb9a07ef56234cb
總結
以上是生活随笔為你收集整理的阿里、美团、Oracle凭这套题不知道刷了多少人的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 无线局域网的部署
- 下一篇: Windows安装hadoop