最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

詳細(xì)分析JVM類加載機制

 更新時間:2022年04月27日 09:02:54   作者:羨羨ˇ  
JVM將class文件字節(jié)碼文件加載到內(nèi)存中,?并將這些靜態(tài)數(shù)據(jù)轉(zhuǎn)換成方法區(qū)中的運行時數(shù)據(jù)結(jié)構(gòu),在堆(并不一定在堆中,HotSpot在方法區(qū)中)中生成一個代表這個類的java.lang.Class?對象,作為方法區(qū)類數(shù)據(jù)的訪問入口,接下來將詳細(xì)講解JVM類加載機制

前言

        ladies and gentleman , 你們好?? ,我是羨羨 , 這節(jié)我們進入jvm的學(xué)習(xí) , 我們知道 , jvm是java虛擬機, java代碼的執(zhí)行與 jvm 息息相關(guān), 接下來我們來依次介紹 , 首先這節(jié)先來介紹 jvm 中的類加載部分

1. jvm 的組成

jvm組成可分為這四個部分

1.類加載器(ClassLoader)

2.運行時數(shù)據(jù)區(qū)(Runtime Data Area)

3.執(zhí)行引擎(ExecutionEngine)

4.本地庫接口(Native Interface)

那么一個程序在 jvm 中的運行過程是怎樣的呢? 

       java代碼首先被編譯成字節(jié)碼文件(Class文件),  通過不同操作系統(tǒng)上的 jvm 來加載解釋 , 這個過程首先需要類加載器加載class文件 , 然后進行字節(jié)碼校驗 , 校驗結(jié)束通過后通過jvm解釋器翻譯成機器碼交給操作系統(tǒng)執(zhí)行

      程序在執(zhí)行之前先要把 java 代碼轉(zhuǎn)換成字節(jié)碼(class 文件),jvm 首先需要把字節(jié)碼通一定的方式 類加載器(ClassLoader) 把文件加載到內(nèi)存中的運行時數(shù)據(jù)區(qū)(Runtime DataArea) ,而字節(jié)碼文件是 jvm 的一套指 令集規(guī)范,并不能直接交個底層操作系統(tǒng)去執(zhí)行,因此需要特定的命令解析器 執(zhí)行引擎(Execution Engine) 將字節(jié)碼翻譯成底層系統(tǒng)指令再交由 CPU 去執(zhí)行,而這個過程中需要調(diào)用其他語言的接口 本地庫接口(Native Interface) 來實現(xiàn)整個程序的功能,這就是這 4 個主要組成部分的職責(zé)與功能

jvm整體結(jié)構(gòu)如下圖

 可能說到這里 , 初學(xué)的同學(xué)會有點懵 , 不過不用擔(dān)心, 上圖中的各個組成部分后面都會一一解釋

2. 類加載

       通過上面 jvm的運行過程可知 , 類加載就是讀取 class文件的過程 , 這期間需要用到類加載器 , 類加載器只負(fù)責(zé)加載 , 至于如何執(zhí)行 , 則由執(zhí)行引擎決定

類加載 又分為以下幾個模塊

      類加載器加載class文件到 jvm中 , 被稱為DNA元數(shù)據(jù)模板 , jvm通過模板來創(chuàng)建實例 , 類加載器在此過程相當(dāng)于擔(dān)任了快遞員的角色

那么類加載的過程是怎樣的呢 ?

可以看到 , 分為三個過程 : 加載, 鏈接 ,初始化 

1. 加載  

1. 通過類名(地址)獲取此類的二進制字節(jié)流.

2. 將這個字節(jié)流所代表的靜態(tài)存儲結(jié)構(gòu)轉(zhuǎn)換為方法區(qū)(元空間)的運行時結(jié)構(gòu).

3. 在內(nèi)存中生成一個代表這個類的 java.lang.Class 對象,作為這個類的各種數(shù)據(jù)的訪問入口.

 顧名思義 , 加載就是把類中的信息加載進 jvm 中

2. 鏈接

 鏈接又分為 3 個過程 : 驗證, 準(zhǔn)備 ,解析

(1) . 驗證

檢驗被加載的類是否有正確的內(nèi)部結(jié)構(gòu),并和其他類協(xié)調(diào)一致

        驗證文件格式是否一致: class 文件在文件開頭有特定的文件標(biāo)識(字節(jié)碼文件都以 CA FE BA BE 標(biāo)識開頭);主,次版本號是否在當(dāng)前 java 虛擬機接收范圍內(nèi)

       元數(shù)據(jù)驗證:對字節(jié)碼描述的信息進行語義分析,以保證其描述的信息符合java 語言規(guī)范的要求,例如這個類是否有父類;是否繼承瀏覽不允許被繼承的類(final 修飾的類)

