學習路線推薦,如何啃下JVM這座大山(完結篇)

大家好,我是小富~

這是關於JVM的第六篇文章,前面寫了五篇關於JVM的文章,都是一層一層帶着大家來深入的認識JVM,關於JVM的基本用到的知識都講解過了。

那麼這一篇文章將作爲JVM的最後一篇,有總結,也有補充還沒有提及到的知識點。

首先,關於JVM的開門篇,關於如何閱讀深入JVM虛擬機第三版的文章:如何三天啃下《深入JVM虛擬機第三版》,主要是分享個人閱讀這本神書的經驗,在文章裏面劃重點,吸收到我們自己所需要的知識點。

然後,是很久之前寫的第二篇關於JVM的運行時數據區以及GC的算法篇:還在學JVM?我都幫你總結好了(附腦圖)

這篇是是作爲理論的重點部分,因爲這片關於JVM的運行時數據區的各個部分是幹嘛的,以及重點JVM堆的分代理論和GC的基本回收算法,都是爲後面的Java堆的調優實戰做鋪墊。

然後是第三篇也是調優的重中之重,主要聊的就是GC:你是不是垃圾,心裏沒點數嗎?如何判斷一個對象是否存活、以及常見的GC的種類,常見GC年輕代和老年代的搭配,各種GC的原理和特點、以及適用的場景,在文章中都有提及到。

有了第二篇運行時數據區和第三篇GC的理論基礎後,然後第四篇的JVM調優實戰篇一:JVM調優實戰篇一,這一篇主要是圍繞着JVM調優實戰講解的工具篇,包括線上的Arthas工具、GUI工具(Visual VM)、內存分析工具(mat)以及linux的原始命令jps、jstack、jstat、jmap、jhat等命令的講解和使用

熟悉了JVM調優的工具後,第五篇就是就是最後實戰調優的場景、案例、經典排查OOM、磁盤不足排查、CPU飆高的排查、死鎖的排查、調優的目的和理論已經調優案例場景解析JVM性能調優實戰篇(二)

其中,第五篇也是寫了我最久的一篇,也是乾貨非常多的一篇,也是目的性最強的一篇,學習JVM就是爲了調優,同時也收穫不少的新讀者的關注。

所以,按照上面幫你們排好的順序,一篇一篇的往下讀,應該對你的調優的技術和理論的深入認識應該是有所幫助的。

然後,自己有時間的話,也可以自己深入的啃啃《深入JVM虛擬機第三版》,關於JVM的其他書籍,我推薦:《Java虛擬機規範》、《垃圾回收算法手冊:自動內存管理的藝術》、《Virtual Machines: Versatile Platforms for System and Processes》 這幾本好書,有時間和能力的都可以去看一看。

最後,這是最後一篇也是第六篇,對於JVM虛擬機我們所需要的部分,還有一塊就是類加載子系統還沒有講解,所以爲了文章的完整性,這一補充JVM的類加載子系統,這一篇還是主要是理論。

類加載子系統概述

首先,我們來聊一聊JVM的類加載子系統,我們知道我們的代碼敲完後是.java類,然後經過編譯就會變成.class類型的字節碼文件。

這些.class類型的字節碼文件經過類加載系統加載到JVM的內存中來供我們使用,這些文件我們也成爲了元數據。

下面我畫了一張圖來大概一個類被類加載系統加載的過程,供大家理解:

就這樣一個java類經過上面層層的過程來到了我們的JVM的虛擬機中,首先在加載過程的.class文件可以來源終於下面幾個方面:

  • 從系統文件中獲取,比如從我們本地編譯好的class。
  • 從網絡中獲取
  • 或者運行時計算出來的,比如使用動態代理技術,運行時生成。
  • 或者由其他的文件生成,比如jsp生成對應的class文件。

當由我們的類加載子系統完成了類加載後,這部分信息(包括類信息、常量、靜態變量、方法信息等)就會存在方法區的內存中(jdk 7以及以前,jdk 8及以上移動到元空間,本地內存中),然後由JVM的執行引擎來執行。

在這個過程類加載的過程就好像扮演着中間人的角色,目的爲的是JVM的執行引擎能夠執行這些類:.class -> JVM -> 元數據模板 -> 實例對象

那麼,JVM在加載類的時候,這個過程的主角類加載器,又是怎麼工作的呢?下面我們來聊一聊類加載器。

類加載器

