欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

一篇文章弄懂JVM類加載機(jī)制過程以及原理

 更新時間:2023年02月07日 17:03:35   作者:哪?吒  
JVM原理對于初學(xué)者而言,比較晦澀難以理解,概念繁多又比較抽象,很多時候感覺看不見摸不著,還不好驗證,下面這篇文章主要給大家介紹了關(guān)于如何通過一篇文章弄懂JVM類加載機(jī)制過程及原理的相關(guān)資料,需要的朋友可以參考下

一、做一個小測試

通過注釋,標(biāo)注出下面兩個類中每個方法的執(zhí)行順序,并寫出studentId的最終值。

package com.nezha.javase;

public class Person1 {

    private int personId;

    public Person1() {
        setId(100);
    }

    public void setId(int id) {
        personId = id;
    }
}
package com.nezha.javase;

public class Student1 extends Person1 {

    private int studentId = 1;

    public Student1() {
    }

    @Override
    public void setId(int id) {
        super.setId(id);
        studentId = id;
    }

    public void getStudentId() {
        System.out.println("studentId = " + studentId);
    }
}
package com.nezha.javase;

public class Test1 {
    public static void main(String[] args) {
        Student1 student = new Student1();
        System.out.println("new Student() 完畢,開始調(diào)用getStudentId()方法");
        student.getStudentId();
    }
}

有興趣的小伙伴試一下,相信我,用System.out.println標(biāo)記一下每個函數(shù)執(zhí)行的先后順序,如果你全對了,下面的不用看了,大佬。

二、類的初始化步驟:

  • 初始化父類中的靜態(tài)成員變量和靜態(tài)代碼塊 ;
  • 初始化子類中的靜態(tài)成員變量和靜態(tài)代碼塊 ;
  • 初始化父類的普通成員變量和代碼塊,再執(zhí)行父類的構(gòu)造方法;
  • 初始化子類的普通成員變量和代碼塊,再執(zhí)行子類的構(gòu)造方法;

三、看看你寫對了沒?

package com.nezha.javase;

public class Person {

    private int personId;

    /**
     * 第一步,走父類無參構(gòu)造函數(shù)
     */
    public Person() {
        // 1、第一步,走父類無參構(gòu)造函數(shù)
        System.out.println("第一步,走父類無參構(gòu)造函數(shù)");
        System.out.println("");
        setId(100);
    }

    /**
     * 第三步,通過super.setId(id);走父類發(fā)方法
     * @param id
     */
    public void setId(int id) {
        System.out.println("第三步,通過super.setId(id);走父類發(fā)方法~~~id="+id);
        personId = id;
        System.out.println("在父類:studentId 被賦值為 " + personId);
        System.out.println("");
    }
}
package com.nezha.javase;

public class Student extends Person {

    private int studentId = 1;

    /**
     * 在走子類無參構(gòu)造函數(shù)前,會先執(zhí)行子類的普通成員變量初始化
     * 第五步,走子類無參構(gòu)造函數(shù)
     */
    public Student() {
        System.out.println("第五步,在走子類無參構(gòu)造函數(shù)前,會先執(zhí)行子類的普通成員變量初始化");
        System.out.println("第六步,走子類無參構(gòu)造函數(shù)");
        System.out.println("");
    }

    /**
     * 第二步,走子類方法
     *
     * 走完super.setId(id);,第四步,再回此方法
     * @param id
     */
    @Override
    public void setId(int id) {
        System.out.println("第二步,走子類方法~~id="+id);
        // 3、第三步,走子類方法
        super.setId(id);
        studentId = id;
        System.out.println("第四步,再回此方法,在子類:studentId 被賦值為 " + studentId);
        System.out.println("");
    }

    /**
     * 第六步,走getStudentId()
     */
    public void getStudentId() {
        // 4、打印出來的值是100
        System.out.println("第七步,走getStudentId()");
        System.out.println("studentId = " + studentId);
        System.out.println("");
    }
}
package com.nezha.javase;

public class Test1 {
    public static void main(String[] args) {
        Student1 student = new Student1();
        System.out.println("new Student() 完畢,開始調(diào)用getStudentId()方法");
        // 打印出來的值是100
        System.out.println("#推測~~打印出來的值是100");
        student.getStudentId();
    }
}

下面通過圖解JVM的方式,分析一下。

四、類的加載過程

1、加載

  • 通過一個類的全限定名獲取定義此類的二進(jìn)制字節(jié)流;
  • 將這個字節(jié)流代表的靜態(tài)存儲結(jié)構(gòu)轉(zhuǎn)化為方法區(qū)的運行時數(shù)據(jù)結(jié)構(gòu);
  • 在內(nèi)存中生成一個代表這個類的java.lang.Class對象,作為方法區(qū)這個類的各種數(shù)據(jù)的訪問入口;