驗證過程主要是看是否符合java語言的規(guī)范

(2) . 準(zhǔn)備

準(zhǔn)備:準(zhǔn)備階段則負(fù)責(zé)為類的靜態(tài)屬性分配內(nèi)存,并設(shè)置默認(rèn)初始值(int為0)

此過程不包含用 final 修飾的 static 常量(靜態(tài)常量),在編譯時進行初始化.

//準(zhǔn)備階段值為0
public static int value = 123;
//準(zhǔn)備階段值為123
public static final int value = 123;

(3) .解析

    將類的二進制數(shù)據(jù)中的符號引用替換成直接引用(符號引用是 Class 文件的邏輯符號,直接引用指向的方法區(qū)中某一個地址)

      將符號引用替換成直接引用, 這句話怎么理解呢 ? 這里來舉個例子

public void method1(){
    method2();
}

        在 方法1 中調(diào)用 方法2 , 我們這樣來寫代碼的時候, 這就只是符號引用 , 而當(dāng)這段程序被加載進 jvm解析的時候 符號引用就會變成直接引用, 也就是指明此處真正的引用地址

3. 初始化

 在談類的初始化過程之前, 先來考慮 , 類什么時候會被初始化? 

1 )創(chuàng)建類的實例,也就是 new 一個對象

2)訪問某個類或接口的靜態(tài)變量,或者對該靜態(tài)變量賦值

3)調(diào)用類的靜態(tài)方法

4)反射(Class.forName(“”))

5)初始化一個類的子類(會首先初始化子類的父類)

       初始化類的過程也是為類中成員賦值的過程 , 在鏈接過程中的準(zhǔn)備過程中被static修飾的變量是賦了默認(rèn)值(int型為0), 而在初始化過程中才會賦予我們賦的值

       我們常說 , 用 static 修飾的變量, 方法 , 代碼塊是跟類直接打交道的 , 我們說加載類的時候, 使用static修飾的成員也會被加載 , 此過程也是在類的初始化中完成

那么在初始化過程中, 賦值順序是怎樣的呢?

      如果同時包含多個靜態(tài)變量和靜態(tài)代碼塊,則按照自上而下的順序依次執(zhí)行。 如果初始化一個類的時候,其父類尚未初始化,則優(yōu)先初始化其父類。

      順序是:父類 static –> 子類 static –> 父類構(gòu)造方法- -> 子類構(gòu)造方法

下面代碼 num 的值變化

3. 類加載器

        從開發(fā)人員的角度上來講, 類加載器可分為3類 : 引導(dǎo)類加載器(啟動類加載器), 擴展類加載器 , 應(yīng)用程序類加載器

引導(dǎo)類加載器(啟動類加載器)

     這個類加載器使用 C/C++語言實現(xiàn),嵌套在 JVM 內(nèi)部.它用來加載 java 核心類庫.     

     并不繼承于java.lang.ClassLoader , 沒有父加載器 , 負(fù)責(zé)加載擴展類加載器和應(yīng)用程序類加載器 , 并為它們指定父類加載器

     ClassLoader 類,它是一個抽象類,其后所有的類加載器都繼承自 ClassLoader (不包括啟動類加載器)

      引導(dǎo)類加載器作為頂級的類加載器, 非java語言實現(xiàn) , 所以和java中其他類加載器也不存在繼承關(guān)系等

擴展類加載器

 Java 語言編寫的,由sun.misc.Launcher$ExtClassLoader 實現(xiàn). 派生于 ClassLoader 類.

          負(fù)責(zé)從 java.ext.dirs 系統(tǒng)屬性所指定的目錄中加載類庫,或從 JDK 系統(tǒng)安裝目錄jre/lib/ext 子目錄(擴展目錄)下加載類庫.如果用戶創(chuàng)建的 jar 放在此目錄下,也會自動由擴展類加載器加載

應(yīng)用程序類加載器

     Java 語言編寫的,由 sun.misc.Launcher$AppClassLoader 實現(xiàn). 派生于 ClassLoader 類.      加載我們自己定義的類,用于加載用戶類路徑(classpath)上所有的類.      該類加載器是程序中默認(rèn)的類加載器.

