想漲薪?掌握這套JVM核心知識,月薪不超過18K直接考慮換工作吧!

應粉絲強烈要求,除了面試經驗,還要霸哥多分享一些常見的面試技術點。

剛好前段時間得到了一份關於Java的核心面試知識點的PDF文件,經過整理,然後現在拆分成專題進行分享。

爲了照顧到基礎相對比較薄弱的朋友,前兩篇文章已經講完了:

·《Java基礎核心知識點》

·《Java集合核心知識點》

按照排期,這篇該介紹JVM相關核心面試知識點,如果說,Java基礎和集合是進入Java開發的基石,那麼JVM則是打開進一步打開Java開發大門的鑰匙。

下面這套JVM知識能夠掌握下來,月薪18K完全沒問題,霸哥這裏所說的不是精通,能夠精通這套JVM體系,當然自會更高。

**注:**整體JVM知識點的數量相對於前兩個知識點會比較多,爲了防止文章過於冗長,霸哥這邊將只詳細分享部分知識點,其它知識點可通過後臺簡信【Java】獲取免費領取方式!

JVM核心知識點

  • 線程
  • JVM內存區域
  • JVM運行時內存
  • 垃圾回收與算法
  • Java四種應用類型
  • GC分代收集算法VS分區收集算法
  • GC垃圾收集器
  • Java IO/NIO
  • JVM類加載機制

更多高清完整大圖,PDF資料,技術視頻,後臺私信【Java】獲取免費領取方式!

私信【Java】獲取高清完整大圖

基本概念:

JVM 是可運行Java代碼的假想計算機 ,包括一套字節碼指令集、一組寄存器、一個棧、一個垃圾回收,堆和一個存儲方法域。JVM 是運行在操作系統之上的,它與硬件沒有直接的交互。

運行過程:

我們都知道 Java 源文件,通過編譯器,能夠生產相應的**.Class**文件,也就是字節碼文件,而字節碼文件又通過 Java 虛擬機中的解釋器,編譯成特定機器上的機器碼 。

也就是如下:

① Java 源文件—->編譯器—->字節碼文件

② 字節碼文件—->JVM—->機器碼

每一種平臺的解釋器是不同的,但是實現的虛擬機是相同的,這也就是 Java 爲什麼能夠跨平臺的原因了,當一個程序從開始運行,這時虛擬機就開始實例化了,多個程序啓動就會存在多個虛擬機實例。程序退出或者關閉,則虛擬機實例消亡,多個虛擬機實例之間數據不能共享。


線程

這裏所說的線程指程序執行過程中的一個線程實體。JVM 允許一個應用併發執行多個線程。**Hotspot JVM 中的 Java 線程與原生操作系統線程有直接的映射關係。**當線程本地存儲、緩衝區分配、同步對象、棧、程序計數器等準備好以後,就會創建一個操作系統原生線程。Java 線程結束,原生線程隨之被回收。操作系統負責調度所有線程,並把它們分配到任何可用的 CPU 上。當原生線程初始化完畢,就會調用 Java 線程的 run() 方法。當線程結束時,會釋放原生線程和 Java 線程的所有資源。

Hotspot JVM 後臺運行的系統線程主要有下面幾個:


JVM 內存區域

JVM 內存區域主要分爲線程私有區域【程序計數器、虛擬機棧、本地方法區】、線程共享區域【JAVA 堆、方法區】、直接內存。

線程私有數據區域生命週期與線程相同, 依賴用戶線程的啓動/結束 而 創建/銷燬(在 HotspotVM 內, 每個線程都與操作系統的本地線程直接映射, 因此這部分內存區域的存/否跟隨本地線程的生/死對應)。

線程共享區域隨虛擬機的啓動/關閉而創建/銷燬。

直接內存並不是 JVM 運行時數據區的一部分, 但也會被頻繁的使用: 在 JDK 1.4 引入的 NIO 提供了基於 Channel 與 Buffer 的 IO 方式, 它可以使用 Native 函數庫直接分配堆外內存, 然後使用DirectByteBuffer 對象作爲這塊內存的引用進行操作(詳見: Java I/O 擴展), 這樣就避免了在 Java堆和 Native 堆中來回複製數據, 因此在一些場景中可以顯著提高性能。

1、程序計數器(線程私有)

一塊較小的內存空間, 是當前線程所執行的字節碼的行號指示器,每條線程都要有一個獨立的程序計數器,這類內存也稱爲“線程私有”的內存。

正在執行 java 方法的話,計數器記錄的是虛擬機字節碼指令的地址(當前指令的地址)。如果還是Native 方法,則爲空。

