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

jvm虛擬機(jī)類(lèi)加載機(jī)制詳解

 更新時(shí)間:2022年04月19日 15:00:11   作者:我的Coder小屋  
本文主要介紹了 jvm虛擬機(jī)類(lèi)加載機(jī)制詳解,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧

1 概述

? Java虛擬機(jī)把描述類(lèi)的數(shù)據(jù)從Class文件加載到內(nèi)存, 并對(duì)數(shù)據(jù)進(jìn)行校驗(yàn)、轉(zhuǎn)化解析和初始化,最終形成可以被虛擬機(jī)直接使用的Java類(lèi)型,這個(gè)過(guò)程稱(chēng)為虛擬機(jī)的類(lèi)加載機(jī)制。在Java語(yǔ)言中,類(lèi)型的加載、連接和初始化都是在程序運(yùn)行期間完成的。

2 類(lèi)的加載時(shí)機(jī)

? 一個(gè)類(lèi)型從被加載到虛擬機(jī)內(nèi)存中開(kāi)始,到卸載出內(nèi)存為止,它的整個(gè)生命周期將會(huì)經(jīng)歷加載、驗(yàn)證、準(zhǔn)備、解析、初始化、使用和卸載七個(gè)階段,其中驗(yàn)證、準(zhǔn)備和解析三個(gè)部分統(tǒng)稱(chēng)為連接。發(fā)生順序如下:

在這里插入圖片描述

? 《Java虛擬機(jī)規(guī)范》嚴(yán)格規(guī)定有且只有六種情況必須立即對(duì)類(lèi)進(jìn)行“初始化”(加載、驗(yàn)證和準(zhǔn)備自然需要在此之前開(kāi)始):

  • 遇到new、getstatic、putstatic或invokestatic這四條字節(jié)碼指令時(shí),如果類(lèi)型沒(méi)有進(jìn)行初始化,則需要先觸發(fā)其初始化階段。能夠生成這四條指令的典型Java代碼場(chǎng)景有:
    • 使用new關(guān)鍵字實(shí)例化對(duì)象的時(shí)候
    • 讀取或設(shè)置一個(gè)類(lèi)型的靜態(tài)字段的時(shí)候
    • 調(diào)用一個(gè)類(lèi)型的靜態(tài)方法的時(shí)候
  • 使用java.lang.reflect包的方法對(duì)類(lèi)型進(jìn)行反射調(diào)用的時(shí)候,如果還沒(méi)被初始化,則需要先觸發(fā)其初始化。
  • 當(dāng)初始化類(lèi)的時(shí)候,如果發(fā)現(xiàn)其父類(lèi)還沒(méi)進(jìn)行過(guò)初始化,則需要先觸發(fā)其父類(lèi)的初始化。
  • 當(dāng)虛擬機(jī)啟動(dòng)時(shí),用戶(hù)需要指定一個(gè)要執(zhí)行的主類(lèi)。虛擬機(jī)會(huì)先初始化這個(gè)主類(lèi)。
  • jdk1.7新加入的動(dòng)態(tài)語(yǔ)言支持時(shí)。
  • 當(dāng)一個(gè)接口中定義了jdk8新加入的默認(rèn)方法時(shí)。

? 這六種場(chǎng)景的行為稱(chēng)為對(duì)一個(gè)類(lèi)型進(jìn)行主動(dòng)引用。除此之外,所有引用類(lèi)型的方式都不會(huì)觸發(fā)初始化,稱(chēng)為被動(dòng)引用。下面舉出被動(dòng)引用的例子

示例1:通過(guò)子類(lèi)引用父類(lèi)的靜態(tài)字段,不會(huì)導(dǎo)致子類(lèi)初始化

public class NotInitialization {
    public static void main(String[] args) {
        System.out.println(SubClass.value);  // 只會(huì)輸出“SuperClass init”,而不會(huì)輸出“subclass init”
        SuperClass[] superClasses = new SuperClass[10];  // 不會(huì)輸出“SuperClass init”
    }
}

class SuperClass {
    static {
        System.out.println("SuperClass init");
    }
    public static int value = 123;
}

class SubClass extends SuperClass {
    static {
        System.out.println("SubClass init!");
    }
}

示例2:常量在編譯階段會(huì)存入調(diào)用類(lèi)的常量池中,本質(zhì)上沒(méi)有直接引用到定義常量的類(lèi),因此不會(huì)觸發(fā)定義常量的初始化

public class NotInitialization {
    public static void main(String[] args) {
        System.out.println(ConstClass.HELLOWORLD);  // 不會(huì)輸出“ConstClass init!”,因?yàn)槌A恐苯哟鎯?chǔ)到常量池中。
    }
}
class ConstClass {
    static {
        System.out.println("ConstClass init!");
    }

    public static final String HELLOWORLD = "hello world";
}

class Test {
    static {
        i = 0;
    }
    static int i = 1;
}

3 類(lèi)的加載過(guò)程

3.1 加載

? 在加載階段,虛擬機(jī)需要完成以下三件事情:

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