在JVM中經典的類加載器分爲如下三層:

  1. 啓動類加載器(BootStrap ClassLoader):該加載器是由C++實現,加載<JAVA_HOME>\lib下的文件,這類加載起不會被Java程序所直接使用,該類加載器一般加載包名爲java、javax、sun等開頭的類
  2. 擴展類加載器(Extension ClassLoader):擴展類加載器是加載<JAVA_HOME>\lib\ext目錄下的資源,它可以用來擴展Java SE的功能,如果用戶創建的JAR包放在此目錄下,就會被擴展類加載器加載
  3. 應用類加載器(Application ClassLoader):它負責加載用戶類路徑(ClassPath)上的所有類庫,開發者同樣可以直接在代碼中使用這個類加載器。


除了上面的經典三層還有一個就是用戶自定義類加載器(User ClassLoader),它可以在程序中加載自己需要的類,所以完整的JVM類加載器如下圖所示:

他們的關係並不是繼承的關係,而是通常以組合的關係來複用父類加載器的代碼。

類加載過程

我們瞭解完各種類加載器後,接下來詳細的瞭解類加載的過程,一個完整的類加載過程主要包括一下幾個階段:加載-> 驗證->準備->解析->初始化

加載階段是通過類的全類名,然後通過類加載器將class文件的二進制字節流轉化爲運行時數據區的方法區中。

並且,會在內存中生成一個java.lang.Class對象,作爲這個類的各種數據的訪問入口。

驗證階段既是驗證字節碼class文件中的字節碼是否服務規範,保證裏面的字節碼不會對JVM自身造成傷害。

準備階段既是爲類中的類變量(static修飾的變量,但沒有被final修飾一起修飾)分配內存以及初始化類變量的零值,這裏並不包括實例變量,實例變量是在對象一起分配在Java堆中。

所謂的零值也就是數據的默認初始值,比如int爲0,boolean默認爲false,float默認爲0.0f,引用類型的默認爲null。

解析階段的作用是將虛擬機內的常量池的符號引用替換爲直接引用的過程。所謂的符號引用就是可以是任何形式的字面量,只要能夠定位到目標即可;而直接引用可以是指向目標的指針、相對偏移量間接定位到目標的句柄。

最後是初始化,初始化是類加載的最後一個階段,也是在這個階段,Java虛擬機才真正開始執行類中的Java程序代碼。

上面說到在準備階段變量已經初始化一次零值了,那麼在這一階段纔會將變量初始化爲程序代碼中主觀設置的值。

對於這一部分,我之前也寫過一篇詳細的,所以這裏做一個大概的介紹,詳細的可以參考這一篇文章:面試官:你知道java類是怎麼跑起來的嗎?問的我一臉懵

雙親委派原則

雙親委派原則是各種加載器之前的一種工作方式,它目的是爲了實現更加高效的進行類的加載。

當一個類加載器收到加載類的請求時,不會自己去嘗試先加載該類,而是把該加載請求委託給父類,若是沒有父類就是直接找頂層類加載器,若是有父類,並且父類還有父類加載器,依次向上委託,直到上面的所有父類都無法完成加載是,纔會自己去加載,若是加載失敗就會拋出異常。

它的好處就是加載一個類時,不用重複加載,當父類已經加載了,就不用加載第二年份,保證內存中只有一份。

我們來看看雙親委派實現的源代碼,它的源代碼主要實現是java.lang.ClassLoader的loadClass() 方法中:

protected synchronized Class<?> loadClass(String name, boolean resolve) throws ClassNotFoundException {
 // 檢查該類是否已經被加載過了
 Class c = findLoadedClass(name);
 // c爲null沒有被加載過,則使用雙親委派原則進行類加載
 if (c == null) {
  try {
      // 存在父類加載器
   if (parent != null) {
    c = parent.loadClass(name, false);
   } else {
       // 不存在服務加載器,則直接使用頂層類加載器進行加載
    c = findBootstrapClassOrNull(name);
   }
  } catch (ClassNotFoundException e) {
   // 父類加載拋出異常,說明父類無法完成加載
  }
  if (c == null) {
   // 父類無法完成加載,則嘗試自己去完成加載動作
   c = findClass(name);
  }
 }
 if (resolve) {
  resolveClass(c);
 }
 return c;
}

好了,這一篇文章是的主要內容也講完了,文字比較短,沒有像以前那樣基本都是萬字,因爲主要的內容都已經講完了,這一篇還是比較簡單的,更加傾向於對以前寫的JVM的文章的總結。


接下來的文章開始數據庫的連載,主要個人看的書籍是 《Mysql 45講》、《MySQL技術內幕  InnoDB存儲引擎  第2版》、《高性能mysql第三版》,好了這一期就到這裏,我們下一期間。

我是小富~,如果對你有用在看關注支持下,咱們下期見~


   
   
   
你的每個贊和在看,我都喜歡!

本文分享自微信公衆號 - 程序員內點事(chengxy-nds)。
如有侵權,請聯繫 [email protected] 刪除。
本文參與“OSC源創計劃”,歡迎正在閱讀的你也加入,一起分享。

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