1. 程式人生 > 實用技巧 >JAVA類的生命週期

JAVA類的生命週期

參考:

1.https://mp.weixin.qq.com/s?src=11&timestamp=1596419476&ver=2499&signature=kT5XnCOM5otjYKMHnxTWZKAd2vMEWUu5lGm9IyyvuLTUwYfexnSLDoBbKovrWodxdShLdcQ1q4oGaZIucCIxdmfmp8DrD8OhhxN2tKZk05huaX8Q6c*Aa5KNzFI4WILo&new=1

2.https://zhuanlan.zhihu.com/p/51029831

3.https://blog.csdn.net/qq_26440803/article/details/93675122

4.https://www.cnblogs.com/zhangpan1244/p/6197832.html

介紹下虛擬機器:

概念:JVM是Java Virtual Machine(Java虛擬機器)的縮寫,JVM是一種用於計算裝置的規範,它是一個虛構出來的計算機,是通過在實際的計算機上模擬模擬各種計算機功能來實現的。

介紹:Java語言的一個非常重要的特點就是與平臺的無關性。而使用Java虛擬機器是實現這一特點的關鍵。一般的高階語言如果要在不同的平臺上執行,至少需要編譯成不同的目的碼。而引入Java語言虛擬機器後,

Java語言在不同平臺上執行時不需要重新編譯。Java語言使用Java虛擬機器遮蔽了與具體平臺相關的資訊,使得Java語言編譯程式只需生成在Java虛擬機器上執行的目的碼(位元組碼),就可以在多種平臺上不加修改地執行。

Java虛擬機器在執行位元組碼時,把位元組碼解釋成具體平臺上的機器指令執行。這就是Java的能夠“一次編譯,到處執行”的原因。

這裡就是簡單瞭解下jvm執行過程和內部結構,想理解更多看參考,現在jvm可以解析的程式語言也不僅僅是java了,Groovy,JRuby等都是可以的

瞭解了虛擬機器大致的工作過程,那麼就開始瞭解下生命週期:

1.類的生命週期

類從被載入到虛擬記憶體中開始,到解除安裝記憶體為止,它的整個生命週期包括:

注:

1.載入和連線是交叉進行的,不需要等載入完成,再連線

2.解析可以在初始化之後再做。比如:Jvm僅僅規定了:如果某些位元組碼使用了符號引用,那麼在執行這些位元組碼之前,需要完成對這些符號引用的解析。

3.類的生命週期在初始化的時候有交叉,但整體的結構是按照這個固定順序的

4.這裡的“載入階段”和我們常說的“類載入”是兩回事,“類載入”指的是虛線框中三部分加起來。

介紹下類的生命週期各階段:

1載入

概念:查詢位元組流,以此來建立類的過程。是類載入過程的一個階段,jvm需要完成以下事情:

1)根據類的全限定名,獲取類的二進位制位元組流

2) 將這個位元組流的靜態儲存結構轉化成方法區的執行時資料結構

3) 在記憶體中生成一個代表這個類的java.lang.Class物件,作為這個方法區這個類的各種資料的訪問入口。

類載入示意圖

總結: 從虛擬機器的角度來說,只存在兩種不同的類載入器:一種是啟動類載入器(Bootstrap ClassLoader),該類載入器使用C++語言實現,屬於虛擬機器自身的一部分。

另外一種就是所有其它的類載入器,這些類載入器是由Java語言實現,獨立於JVM外部,並且全部繼承自抽象類java.lang.ClassLoader。

四種載入器:

第一種:啟動(Bootstrap)類載入器

載入物件:啟動類載入器負責載入最為基礎、最為重要的類。負責將 JAVA_HOME/lib 下面的類庫載入到記憶體中(比如rt.jar)。

注意:1. 由於引導類載入器涉及到虛擬機器本地實現細節,開發者無法直接獲取到啟動類載入器的引用,所以不允許直接通過引用進行操作。

2. 啟動類載入器是由 C++ 實現的,沒有對應的 Java 物件,因此在 Java 中只能用 null 來指代。

3. 除了啟動類載入器之外,其他的類載入器都是 java.lang.ClassLoader 的子類,因此有對應的 Java 物件。

4. 這些類載入器需要先由另一個類載入器,比如說啟動類載入器,載入至 Java 虛擬機器中,方能執行類載入。

第二種:標準擴充套件(Extension)類載入器

載入物件:它負責載入相對次要、但又通用的類,負責將 JAVA_HOME/jre/lib/ext 或者由系統變數 java.ext.dirs指定位置中的類庫載入到記憶體中。

第三種:應用程式(Application)類載入器

載入物件:它負責將系統類路徑(CLASSPATH) 中指定的類庫載入到記憶體中。由於這個類載入器是ClassLoader中的 getSystemClassLoader()方法的返回值,因此一般稱為系統(System)載入器

第四種:自定義類載入器

載入物件:除了由 Java 核心類庫提供的類載入器外,我們還可以加入自定義的類載入器,來實現特殊的載入方式。舉例來說,我們可以對 class 檔案進行加密,載入時再利用自定義的類載入器對其解密。

雙親委任

工作流程:

(1)當前ClassLoader首先從自己已經載入的類中查詢是否此類已經載入,如果已經載入則直接返回原來已經載入的類。

注意:每個類載入器都有自己的載入快取,當一個類被載入了以後就會放入快取,等下次載入的時候就可以直接返回了。

(2)當前classLoader的快取中沒有找到被載入的類的時候,委託父類載入器去載入,父類載入器採用同樣的策略,首先檢視自己的快取,然後委託父類的父類去載入,一直到bootstrp ClassLoader.

(3)當所有的父類載入器都沒有載入的時候,再由當前的類載入器載入,並將其放入它自己的快取中,以便下次有載入請求的時候直接返回。

好處:1.類的名稱空間:類需要類的全限定名(類的全路徑)以及載入此類的ClassLoader來共同確定。也就是說即使兩個類的全限定名是相同的,但是因為不同的ClassLoader載入了此類,那麼在JVM中它是不同的類。

比如:比如上面說的,我們 JDK 本生提供的類庫,比如 string,hashmap,linkedlist 等等,這些類由bootstrp 類載入器載入了以後,

無論你程式中有多少個類載入器,那麼這些類其實都是可以共享的,這樣就避免了不同的類載入器載入了同樣名字的不同類以後造成混亂。

2.避免病毒植入。

比如:自定義一個 java.lang.String 類,該 String 類具有系統的 String 類一樣的功能,只是在某個函式稍作修改。

這個函式經常使用,假如在這這個函式中植入一些“病毒代 碼”。並且通過自定義類載入器加入到 JVM 中。完了,程式涼涼,這是比較直觀的理解。

雙親委任載入規則總結:檢查自底而上,載入自上而下