3.2 驗(yàn)證

? 驗(yàn)證是連接階段的第一步,這一階段的目的是確保Class文件的字節(jié)流中包含的信息符合《Java虛擬機(jī)規(guī)范》的約束要求,保證這些信息不會(huì)危害虛擬機(jī)自身。

3.3 準(zhǔn)備

? 準(zhǔn)備階段是正式為類(lèi)中定義的變量(即靜態(tài)變量,被static修飾的變量)分配內(nèi)存并設(shè)置類(lèi)變量初始值的階段。

3.4 解析

? 解析階段是將常量池內(nèi)的符號(hào)引用替換為直接引用的過(guò)程。

3.5 初始化

? 初始化是類(lèi)加載過(guò)程的最后一個(gè)階段,直到初始化階段,Java虛擬機(jī)才真正開(kāi)始執(zhí)行類(lèi)中編寫(xiě)的Java程序代碼,將主導(dǎo)權(quán)移交給應(yīng)用程序。初始化階段就是執(zhí)行類(lèi)構(gòu)造器的()方法的過(guò)程。

  • ()方法與類(lèi)的構(gòu)造函數(shù)不同,它不需要顯示地調(diào)用父類(lèi)構(gòu)造器,Java虛擬機(jī)會(huì)保證在子類(lèi)的()方法執(zhí)行前,父類(lèi)的()方法已經(jīng)執(zhí)行完畢。因此在Java虛擬機(jī)中第一個(gè)被執(zhí)行的()方法肯定是Object。
  • 由于父類(lèi)的()方法先執(zhí)行,也就意味著父類(lèi)中定義的靜態(tài)語(yǔ)句塊要優(yōu)先于子類(lèi)的變量賦值操作,如下代碼:字段值將會(huì)是2而不是1。
public static void main(String[] args) {
    System.out.println(Sub.B);
}

static class Parent {
    public static int A = 1;
    static {
        A = 2;
    }
}

static class Sub extends Parent {
    public static int B = A;
}

4 類(lèi)加載器

? 類(lèi)加載器用于實(shí)現(xiàn)類(lèi)的加載動(dòng)作,JVM中內(nèi)置了三個(gè)重要的ClassLoader,除了BootstrapClassLoader其他類(lèi)加載器均由Java實(shí)現(xiàn)且全部繼承自java.lang.ClassLoader:

  • BootstrapClassLoader(啟動(dòng)類(lèi)加載器):最頂層的加載類(lèi),負(fù)責(zé)加載%JAVA_HOME%/lib目錄下的jar包和類(lèi)或者被-X:bootclasspathc參數(shù)指定的路徑下的所有類(lèi)。
  • Extension Class Loader(擴(kuò)展類(lèi)加載器):主要負(fù)責(zé)加載<JAVA_HOME>\lib\ext目錄中的所有類(lèi)庫(kù)。
  • AppClassLoader(應(yīng)用程序類(lèi)加載器):面向我們用戶(hù)的加載器,負(fù)責(zé)加載當(dāng)前應(yīng)用的classpath中的所有jar包和類(lèi)。

4.1 雙親委派模型

在這里插入圖片描述

? 如上圖:雙親委派模型的工作流程是如果一個(gè)類(lèi)加載器收到了類(lèi)加載的請(qǐng)求,它首先不會(huì)自己去嘗試加載這個(gè)類(lèi),而是把這個(gè)請(qǐng)求委派給父類(lèi)加載器去完成,每一個(gè)層次的類(lèi)加載器都是如此,因此所有的加載請(qǐng)求最終都應(yīng)該傳送到最頂層的啟動(dòng)類(lèi)加載器中,只有當(dāng)父加載器反饋?zhàn)约簾o(wú)法完成這個(gè)加載請(qǐng)求時(shí),子加載器才會(huì)嘗試自己去完成加載。

好處

Java中的類(lèi)隨著它的類(lèi)加載器一起具備了一種帶有優(yōu)先級(jí)的層次關(guān)系。

實(shí)現(xiàn)

private final ClassLoader parent; 
protected Class<?> loadClass(String name, boolean resolve)
        throws ClassNotFoundException
    {
        synchronized (getClassLoadingLock(name)) {
            // 首先,檢查請(qǐng)求的類(lèi)是否已經(jīng)被加載過(guò)
            Class<?> c = findLoadedClass(name);
            if (c == null) {
                long t0 = System.nanoTime();
                try {
                    if (parent != null) {//父加載器不為空,調(diào)用父加載器loadClass()方法處理
                        c = parent.loadClass(name, false);
                    } else {//父加載器為空,使用啟動(dòng)類(lèi)加載器 BootstrapClassLoader 加載
                        c = findBootstrapClassOrNull(name);
                    }
                } catch (ClassNotFoundException e) {
                   //拋出異常說(shuō)明父類(lèi)加載器無(wú)法完成加載請(qǐng)求
                }
                
                if (c == null) {
                    long t1 = System.nanoTime();
                    //自己嘗試加載
                    c = findClass(name);

                    // this is the defining class loader; record the stats
                    sun.misc.PerfCounter.getParentDelegationTime().addTime(t1 - t0);
                    sun.misc.PerfCounter.getFindClassTime().addElapsedTimeFrom(t1);
                    sun.misc.PerfCounter.getFindClasses().increment();
                }
            }
            if (resolve) {
                resolveClass(c);
            }
            return c;
        }
    }