這個內存區域是唯一一個在虛擬機中沒有規定任何 OutOfMemoryError 情況的區域。

2、虛擬機棧(線程私有)

**是描述java方法執行的內存模型,每個方法在執行的同時都會創建一個棧幀(Stack Frame)用於存儲局部變量表、操作數棧、動態鏈接、方法出口等信息。**每一個方法從調用直至執行完成的過程,就對應着一個棧幀在虛擬機棧中入棧到出棧的過程。

棧幀( Frame)是用來存儲數據和部分過程結果的數據結構,同時也被用來處理動態鏈接(Dynamic Linking)、 方法返回值和異常分派( Dispatch Exception)。棧幀隨着方法調用而創建,隨着方法結束而銷燬——無論方法是正常完成還是異常完成(拋出了在方法內未被捕獲的異常)都算作方法結束。

3、本地方法區(線程私有)

本地方法區和 Java Stack 作用類似, 區別是虛擬機棧爲執行 Java 方法服務, 而本地方法棧則爲Native 方法服務, 如果一個 VM 實現使用 C-linkage 模型來支持 Native 調用, 那麼該棧將會是一個C 棧,但 HotSpot VM 直接就把本地方法棧和虛擬機棧合二爲一。

4、堆(Heap-線程共享)-運行時數據區

是被線程共享的一塊內存區域,創建的對象和數組都保存在 Java 堆內存中,也是垃圾收集器進行垃圾收集的最重要的內存區域。由於現代 VM 採用分代收集算法, 因此 Java 堆從 GC 的角度還可以細分爲: 新生代(Eden 區、From Survivor 區和 To Survivor 區)和老年代。

5、方法區/永久代(線程共享)

即我們常說的永久代(Permanent Generation), 用於存儲被 JVM 加載的類信息常量靜態變量即時編譯器編譯後的代碼等數據. HotSpot VM把GC分代收集擴展至方法區, 即使用Java堆的永久代來實現方法區, 這樣 HotSpot 的垃圾收集器就可以像管理 Java 堆一樣管理這部分內存,而不必爲方法區開發專門的內存管理器(永久帶的內存回收的主要目標是針對常量池的回收類型的卸載, 因此收益一般很小)。

運行時常量池(Runtime Constant Pool)是方法區的一部分。Class 文件中除了有類的版本、字段、方法、接口等描述等信息外,還有一項信息是常量池(Constant Pool Table),用於存放編譯期生成的各種字面量和符號引用,這部分內容將在類加載後存放到方法區的運行時常量池中。 Java 虛擬機對Class 文件的每一部分(自然也包括常量池)的格式都有嚴格的規定,每一個字節用於存儲哪種數據都必須符合規範上的要求,這樣纔會被虛擬機認可、裝載和執行。


JVM 運行時內存

Java 堆從 GC 的角度還可以細分爲:新生代(Eden 區、From Survivor 區和 To Survivor 區)和老年代。


垃圾回收與算法


JAVA 四種引用類型

1、強引用

在 Java 中最常見的就是強引用,把一個對象賦給一個引用變量,這個引用變量就是一個強引用。當一個對象被強引用變量引用時,它處於可達狀態,它是不可能被垃圾回收機制回收的,即使該對象以後永遠都不會被用到 JVM 也不會回收。因此強引用是造成 Java 內存泄漏的主要原因之一。

2、軟引用

軟引用需要用 SoftReference 類來實現,對於只有軟引用的對象來說,當系統內存足夠時它不會被回收,當系統內存空間不足時它會被回收。軟引用通常用在對內存敏感的程序中。

3、弱引用

弱引用需要用 WeakReference 類來實現,它比軟引用的生存期更短,對於只有弱引用的對象來說,只要垃圾回收機制一運行,不管 JVM 的內存空間是否足夠,總會回收該對象佔用的內存。

4、虛引用

虛引用需要 PhantomReference 類來實現,它不能單獨使用,必須和引用隊列聯合使用。虛引用的主要作用是跟蹤對象被垃圾回收的狀態。


GC 分代收集算法 VS 分區收集算法


GC 垃圾收集器


JAVA IO/NIO

JVM 類加載機制

**JVM 類加載機制分爲五個部分:**加載,驗證,準備,解析,初始化,下面我們就分別來看一下這五個過程。

如果你看完這些知識點發現自己都掌握了,薪資卻沒有18K,趕緊跳槽吧!

接下來將花兩至三章的篇幅分享“Java多線程併發”!

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章