你能講清楚Java類的整個生命週期嗎?

想了很久,想把JVM這塊了結一下,奈何知識實在是太多,隨便拿出一個知識點都能寫一篇文章了。今天就從Java類的生命週期講吧,就跟人的一生一樣,有太多的曲折和苦難,但是也有很溫暖、很甜的時候,這就是人生百態,也是Java類的人生百態。

初次相見,你是否還記得HelloWorld

有多少人,還記得第一次寫Java代碼時候的情景?我想99%的人都是從HelloWorld開始Java這一段精彩的人生的。來,我們在看看那熟悉的Hello World吧!

public class MainTest {
    
    public static void main(String[] args){
        System.out.println("Hello World!");
    }
}

一別多年,你又回來看HelloWorld

從上一次寫Hello World以後,你是不是很多年都沒有寫過Hello World呢?在與它分別的這些日日夜夜裏面,你是不是已經開始使用Spring全家桶了?你是不是已經開始使用ORM框架了?你是不是已經開始使用NoSql數據庫了?你是不是已經開始Redis了?你又是不是開始使用RPC了呢?
當你用過了越來越多的框架,你發現你也只是個使用級別的程序員,是不是內心很崩潰呢?
當你靜下心來,回想當初步入這個行業的時候,回想起你寫下第一行代碼的時候,你是不是又想起了Hello World?你真的認識它嗎?

重拾,再看HelloWorld

依稀記得,這幾行簡單的不能再簡單的代碼,可是,你瞭解它的生命週期嗎?你知道它從靜態編譯到加載,再到連接,在到初始化,在到使用,在到卸載的這一生都要經歷什麼嗎?
從.java文件,靜態編譯以後變成了.class文件,你知道class文件裏面長什麼樣子嗎?我們來一起看看吧!
在這裏插入圖片描述

用編輯器,打開class文件,你會看到這些16進制的字符,你是否認識它們啊?
這長圖確實有難度,我們再換一張圖,來看看。

類結構圖

你是否看到了熟悉的身影:CA FE BA BE,這是不是你常常唸叨的咖啡貝貝啊?這就是class文件的結構了。想想,你都會和這裏面的哪些夥伴接觸過呢?

  • 【魔術】magic,這東西,平時真沒交集,只有在類生命週期的驗證階段纔會用到它,只有.java文件編譯後的.class纔有這玩意,這算是一個唯一標識符了。記住了,下次,看見它,就要知道,這個咖啡貝貝是你用Java寫得了。
  • 【副版本號】minor_version,說實在的,這玩意好像真沒啥用,咱也不敢問當初開發的大牛,爲什麼要這玩意兒啊!哪位大牛知道,希望給普及一下知識盲區。
  • 【主版本號】,這玩意兒你要知道,怎麼看呢?再給一幅圖看看吧!
    在這裏插入圖片描述
    你找到最上面的那張圖,看看是用什麼版本寫的,你是不是已經看到了【00 00 00 34】,這是16進制的,對應的十進制是52,對應jdk1.8.剩下的,就不一個一個說了。再來一張圖片吧!
    在這裏插入圖片描述
    這裏面有很多都是經常你經常使用的,比如:接口,字段,方法,屬性等等。

這上面的太抽象了,在使用Java的過程中,怎麼才能查看呢?

利器,javap命令

在這裏插入圖片描述

以後,有時間多用javap命令來看看你寫的代碼,有助於深入理解Java。
說了這麼久,都沒有提及Java類的生命週期,是不是覺得我在忽悠人啊?下面,就一起來看看吧!

Java類的生命週期

在這裏插入圖片描述
這應該是你熟悉的Java類的生命週期吧,我們上面聊的只是從.java文件編譯爲.class文件中涉及一點知識點而已。

Java類的生命週期,從大的範圍可以劃分爲加載-連接-初始化-使用-卸載.從小的範圍可以分爲加載-驗證-準備-解析-初始化-使用-卸載。