我們自己寫的類是由應(yīng)用程序類加載器加載的, 類加載器結(jié)構(gòu)示例如下

//獲取應(yīng)用程序類加載器  sun.misc.Launcher$AppClassLoader@18b4aac2
ClassLoader classLoader = ClassLoader.getSystemClassLoader();
System.out.println(classLoader);
//獲得父類加載器 sun.misc.Launcher$ExtClassLoader@74a14482
System.out.println(classLoader.getParent());
//擴展類加載器上一級是引導(dǎo)類加載器,不是java實現(xiàn),為null
System.out.println(classLoader.getParent().getParent());
//拿到String類的類加載器,結(jié)果為null
//可見,String類為引導(dǎo)類加載器加載
ClassLoader classLoader1 = String.class.getClassLoader();
System.out.println(classLoader1);

另外還有一種叫做用戶自定義類加載器 , 例如 tomcat

4. 雙親委派機制

什么是雙親委派機制呢? 

       Java 虛擬機對 class 文件采用的是按需加載的方式,也就是說當(dāng)需要該類時才會 將它的class 文件加載到內(nèi)存中生成 class 對象.而且加載某個類的 class 文件 時,Java 虛擬機采用的是雙親委派模式,即把請求交由父類處理,它是一種任務(wù)委 派模式.

.

      就是說呢, 如果類加載器接收到了加載請求, 并不會去立即加載這個類, 而是把請求交給它的上一級加載器去加載 , 上一級沒有則繼續(xù)往上找 , 直到頂級的類加載器(引導(dǎo)類加載器)也無法加載時, 開始往下找 , 如果有一級加載成功則返回, 最終加載器都無法加載時, 就會拋出ClassNotFoundException異常

      那么為什么要這樣去做呢? 試想, 我們自己創(chuàng)建一個java.lang.String類

package java.lang;
public class String {
    public String(){
        System.out.println("自己的String");
    }
}

建立一個測試類

public class TestString {
    public static void main(String[] args) {
        new String();
    }
}

        試想 , "自己的String" 這句話會被輸出嗎 ? 答案肯定是不會

        因為加載類的時候會先往上走, 此時走到了引導(dǎo)類加載器, 引導(dǎo)類加載器發(fā)現(xiàn)此類沒有被加載,并且自己可以加載, 那么java.lang.String 就會被加載了, 此時就會直接返回 

        那么雙親委派機制出現(xiàn)的原因就顯而易見了

      安全,可避免用戶自己編寫的類動態(tài)替換 Java 的核心類,如 java.lang.String , 避免全限定命名的類重復(fù)加載(使用了 findLoadClass()判斷當(dāng)前類是否已加載)

5. 類的主動/被動使用

      JVM 規(guī)定,每個類或者接口被首次主動使用時才對其進行初始化,有主動使用,自然就有被動使用.那么什么時候類被主動使用呢?

  • 通過new關(guān)鍵字被導(dǎo)致類的初始化,這是大家經(jīng)常使用的初始化一個類的方式,他肯定會導(dǎo)致類的加載并且初始化
  • 訪問類的靜態(tài)變量,包括讀取和更新
  • 訪問類的靜態(tài)方法
  • 對某個類進行反射操作,會導(dǎo)致類的初始化
  • 初始化子類會導(dǎo)致父類的的初始化
  • 執(zhí)行該類的 main 函數(shù)

除了上面的幾種主動使用其余就是被動使用了

     1.引用該類的靜態(tài)常量,注意是常量,不會導(dǎo)致初始化,但是也有意外,這里的常量是指已經(jīng)指定字面量的常量,對于那些需要一些計算才能得出結(jié)果的常量就會導(dǎo)致初始化,比如:

public final static int NUMBER = 5 ; //不會導(dǎo)致類初始化,被動使用 public final static int RANDOM = new Random().nextInt() ; //會導(dǎo)致類的初始化,主動使用

     2.構(gòu)造某個類的數(shù)組時不會導(dǎo)致該類的初始化

Student[] students = new Student[10]

      主動使用和被動使用的區(qū)別在于類是否會被初始化.

結(jié)語

       到此關(guān)于 jvm 類加載這一章就說完了 , 感謝您的閱讀 , 后續(xù)將會進行 jvm 中運行時數(shù)據(jù)區(qū)的講解 , 感謝您的支持 ,謝謝 !!!