2、鏈接

(1)驗證(Verify)

  • 目的在于確保Class文件的字節(jié)流中包含信息符合當(dāng)前虛擬機(jī)要求,保證被加載類的正確性,不會危害虛擬機(jī)自身安全;
  • 主要包括四種驗證:文件格式驗證、元數(shù)據(jù)驗證、字節(jié)碼驗證、符號引用驗證;

(2)準(zhǔn)備(Prepare)

  • 為類變量分配內(nèi)存并且設(shè)置該類變量的默認(rèn)初始值;
  • 這里不包含final修飾的static,因為final在編譯的時候就會分配了,準(zhǔn)備階段會顯示初始化;
  • 這里不會為實例變量分配初始化,類變量會分配在方法區(qū)中,而實例變量是會隨著對象一起分配到堆中;

(3)解析

  • 將常量池內(nèi)的符號引用轉(zhuǎn)換為直接引用的過程
  • 例如靜態(tài)代碼塊、靜態(tài)變量的顯示賦值
  • 事實上,解析操作往往會伴隨著JVM在執(zhí)行完初始化之后在執(zhí)行
  • 符號引用就是一組符號來描述所引用的目標(biāo)。符號引用的字面量形式明確定義在《Java虛擬機(jī)規(guī)范》的Class文件格式中。直接引用就是指- 向目標(biāo)的指針、相對偏移量或一個間接定位到目標(biāo)的句柄
  • 解析動作主要針對類或接口、字段、類方法、接口方法、方法類型等。對常量池中的CONSTANT_Filedref_info、CONSTANT_Class_info、CONSTANT_Methodref_info等。

3、初始化

  • 初始化階段就是執(zhí)行類構(gòu)造器方法的過程;
  • 此方法不需要定義,是javac編譯器自動收集類中的所有類變量的賦值動作和靜態(tài)代碼塊中的語句合并而來;
  • 構(gòu)造器方法中指令按語句在源文件中出現(xiàn)的順序執(zhí)行;
  • 類構(gòu)造器方法不同于類的構(gòu)造器。構(gòu)造器是虛擬機(jī)視角下的類構(gòu)造器;
  • 若該類具有父類,JVM會保證子類的類構(gòu)造器執(zhí)行前,父類的類構(gòu)造器已經(jīng)執(zhí)行完畢;
  • 虛擬機(jī)必須保證一個類的類構(gòu)造器方法在多線程下被同步加鎖;

五、類加載器的分類

JVM類加載器包括兩種,分別為引導(dǎo)類加載器(Bootstrap ClassLoader)和自定義類加載器(User-Defined ClassLoader)。

所有派生于抽象類ClassLoader的類加載器劃分為自定義類加載器。

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

  • 啟動類加載器是使用C/C++語言實現(xiàn)的,嵌套在JVM內(nèi)部;
  • Java的核心類庫都是使用引導(dǎo)類加載器加載的,比如String;
  • 沒有父加載器;
  • 是擴(kuò)展類加載器和應(yīng)用程序類加載器的父類加載器 ;
  • 出于安全考慮,Bootstrap啟動類加載器只加載包名為java、javax、sun等開頭的類 ;

2、擴(kuò)展類加載器

  • java語言編寫
  • 派生于ClassLoader類
  • 父類加載器為啟動類加載器
  • 從java.ext.dirs系統(tǒng)屬性所指定的目錄中加載類庫,或從JDK的安裝目錄jre/lib/ext子目錄(擴(kuò)展目錄)下加載類庫。如果用戶創(chuàng)建的jar放在此目錄下,也會自動由擴(kuò)展類加載器加載

3、應(yīng)用程序類加載器(系統(tǒng)類加載器)

  1. java語言編寫
  2. 派生于ClassLoader類
  3. 父類加載器為擴(kuò)展類加載器
  4. 它負(fù)責(zé)加載環(huán)境變量classpath或系統(tǒng)屬性java.class.path指定路徑下的類庫
  5. 該類加載器是程序中默認(rèn)的類加載器,一般來說,Java應(yīng)用的類都是由它來完成加載的
  6. 通過ClassLoader.getSystemClassLoader()方法可以獲得該類加載器

六、類加載器子系統(tǒng)的作用

類加載器子系統(tǒng)負(fù)責(zé)從文件系統(tǒng)或網(wǎng)絡(luò)中加載class文件,class文件在文件開頭有特定的文件標(biāo)識。

ClassLoader只負(fù)責(zé)class文件的加載,至于它是否可以運行,則有執(zhí)行引擎決定。