你有想過,類在生命時候初始化嗎?類在哪裏使用了?類在什麼時候卸載?

Java類加載子系統,類加載器

你是否清楚,Java類是怎麼加載?我們通過一張圖,來看看

在這裏插入圖片描述

  • BootStrap ClassLoader[啓動類加載器],這個加載器是由C++寫的,它加載JAVA_HOME\lib目錄下的jar包。注意,它不是ClassLoader的子類。
  • Extension ClassLoader[擴展類加載器],它加載JAVA_HOME\lib\ext目錄下的jar包。
  • Application ClassLoader[應用類加載器],加載用戶路徑(classpath)目錄下的jar包。
  • 自定義加載器,加載用戶自定義目錄下的jar包。
    從上面這張圖,你應該知道類在加載的時候,有這麼多關卡,箭頭都是向上的,爲什麼呢?
    【雙親委派】,【自底向上檢查類是否已經記載】,【自頂向下嘗試加載類】,這就是雙親委派。你知道爲什麼叫【雙親委派】嗎? 可能,就是應用類加載器上面有一個爹和一個爺爺吧。所以,才叫做【雙親委派】吧!
  • 【驗證】,保證二進制字節流中的信息符合虛擬機規範,並沒有安全問題。
  • 【準備】,僅僅爲類變量(即static修飾的字段變量)分配內存並且設置該類變量的初始值即零值。
  • 【解析】,解析是虛擬機將常量池的符號引用替換爲直接引用的過程。解析動作主要針對類或接口、字段、類方法、接口方法四類符號引用進行,分別對應於常量池中的
    CONSTANT_Class_info、CONSTANT_Fieldref_info 、CONSTANT_Methodref_info 、CONSTANT_InterfaceMethodref_info`四種常量類型。
  • 【初始化】,初始化是類加載過程的最後一步,到了此階段,才真正開始執行類中定義的Java程序代碼(初始化成爲代 碼設定的默認值)。其實初始化過程就是調用類初始化方法的過程,完成對static修飾的類變量的手動賦值還有主動調用靜 態代碼塊。

當你步入社會【JVM運行時區域】,可就要靠自己了

jvm運行時區域,從大範圍,可以分爲兩種區域,一種是線程共享區域,另外一種,就是線程獨享區域了
線程共享區域,在不同的JDK版本中,大體相同,但是也有不同。有些區域,危險無比,有些區域也無比安全。隨着JVM的啓用生,隨着JVM的死而銷燬。
線程獨享區域,隨着線程的創建而生,隨着線程的死亡而死亡。思想之下,這就是皇帝和愛妃啊,皇帝駕崩,愛妃陪葬啊!

  • 線程共享區域,在JDK1.6中包含堆和方法區(永久代的實現),在JDK1.7中也包含堆和方法區(永久代),在JDK1.8+以後只包含堆了。備註:【在JDK1.6中方法區中包含運行時常量池,在JDK1.7的時候運行時常量池挪到堆中了,在JDK1.8的時候真正實現了去除永久代。有人會說JDK1.8中有元空間,但是,元空間用的是對外內存,已經不再Java堆中了】

  • 【朝生夕死】年輕代,分爲eden和兩個交換區,在平時運行時工作的是eden和其中一塊交換區。

  • 【長命百歲】老年代,老東西都是關係複雜的,有各種社會人脈和資源的,能活的很久。

  • 【與天同壽】永久代,JVM生它就生,JVM死它才死。【也有個例,會被帶走】
    能活多久,全靠自己本事和那麼一點點運氣了。

總結:歲月靜好,願你一世安康快樂

不管你,是不是寫代碼的,還是高級寫代碼的,都要快樂!
寫代碼的時候,心情是美好的。改BUG的時候,是糟糕的。跟產品聊天的時候,是想拿刀的。
歲月靜好,你要靜下心來,聆聽和感受這氛圍,願你一世安康快樂!

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