到此這篇關(guān)于詳細(xì)分析JVM類加載機制的文章就介紹到這了,更多相關(guān)JVM類加載內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • Java完美實現(xiàn)2048小游戲

    Java完美實現(xiàn)2048小游戲

    本文給大家分享的是一則根據(jù)網(wǎng)友的代碼改編的2048小游戲的源碼,個人認(rèn)為已經(jīng)非常完美了,推薦給大家,有需要的小伙伴可以參考下。
    2015-03-03
  • 詳解Spring Boot 事務(wù)的使用

    詳解Spring Boot 事務(wù)的使用

    spring Boot 使用事務(wù)非常簡單,首先使用注解 @EnableTransactionManagement 開啟事務(wù)支持后,然后在訪問數(shù)據(jù)庫的Service方法上添加注解 @Transactional 便可。接下來通過本文重點給大家介紹spring boot事務(wù)的使用,需要的的朋友參考下吧
    2017-04-04
  • SpringMVC如何接收參數(shù)各種場景

    SpringMVC如何接收參數(shù)各種場景

    這篇文章主要介紹了SpringMVC如何接收參數(shù)各種場景,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2021-11-11
  • MyBatis-Plus?條件查詢器的實現(xiàn)

    MyBatis-Plus?條件查詢器的實現(xiàn)

    本文主要介紹了MyBatis-Plus?條件查詢器的實現(xiàn),文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2022-07-07
  • Mybatis關(guān)聯(lián)查詢結(jié)果集對象嵌套的具體使用

    Mybatis關(guān)聯(lián)查詢結(jié)果集對象嵌套的具體使用

    在查詢時經(jīng)常出現(xiàn)一對多”的關(guān)系,所有會出現(xiàn)嵌套對象的情況,本文主要介紹了Mybatis關(guān)聯(lián)查詢結(jié)果集對象嵌套的具體使用,文中通過示例代碼介紹的非常詳細(xì),具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2022-02-02
  • 高吞吐、線程安全的LRU緩存詳解

    高吞吐、線程安全的LRU緩存詳解

    這篇文章主要介紹了高吞吐、線程安全的LRU緩存詳解,分享了相關(guān)代碼示例,小編覺得還是挺不錯的,具有一定借鑒價值,需要的朋友可以參考下
    2018-02-02
  • Java解釋器的運行過程介紹

    Java解釋器的運行過程介紹

    今天小編就為大家分享一篇關(guān)于Java解釋器的運行過程介紹,小編覺得內(nèi)容挺不錯的,現(xiàn)在分享給大家,具有很好的參考價值,需要的朋友一起跟隨小編來看看吧
    2019-04-04
  • Java中隊列Queue和Deque的區(qū)別與代碼實例

    Java中隊列Queue和Deque的區(qū)別與代碼實例

    學(xué)過數(shù)據(jù)結(jié)構(gòu)的,一定對隊列不陌生,java也實現(xiàn)了隊列,下面這篇文章主要給大家介紹了關(guān)于Java中隊列Queue和Deque區(qū)別的相關(guān)資料,需要的朋友可以參考下
    2021-08-08
  • 詳解JAVA生成將圖片存入數(shù)據(jù)庫的sql語句實現(xiàn)方法

    詳解JAVA生成將圖片存入數(shù)據(jù)庫的sql語句實現(xiàn)方法

    這篇文章主要介紹了詳解JAVA生成將圖片存入數(shù)據(jù)庫的sql語句實現(xiàn)方法的相關(guān)資料,這里就是實現(xiàn)java生成圖片并存入數(shù)據(jù)庫的實例,需要的朋友可以參考下
    2017-08-08
  • Java類加載連接和初始化原理解析

    Java類加載連接和初始化原理解析

    這篇文章主要介紹了Java類加載連接和初始化原理解析,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友可以參考下
    2020-03-03

最新評論

宝应县| 中牟县| 隆回县| 微博| 嘉荫县| 澜沧| 施秉县| 东山县| 黔南| 清水河县| 漾濞| 曲松县| 泾阳县| 绍兴市| 华坪县| 家居| 淳化县| 普兰县| 海门市| 清水县| 陕西省| 定边县| 封开县| 遂川县| 柳江县| 景德镇市| 乃东县| 彩票| 石嘴山市| 温泉县| 琼中| 和林格尔县| 龙里县| 山阳县| 玉山县| 石城县| 河间市| 汕尾市| 孙吴县| 连平县| 重庆市|