加載的類信息存放于一塊稱為方法區(qū)的內(nèi)存空間。除了類的信息外,方法區(qū)中還會存放運行時常量池的信息,可能還包括字符串字面量和數(shù)字常量(這部分常量信息是class文件中常量池部分的內(nèi)存映射)。

七、總結(jié)

類的初始化步驟,這看似非常基礎(chǔ)的話題,卻實打?qū)嵉碾y住了很多人,還總結(jié)了更為深入JVM的類的加載過程、類加載器的分類、類加載器的作用。

到此這篇關(guān)于一篇文章弄懂JVM類加載機(jī)制過程以及原理的文章就介紹到這了,更多相關(guān)JVM類加載機(jī)制過程及原理內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • 解決mybatis plus報錯Invalid bound statement (not found):問題

    解決mybatis plus報錯Invalid bound statement 

    在使用MyBatis時遇到InvalidBoundStatement異常,常因多個MapperScan配置沖突或者包掃描路徑設(shè)置錯誤,解決方法包括保留一個MapperScan聲明、檢查jar包沖突、確保命名空間和掃描路徑正確,使用@TableId注解指定主鍵
    2024-11-11
  • Java類初始化順序詳解

    Java類初始化順序詳解

    這篇文章主要介紹了Java類初始化順序詳解,java語言在使用過程中最先開始就是初始化,在工作中如果遇到什么問題需?要定位往往到最后也可能是初始化的問題,因此掌握初始化的順序很重要,需要的朋友可以參考下
    2023-08-08
  • python實戰(zhàn)之德州撲克第一步-發(fā)牌

    python實戰(zhàn)之德州撲克第一步-發(fā)牌

    這篇文章主要介紹了python實戰(zhàn)之德州撲克第一步-發(fā)牌,文中有非常詳細(xì)的代碼示例,對正在學(xué)習(xí)python的小伙伴們有非常好的幫助,需要的朋友可以參考下
    2021-04-04
  • Java中實現(xiàn)用戶之間的通訊方式

    Java中實現(xiàn)用戶之間的通訊方式

    在Java中實現(xiàn)用戶間通訊主要有兩種方法:Socket編程和WebSocket,Socket編程允許兩個設(shè)備間進(jìn)行數(shù)據(jù)交換,適用于基本的網(wǎng)絡(luò)通訊,本文提供了兩種方法的基本實現(xiàn)代碼和相關(guān)配置,幫助開發(fā)者根據(jù)需求選擇合適的通訊方式
    2024-09-09
  • Java String保存字符串的機(jī)制

    Java String保存字符串的機(jī)制

    Java中字符串以什么格式來存儲?Java 中的 Unicode 字符串會按照 Latin1或者 UTF16 的編碼格式保存在 String 中,本文就詳細(xì)的介紹了一下,感興趣的可以了解一下
    2021-05-05
  • Java的System.getProperty()方法獲取大全

    Java的System.getProperty()方法獲取大全

    這篇文章主要介紹了Java的System.getProperty()方法獲取大全,羅列了System.getProperty()方法獲取各類信息的用法,具有一定的參考借鑒價值,需要的朋友可以參考下
    2014-12-12
  • java教程之java注解annotation使用方法

    java教程之java注解annotation使用方法

    這篇文章主要介紹了java注解annotation使用方法,注解可以定義到方法上,類上,一個注解相當(dāng)與一個類,就相當(dāng)于實例了一個對象,加上了注解,就相當(dāng)于加了一個標(biāo)志
    2014-01-01
  • Java中靜態(tài)代碼塊、構(gòu)造代碼塊、構(gòu)造函數(shù)和普通代碼塊的區(qū)別

    Java中靜態(tài)代碼塊、構(gòu)造代碼塊、構(gòu)造函數(shù)和普通代碼塊的區(qū)別

    在Java中,靜態(tài)代碼塊、構(gòu)造代碼塊、構(gòu)造函數(shù)、普通代碼塊的執(zhí)行順序是一個筆試的考點,通過這篇文章希望大家能徹底了解它們之間的執(zhí)行順序,需要的朋友可以參考下
    2023-05-05
  • java二叉樹的遍歷方式詳解

    java二叉樹的遍歷方式詳解

    這篇文章主要為大家詳細(xì)介紹了java實現(xiàn)二叉樹遍歷的四種方式,具有一定的參考價值,感興趣的小伙伴們可以參考一下,希望能給你帶來幫助
    2021-08-08
  • IOC?容器啟動和Bean實例化兩個階段詳解

    IOC?容器啟動和Bean實例化兩個階段詳解

    這篇文章主要為大家介紹了IOC?容器啟動和Bean實例化兩個階段詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2022-08-08

最新評論