4.2 破壞雙親委派模型

? 雙親委派模型主要出現(xiàn)過(guò)3次較大規(guī)模的“被破壞”的情況。具體想了解的詳看《深入理解Java虛擬機(jī)》。

到此這篇關(guān)于 jvm虛擬機(jī)類(lèi)加載機(jī)制詳解的文章就介紹到這了,更多相關(guān) jvm虛擬機(jī)類(lèi)加載內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • Spring Boot 會(huì)員管理系統(tǒng)之處理文件上傳功能

    Spring Boot 會(huì)員管理系統(tǒng)之處理文件上傳功能

    Spring Boot會(huì)員管理系統(tǒng)的中,需要涉及到Spring框架,SpringMVC框架,Hibernate框架,thymeleaf模板引擎。這篇文章主要介紹了Spring Boot會(huì)員管理系統(tǒng)之處理文件上傳功能,需要的朋友可以參考下
    2018-03-03
  • 利用ScriptEngineManager實(shí)現(xiàn)字符串公式靈活計(jì)算的方法

    利用ScriptEngineManager實(shí)現(xiàn)字符串公式靈活計(jì)算的方法

    今天小編就為大家分享一篇利用ScriptEngineManager實(shí)現(xiàn)字符串公式靈活計(jì)算的方法,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧
    2018-07-07
  • java中元素排序Comparable和Comparator的區(qū)別

    java中元素排序Comparable和Comparator的區(qū)別

    本文主要介紹了java中元素排序Comparable和Comparator的區(qū)別,文中通過(guò)示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2021-12-12
  • 基于Zookeeper實(shí)現(xiàn)分布式鎖詳解

    基于Zookeeper實(shí)現(xiàn)分布式鎖詳解

    Zookeeper是一個(gè)分布式的,開(kāi)源的分布式應(yīng)用程序協(xié)調(diào)服務(wù),是Hadoop和hbase的重要組件。這篇文章主要介紹了通過(guò)Zookeeper實(shí)現(xiàn)分布式鎖,感興趣的朋友可以了解一下
    2021-12-12
  • java如何用Processing生成馬賽克風(fēng)格的圖像

    java如何用Processing生成馬賽克風(fēng)格的圖像

    這篇文章主要介紹了如何用java如何用Processing生成馬賽克風(fēng)格的圖像,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2020-03-03
  • Java中的BlockingQueue阻塞隊(duì)列原理以及實(shí)現(xiàn)詳解

    Java中的BlockingQueue阻塞隊(duì)列原理以及實(shí)現(xiàn)詳解

    這篇文章主要介紹了Java中的BlockingQueue阻塞隊(duì)列原理以及實(shí)現(xiàn)詳解,在最常見(jiàn)的使用到這個(gè)阻塞隊(duì)列的地方,就是我們耳熟能詳?shù)木€程池里面了,作為我們線程池的一大最大參與者,也是AQS的一個(gè)具體實(shí)現(xiàn),需要的朋友可以參考下
    2023-12-12
  • mybatis類(lèi)型轉(zhuǎn)換器如何實(shí)現(xiàn)數(shù)據(jù)加解密

    mybatis類(lèi)型轉(zhuǎn)換器如何實(shí)現(xiàn)數(shù)據(jù)加解密

    這篇文章主要介紹了mybatis類(lèi)型轉(zhuǎn)換器如何實(shí)現(xiàn)數(shù)據(jù)加解密,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2021-09-09
  • 詳解SpringBoot中的tomcat優(yōu)化和修改

    詳解SpringBoot中的tomcat優(yōu)化和修改

    這篇文章主要介紹了詳解SpringBoot中的tomcat優(yōu)化和修改,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2020-09-09
  • tk-mybatis整合springBoot使用兩個(gè)數(shù)據(jù)源的方法

    tk-mybatis整合springBoot使用兩個(gè)數(shù)據(jù)源的方法

    單純的使用mybaits進(jìn)行多數(shù)據(jù)配置網(wǎng)上資料很多,但是關(guān)于tk-mybaits多數(shù)據(jù)源配置沒(méi)有相關(guān)材料,本文就詳細(xì)的介紹一下如何使用,感興趣的可以了解一下
    2021-12-12
  • java?Spring?Boot的介紹與初體驗(yàn)

    java?Spring?Boot的介紹與初體驗(yàn)

    大家好,本篇文章主要講的是java?Spring?Boot的介紹與初體驗(yàn),感興趣的同學(xué)趕快來(lái)看一看吧,對(duì)你有幫助的話記得收藏一下
    2022-01-01

最新評(píng)論