精品欧美一区二区三区在线观看 _久久久久国色av免费观看性色_国产精品久久在线观看_亚洲第一综合网站_91精品又粗又猛又爽_小泽玛利亚一区二区免费_91亚洲精品国偷拍自产在线观看 _久久精品视频在线播放_美女精品久久久_欧美日韩国产成人在线

面試官:說說類加載的幾個階段

開發(fā) 前端
當一個類加載器負責加載某個Class文件時,該Class所依賴的和引用的其他Class也將由該類加載器負責載入,除非顯示使用另外一個類加載器來加載。

一、摘要

我們知道 Java 是先通過編譯器將.java類文件轉成.class字節(jié)碼文件,然后再通過虛擬機將.class字節(jié)碼文件加載到內(nèi)存中來實現(xiàn)應用程序的運行。

那么虛擬機是什么時候加載class文件?如何加載class文件?class文件進入到虛擬機后發(fā)生了哪些變化?

今天我們就一起來了解一下,虛擬機是如何加載類文件的。

二、類加載的時機

經(jīng)常有面試官問,“類什么時候加載”和“類什么時候初始化”,從內(nèi)容上來說,似乎都在問同一個問題:class文件是什么時候被虛擬機加載到內(nèi)存中,并進入可以使用的狀態(tài)?

從虛擬機角度來說,加載和初始化是類的加載過程中的兩個階段。

對于“什么時候加載”,Java 虛擬機規(guī)范中并沒有約束,每個虛擬機實例都可以按自身需要來自由實現(xiàn)。但基本上都遵循類在進行初始化之前,需要先進行加載class文件。

對于“什么時候初始化”,Java 虛擬機規(guī)范有明確的規(guī)定,當符合以下條件時(包括但不限),并且虛擬機在內(nèi)存中沒有找到對應的類信息,必須對類進行“初始化”操作:

  • 使用new實例化對象時,讀取或者設置一個類的靜態(tài)字段或方法時
  • 反射調(diào)用時,例如Class.forName("com.xxx.Test")
  • 初始化一個類的子類,會首先初始化子類的父類
  • Java 虛擬機啟動時標明的啟動類,比如main方法所在的類
  • JDK8 之后,接口中存在default方法,這個接口的實現(xiàn)類初始化時,接口會在它之前進行初始化

類在初始化開始之前,需要先經(jīng)歷加載、驗證、準備、解析這四個階段的操作。

下面我們一起來看看類的加載過程。

三、類的加載過程

當一個類需要被加載到虛擬機中執(zhí)行時,虛擬機會通過類加載器,將其.class文件中的字節(jié)碼信息在內(nèi)存中轉化成一個具體的java.lang.Class對象,以便被調(diào)用執(zhí)行。

類從被加載到虛擬機內(nèi)存中開始,到卸載出內(nèi)存,整個生命周期包括七個階段:加載、驗證、準備、解析、初始化、使用和卸載,可以用如下圖來簡要概括。

圖片圖片

其中類加載的過程,可以用三個步驟(五個階段)來簡要描述:加載 -> 連接(驗證、準備、解析)-> 初始化。(驗證、準備、解析這3個階段統(tǒng)稱為連接)

其次加載、驗證、準備和初始化這四個階段發(fā)生的順序是確定的,必須按照這種順序按部就班的開始,而解析階段則不一定。在某些情況下解析階段可以在初始化階段之后開始,這是為了支持 Java 語言的運行時綁定,也稱為動態(tài)綁定或晚期綁定。

同時,這五個階段并不是嚴格意義上的按順序完成,在類加載的過程中,這些階段會互相混合,可能有些階段完成了,有些階段沒有完成,會交叉運行,最終完成類的加載和初始化。

接下來依此分解一下加載、驗證、準備、解析、初始化這五個步驟,這五個步驟組成了一個完整的類加載過程。使用沒什么好說的,卸載通常屬于 GC 的工作,當一個類沒有被任何地方引用并且類加載器已被 GC 回收,GC 會將當前類進行卸載,在后續(xù)的文章我們會介紹 GC 的工作機制。

3.1、加載

加載是類加載的過程的第一個階段,這個階段的主要工作是查找并加載類的二進制數(shù)據(jù),在虛擬機中,類的加載有兩種觸發(fā)方式:

  • 預先加載:指的是虛擬機啟動時加載,例如JAVA_HOME/lib/下的rt.jar下的.class文件,這個jar包里面包含了程序運行時常用的文件內(nèi)容,例如java.lang.*、java.util.*、java.io.*等等,因此會隨著虛擬機啟動時一起加載到內(nèi)存中。要證明這一點很簡單,自己可以寫一個空的main函數(shù),設置虛擬機參數(shù)為-XX:+TraceClassLoading,運行程序就可以獲取類加載的全部信息
  • 運行時加載:虛擬機在用到一個.class文件的時候,會先去內(nèi)存中查看一下這個.class文件有沒有被加載,如果沒有,就會按照類的全限定名來加載這個類;如果有,就不會加載。

無論是哪種觸發(fā)方式,虛擬機在加載.class文件時,都會做以下三件事情:

  • 1.通過類的全限定名定位.class文件,并獲取其二進制字節(jié)流
  • 2.將類信息、靜態(tài)變量、字節(jié)碼、常量這些.class文件中的內(nèi)容放入運行時數(shù)據(jù)區(qū)的方法區(qū)中
  • 3.在內(nèi)存中生成一個代表這個.class文件的java.lang.Class對象,作為方法區(qū)這個類的各種數(shù)據(jù)的訪問入口,一般這個java.lang.Class對象會存在 Java 堆中

虛擬機規(guī)范對這三點的要求并不具體,因此具體虛擬機實現(xiàn)的靈活度都很大。比如第一條,沒有指明二進制字節(jié)流要從哪里來,單單就這一條,就能變出許多花樣來,比如下面幾種加載方式:

  • 從 zip、jar、ear、war 等歸檔文件中加載.class文件
  • 通過網(wǎng)絡下載并加載.class文件,典型應用就是 Applet
  • 將Java源文件動態(tài)編譯為.class文件,典型應用就是動態(tài)代理技術
  • 從數(shù)據(jù)庫中提取.class文件并進行加載

總的來說,加載階段(準確地說,是加載階段獲取類的二進制字節(jié)流的動作)對于開發(fā)者來說是可控性最強的一個階段。因為開發(fā)者既可以使用系統(tǒng)提供的類加載器來完成加載,也可以自定義類加載器來完成加載。

3.2、驗證

驗證是連接階段的第一步,這一階段的目的是為了確保.class文件的字節(jié)流中包含的信息符合當前虛擬機的要求,并且不會危害虛擬機自身的安全。

Java 語言本身是比較安全的語言,但是正如上面說到的.class文件未必是從 Java 源碼編譯而來,可以使用任何途徑來生成并加載。虛擬機如果不檢查輸入的字節(jié)流,對其完全信任的話,很可能會因為載入了有害的字節(jié)流而導致系統(tǒng)崩潰,所以驗證是虛擬機對自身保護的一項重要工作。

驗證階段大致會完成 4 項檢驗工作:

  • 文件格式驗證:驗證字節(jié)流是否符合Class文件格式的規(guī)范,例如:是否以0xCAFEBABE開頭、主次版本號是否在當前虛擬機的處理范圍之內(nèi)、常量池中的常量是否有不被支持的類型等
  • 元數(shù)據(jù)驗證:對字節(jié)碼描述的元數(shù)據(jù)信息進行語義分析,要符合 Java 語言規(guī)范,例如:是否繼承了不允許被繼承的類(例如 final 修飾過的)、類中的字段、方法是否和父類產(chǎn)生矛盾等等
  • 字節(jié)碼驗證:對類的方法體進行校驗分析,確保這些方法在運行時是合法的、符合邏輯的
  • 符號引用驗證:確保解析動作能正確執(zhí)行,例如:確保符號引用的全限定名能找到對應的類,符號引用中的類、字段、方法允許被當前類所訪問等等

驗證階段是非常重要的,但不是必須的,它對程序運行期沒有影響,如果所引用的類經(jīng)過反復驗證,那么可以考慮采用-Xverify:none參數(shù)來關閉大部分的類驗證措施,以縮短虛擬機類加載的時間。

3.3、準備

準備是連接階段的第二步,這個階段的主要工作是正式為類變量分配內(nèi)存并設置其初始值的階段,這些變量所使用的內(nèi)存都將在方法區(qū)中分配。

不過這個階段,有幾個知識點需要注意一下:

  • 1.這時候進行內(nèi)存分配的僅僅是類變量(被static修飾的變量),而不是實例變量,實例變量將會在對象實例化的時候隨著對象一起分配在 Java 堆中
  • 2.這個階段會設置變量的初始值,值為數(shù)據(jù)類型默認的零值(如 0、0L、null、false 等),不是在代碼中被顯式地賦予的值;但是當字段被final修飾時,這個初始值就是代碼中顯式地賦予的值
  • 3.在 JDK1.8 取消永久代后,方法區(qū)變成了一個邏輯上的區(qū)域,這些類變量的內(nèi)存實際上是分配在 Java 堆中的,跟 JDK1.7 及以前的版本稍有不同

關于第二個知識點,我們舉個簡單的例子進行講解,比如public static int value = 123,value在準備階段過后是0而不是123。

因為這時候尚未開始執(zhí)行任何 Java 方法,把value賦值為123的public static指令是在程序編譯后存放于類構造器<clinit>()方法之中的,因此把value賦值為123的動作將在初始化階段才會執(zhí)行。

假如被final修飾,比如public static final int value = 123就不一樣了,編譯時Javac將會為value生成ConstantValue屬性,在準備階段,虛擬機就會給value賦值為123,因為這個變量無法被修改,會存入類的常量池中。

各個數(shù)據(jù)類型的零值如下圖:

數(shù)據(jù)類型

零值

byte

0

short

0

int

0

long

0L

float

0.0f

double

0.0d

boolean

false

char

\u0000

reference

null

3.4、解析

解析是連接階段的第三步,這個階段的主要工作是虛擬機會把這個.class文件中常量池內(nèi)的符號引用轉換為直接引用。

主要解析的是類或接口、字段、方法等符號引用,我們可以把解析階段中符號引用轉換為直接引用的過程,理解為當前加載的這個類和它所引用的類,正式進行“連接“的過程。

我們先來了解一下符號引用和直接引用有什么區(qū)別:

  • 符號引用:這個其實是屬于編譯原理方面的概念,Java 代碼在編譯期間,是不知道最終引用的類型,具體指向內(nèi)存中哪個位置的,這時候會使用一個符號引用來表示具體引用的目標是"誰",符號引用和虛擬機的內(nèi)存布局是沒有關系的
  • 直接引用:指的是可以直接或間接指向目標內(nèi)存位置的指針或句柄,直接引用和虛擬機實現(xiàn)的內(nèi)存布局是有關系的

符號引用轉換為直接引用,可以理解成將某個符號與虛擬機中的內(nèi)存位置建立連接,通過指針或句柄來直接訪問目標。

與此同時,同一個符號引用在不同的虛擬機實現(xiàn)上翻譯出來的直接引用一般不會相同。

3.5、初始化

初始化是類加載的過程的最后一步,這個階段的主要工作是執(zhí)行類構造器 <clinit>()方法的過程。

簡單的說,初始化階段做的事就是給static變量賦予用戶指定的值,同時類中如果存在static代碼塊,也會執(zhí)行這個靜態(tài)代碼塊里面的代碼。

初始化階段,虛擬機大致依此會進行如下幾個步驟的操作:

  • 1.檢查這個類是否被加載和連接,如果沒有,則程序先加載并連接該類
  • 2.檢查該類的直接父類有沒有被初始化,如果沒有,則先初始化其直接父類
  • 3.類中如果有多個初始化語句,比如多個static代碼塊,則依次執(zhí)行這些初始化語句

有個地方需要注意的是:虛擬機會保證類的初始化在多線程環(huán)境中被正確地加鎖、同步執(zhí)行,所以無需擔心是否會出現(xiàn)變量初始化時線程不安全的問題。

如果多個線程同時去初始化一個類,那么只會有一個線程去執(zhí)行這個類的<clinit>()方法,其他線程都會阻塞等待,直到<clinit>()方法執(zhí)行完畢。同時,同一個類加載器下,一個類只會初始化一次,如果檢查到當前類沒有初始化,執(zhí)行初始化;反之,不會執(zhí)行初始化。

與此同時,只有當對類的主動使用的時候才會觸發(fā)類的初始化,觸發(fā)時機主要有以下幾種場景:

  • 1.創(chuàng)建類的實例對象,比如new一個對象操作
  • 2.訪問某個類或接口的靜態(tài)變量,或者對該靜態(tài)變量賦值
  • 3.調(diào)用類的靜態(tài)方法
  • 4.反射操作,比如Class.forName("xxx")
  • 5.初始化某個類的子類,則其父類也會被初始化,并且父類具有優(yōu)先被初始化的優(yōu)勢
  • 6.Java 虛擬機啟動時被標明為啟動類的類,比如SpringBootApplication入口類

最后,<clinit>()方法和<init>()方法是不同的,一個是類構造器初始化,一個是實例構造器初始化,千萬別搞混淆了啊。

3.6、小結

當一個符合 Java 虛擬機規(guī)范的.class字節(jié)碼文件,經(jīng)歷加載、驗證、準備、解析、初始化這些 5 個階段相互協(xié)作執(zhí)行完成之后,虛擬機會將此文件的二進制數(shù)據(jù)導入運行時數(shù)據(jù)區(qū)的方法區(qū)內(nèi),然后在堆內(nèi)存中,創(chuàng)建一個java.lang.Class類的對象,這個對象描述了這個類所有的信息,同時提供了這個類在方法區(qū)的訪問入口。

可以用如下圖來簡要描述。

圖片圖片

與此同時,在方法區(qū)中,使用同一加載器的情況下,每個類只會有一份Class字節(jié)流信息;在堆內(nèi)存中,使用同一加載器的情況下,每個類也只會有一份java.lang.Class類的對象。

四、類加載器

在上文類的加載過程中,我們有提到在加載階段,通過一個類的全限定名來獲取此類的二進制字節(jié)流操作,其實類加載器就是用來實現(xiàn)這個操作的。

在虛擬機中,任何一個類,都需要由加載它的類加載器和這個類本身一同確立其唯一性,每一個類加載器,都擁有一個獨立的類名稱空間,對于類也同樣如此。

簡單的說,在虛擬機中看兩個類是否相同,只有在這兩個類是由同一個類加載器加載的前提下才有意義,否則即使這兩個類來源于同一個.class文件,被同一個虛擬機加載,但是它們的類加載器不同,這兩個類必定不相等。

當年為了滿足瀏覽器上 Java Applet 的需求,Java 的開發(fā)團隊設計了類加載器,它獨立于 Java 虛擬機外部,同時也允許用戶按自身需要自行實現(xiàn)類加載器。通過類加載器,可以讓同一個類可以實現(xiàn)訪問隔離、OSGi、程序熱部署等等場景。發(fā)展至今,類加載器已經(jīng)是 Java 技術體系的一塊重要基石。

4.1、類加載器介紹

如果要查找類加載器,通過Thread.currentThread().getContextClassLoader()方法可以獲取。

簡單示例如下:

public class ClassLoaderTest {

    public static void main(String[] args) {
        ClassLoader loader = Thread.currentThread().getContextClassLoader();
        System.out.println("current loader:" +  loader);
        System.out.println("parent loader:" +  loader.getParent());
        System.out.println("parent parent loader:" +  loader.getParent().getParent());
    }
}

輸出結果如下:

current loader:sun.misc.Launcher$AppClassLoader@18b4aac2
parent loader:sun.misc.Launcher$ExtClassLoader@511d50c0
parent parent loader:null

從運行結果可以看到,當前的類加載器是AppClassLoader,它的上一級是ExtClassLoader,再上一級是null。

其實ExtClassLoader的上一級是有類加載器的,它叫Bootstrap ClassLoader,是一個啟動類加載器,由 C++ 實現(xiàn),不是 ClassLoader 子類,因此以 null 作為結果返回。

這幾種類加載器的層次關系,可以用如下圖來描述。

圖片圖片

它們之間的啟動流程,可以通過以下內(nèi)容來簡單描述:

  • 1.在虛擬機啟動后,會優(yōu)先初始化Bootstrap Classloader
  • 2.接著Bootstrap Classloader負責加載ExtClassLoader,并且將 ExtClassLoader的父加載器設置為Bootstrap Classloader
  • 3Bootstrap Classloader加載完ExtClassLoader后,就會加載AppClassLoader,并且將AppClassLoader的父加載器指定為 ExtClassLoader

因此,在加載 Java 應用程序中的class文件時,這里的父類加載器并不是通過繼承關系來實現(xiàn)的,而是互相配合進行加載。

站在虛擬機的角度,只存在兩種不同的類加載器:

  • 啟動類加載器:它由 C++ 實現(xiàn)(這里僅限于 Hotspot,不同的虛擬機可能實現(xiàn)不太一樣),是虛擬機自身的一部分
  • 其它類加載器:這些類加載器都由 Java 實現(xiàn),獨立于虛擬機之外,并且全部繼承自抽象類java.lang.ClassLoader,比如ExtClassLoader、AppClassLoader等,這些類加載器需要由啟動類加載器加載到內(nèi)存中之后才能去加載其他的類

站在開發(fā)者的角度,類加載器大致可以劃分為三類:

  • 啟動類加載器:比如Bootstrap ClassLoader,負責加載<JAVA_HOME>\lib目錄,或者被-Xbootclasspath參數(shù)制定的路徑,例如jre/lib/rt.jar里所有的class文件。同時,啟動類加載器是無法被 Java 程序直接引用的
  • 拓展類加載器:比如Extension ClassLoader,負責加載 Java 平臺中擴展功能的一些 jar 包,包括<JAVA_HOME>\lib\ext目錄中或java.ext.dirs指定目錄下的 jar 包。同時,開發(fā)者可以直接使用擴展類加載器
  • 應用程序類加載器:比如Application ClassLoader,負責加載ClassPath路徑下所有 jar 包,如果應用程序中沒有自定義過自己的類加載器,一般情況下它就是程序中默認的類加載器

當然,如果有必要,也可以自定義類加載器,因為 JVM 自帶的 ClassLoader 只懂得從本地文件系統(tǒng)中加載標準的class文件,如果要從特定的場所取得class文件,例如數(shù)據(jù)庫中和網(wǎng)絡中,此時可以自己編寫對應的 ClassLoader 類加載器。

4.2、雙親委派模型

在上文中我們提到,在虛擬機中,任何一個類由加載它的類加載器和這個類一同來確立其唯一性。

也就是說,JVM 對類的唯一標識,可以簡單的理解為由ClassLoader id + PackageName + ClassName組成,因此在一個運行程序中有可能存在兩個包名和類名完全一致的類,但是如果這兩個類不是由一個 ClassLoader 加載,會被視為兩個不同的類,此時就無法將一個類的實例強轉為另外一個類,這就是類加載器的隔離性。

為了解決類加載器的隔離問題,JVM 引入了雙親委派模型。

雙親委派模式,可以用一句話來說表達:任何一個類加載器在接到一個類的加載請求時,都會先讓其父類進行加載,只有父類無法加載(或者沒有父類)的情況下,才嘗試自己加載。

大致流程圖如下:

圖片圖片

使用雙親委派模式,可以保證,每一個類只會有一個類加載器。例如 Java 最基礎的 Object 類,它存放在 rt.jar 之中,這是 Bootstrap 的職責范圍,當向上委派到 Bootstrap 時就會被加載。

但如果沒有使用雙親委派模式,可以任由自定義加載器進行加載的話,Java 這些核心類的 API 就會被隨意篡改,無法做到一致性加載效果。

JDK 中ClassLoader.loadClass()類加載器中的加載類的方法,部分核心源碼如下:

public Class<?> loadClass(String name) throws ClassNotFoundException {
    return loadClass(name, false);
}
protected Class<?> loadClass(String name, boolean resolve)
        throws ClassNotFoundException
{
    // 1.首先要保證線程安全
    synchronized (getClassLoadingLock(name)) {
        // 2.先判斷這個類是否被加載過,如果加載過,直接跳過
        Class<?> c = findLoadedClass(name);
        if (c == null) {
            long t0 = System.nanoTime();
            try {
                // 3.有父類,優(yōu)先交給父類嘗試加載;如果為空,使用BootstrapClassLoader類加載器
                if (parent != null) {
                    c = parent.loadClass(name, false);
                } else {
                    c = findBootstrapClassOrNull(name);
                }
            } catch (ClassNotFoundException e) {
                // 父類加載失敗,這里捕獲異常,但不需要做任何處理
            }

            // 4.沒有父類,或者父類無法加載,嘗試自己加載
            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.3、自定義類加載器

在上文中我們提及過,針對某些特定場景,比如通過網(wǎng)絡來傳輸 Java 類的字節(jié)碼文件,為保證安全性,這些字節(jié)碼經(jīng)過了加密處理,這時系統(tǒng)提供的類加載器就無法對其進行加載,此時我們可以自定義一個類加載器來完成文件的加載。

自定義類加載器也需要繼承ClassLoader類,簡單示例如下:

public class CustomClassLoader extends ClassLoader {

    private String classPath;

    public CustomClassLoader(String classPath) {
        this.classPath = classPath;
    }

    @Override
    protected Class<?> findClass(String name) throws ClassNotFoundException {
        Class<?> c = findLoadedClass(name);
        if (c == null) {
            byte[] data = loadClassData(name);
            if (data == null) {
                throw new ClassNotFoundException();
            }
            return defineClass(name, data, 0, data.length);
        }
        return null;
    }

    protected byte[] loadClassData(String name) {
        try {
            // package -> file folder
            name = name.replace(".", "http://");
            FileInputStream fis = new FileInputStream(new File(classPath + "http://" + name + ".class"));
            ByteArrayOutputStream baos = new ByteArrayOutputStream();
            int len = -1;
            byte[] b = new byte[2048];
            while ((len = fis.read(b)) != -1) {
                baos.write(b, 0, len);
            }
            fis.close();
            return baos.toByteArray();
        } catch (IOException e) {
            e.printStackTrace();
        }
        return null;
    }
}

相關的測試類如下:

package com.example;

public class ClassLoaderTest {

    public static void main(String[] args) {
        ClassLoader loader = Thread.currentThread().getContextClassLoader();
        System.out.println("current loader:" +  loader);
    }
}

將ClassLoaderTest.java源文件放在指定目錄下,并通過javac命令編譯成ClassLoaderTest.class,最后進行測試。

public class CustomClassLoaderTest {

    public static void main(String[] args) throws Exception {
        String classPath = "/Downloads";
        CustomClassLoader customClassLoader = new CustomClassLoader(classPath);
        Class<?> testClass = customClassLoader.loadClass("com.example.ClassLoaderTest");
        Object obj = testClass.newInstance();
        System.out.println(obj.getClass().getClassLoader());
    }
}

輸出結果:

com.example.CustomClassLoader@60e53b93

在實際使用過程中,最好不要重寫loadClass方法,避免破壞雙親委派模型。

4.4、加載類的幾種方式

在類加載器中,有三種方式可以實現(xiàn)類的加載。

  • 1.通過命令行啟動應用時由 JVM 初始化加載,在上文已提及過
  • 2.通過Class.forName()方法動態(tài)加載
  • 3.通過ClassLoader.loadClass()方法動態(tài)加載

其中Class.forName()和ClassLoader.loadClass()加載方法,稍有區(qū)別:

  • Class.forName():表示將類的.class文件加載到 JVM 中之后,還會對類進行解釋,執(zhí)行類中的static方法塊;
  • Class.forName(name, initialize, loader):支持通過參數(shù)來控制是否執(zhí)行類中的static方法塊;
  • ClassLoader.loadClass():它只將類的.class文件加載到 JVM,但是不執(zhí)行類中的static方法塊,只有在newInstance()才會去執(zhí)行static方法塊;

我們可以看一個簡單的例子!

public class ClassTest {

    static {
        System.out.println("初始化靜態(tài)代碼塊!");
    }
}
public class CustomClassLoaderTest {

    public static void main(String[] args) throws Exception {
        // 獲取當前系統(tǒng)類加載器
        ClassLoader classLoader = Thread.currentThread().getContextClassLoader();

        // 1.使用Class.forName()來加載類,默認會執(zhí)行初始化靜態(tài)代碼塊
        Class.forName(ClassTest.class.getName());

        // 2.使用Class.forName()來加載類,指定false,不會執(zhí)行初始化靜態(tài)代碼塊
//        Class.forName(ClassTest.class.getName(), false, classLoader);

        // 3.使用ClassLoader.loadClass()來加載類,不會執(zhí)行初始化靜態(tài)代碼塊
//        classLoader.loadClass(ClassTest.class.getName());
    }
}

運行結果如下:

初始化靜態(tài)代碼塊!

切換不同的加載方式,會有不同的輸出結果!

4.5、小結

從以上的介紹中,針對類加載器的機制,我們可以總結出以下幾點:

  • 全盤負責:當一個類加載器負責加載某個Class文件時,該Class所依賴的和引用的其他Class也將由該類加載器負責載入,除非顯示使用另外一個類加載器來加載
  • 雙親委派:在接受類加載請求時,會讓父類加載器試圖加載該類,只有在父類加載器無法加載該類或者沒有父類時,才嘗試從自己的類路徑中加載該類
  • 按需加載:用戶創(chuàng)建的類,通常加載是按需進行的,只有使用了才會被類加載器加載
  • 緩存機制:有被加載過的Class文件都會被緩存,當要使用某個Class時,會先去緩存查找,如果緩存中沒有才會讀取Class文件進行加載。這就是為什么修改了Class文件后,必須重啟 JVM,程序的修改才會生效的原因

五、小結

本文從類的加載過程到類加載器,做了一次知識內(nèi)容講解,內(nèi)容比較多,如果有描述不對的地方,歡迎大家留言指出,不勝感激!

六、參考

1.https://zhuanlan.zhihu.com/p/25228545

2.http://www.ityouknow.com/jvm/2017/08/19/class-loading-principle.html

3.https://www.cnblogs.com/xrq730/p/4844915.html

4.https://www.cnblogs.com/xrq730/p/4845144.html

責任編輯:武曉燕 來源: Java極客技術
相關推薦

2024-11-19 15:13:02

2025-04-16 00:00:01

JWT客戶端存儲加密令

2023-12-27 18:16:39

MVCC隔離級別幻讀

2025-04-08 00:00:00

@AsyncSpring異步

2024-08-22 10:39:50

@Async注解代理

2024-03-05 10:33:39

AOPSpring編程

2024-05-30 08:04:20

Netty核心組件架構

2024-03-14 14:56:22

反射Java數(shù)據(jù)庫連接

2021-11-25 10:18:42

RESTfulJava互聯(lián)網(wǎng)

2024-07-31 08:28:37

DMAIOMMap

2024-12-06 07:00:00

2024-09-20 08:36:43

零拷貝數(shù)據(jù)傳輸DMA

2024-03-11 18:18:58

項目Spring線程池

2024-03-22 06:56:24

零拷貝技術數(shù)據(jù)傳輸數(shù)據(jù)拷貝

2021-08-09 07:47:40

Git面試版本

2020-07-02 07:52:11

RedisHash映射

2024-02-29 16:49:20

volatileJava并發(fā)編程

2024-08-29 16:30:27

2024-08-12 17:36:54

2021-07-28 10:08:19

類加載代碼塊面試
點贊
收藏

51CTO技術棧公眾號

欧美日韩一区小说| av在线播放一区二区三区| 最好看的2019的中文字幕视频| 少妇一级淫免费播放| 91亚洲天堂| 99久久夜色精品国产网站| 国产精品视频自拍| 国产精品suv一区二区69| 国产欧美日韩精品一区二区免费 | sis001欧美| 国产精品三级电影| 国产日韩精品推荐| 亚洲天堂自拍偷拍| 亚洲精品乱码| 日韩在线播放一区| www.超碰97| 国产精品日本一区二区三区在线| 日韩欧美在线观看| 日韩国产小视频| 中文字幕日本在线观看| 99精品视频一区二区| 成人国产亚洲精品a区天堂华泰| 亚州国产精品视频| 你懂的成人av| 日韩中文字幕在线精品| 国产精品jizz| 精品淫伦v久久水蜜桃| 欧美一区二区观看视频| 免费看污黄网站| 伊人久久视频| 天天影视色香欲综合网老头| 大地资源网在线观看免费官网| 国产三区四区在线观看| 91免费看`日韩一区二区| 51精品国产人成在线观看 | 久久精品一区二区三区四区五区| 偷拍一区二区| 日韩av在线网| 蜜臀av粉嫩av懂色av| 日韩精品成人在线观看| 91 com成人网| 亚洲国产综合av| 亚洲福利影视| 在线不卡的av| 中文字幕av专区| 2019年精品视频自拍| 日本精品视频一区二区三区| 成人一级片网站| 性xxxxfreexxxxx欧美丶| 午夜一区二区三区视频| 久久久久久免费看| 成人免费观看在线观看| 亚洲成人在线免费| 六月婷婷在线视频| 欧美gv在线| 欧美性猛交xxxx免费看| 99蜜桃臀久久久欧美精品网站| 三级在线观看视频| 日韩欧美在线观看| 久草福利视频在线| 国内精品伊人| 欧美一区二区免费视频| 一区二区在线免费观看视频| 日韩有吗在线观看| 亚洲成人精品久久久| 日本少妇毛茸茸| 妖精视频一区二区三区免费观看| 亚洲午夜小视频| 青青草华人在线视频| 久久视频在线| 欧美高清视频在线观看| 男女免费视频网站| 性色av一区二区怡红| 国产成+人+综合+亚洲欧洲| 亚洲精品一区二区二区| 极品少妇一区二区| 亚洲字幕一区二区| 三级在线视频| 国产精品久久久久久久蜜臀| 熟妇熟女乱妇乱女网站| 黑人玩欧美人三根一起进| 天天综合日日夜夜精品| 国产喷水theporn| 亚洲综合色婷婷在线观看| 亚洲成年人在线| 波多野结衣a v在线| 97精品国产一区二区三区 | 免费观看黄色的网站| 牛牛精品视频在线| 91国偷自产一区二区三区观看| 第一区免费在线观看| 美女视频亚洲色图| 色偷偷88888欧美精品久久久 | 免费亚洲网站| 91美女片黄在线观看游戏| 风流少妇一区二区三区91| 久久久国际精品| 国产精品av免费观看| 国偷自产一区二区免费视频| 91精品国产综合久久精品app| 三级男人添奶爽爽爽视频| 日韩伦理视频| 51午夜精品视频| 国产熟女一区二区三区四区| 2023国产一二三区日本精品2022| 中文字幕色一区二区| 天堂中文最新版在线中文| 欧美一区二区视频在线观看2022| 日本丰满少妇裸体自慰| av文字幕在线观看| 蜜乳av综合| 久久国产加勒比精品无码| 激情五月色婷婷| 国产一区二区免费视频| 青青草成人激情在线| 日韩电影免费观看| 欧美日韩国产精品成人| 一区二区三区四区免费| 伊人久久亚洲美女图片| 成人激情视频小说免费下载| 天堂网在线中文| 亚洲精品亚洲人成人网| 日本超碰在线观看| 国产精品一区二区99| 欧美激情亚洲视频| 国产一区二区视频免费观看| 久久精品亚洲国产奇米99 | 国产欧美高清| 99视频免费观看| 美女免费久久| 欧美熟乱第一页| 中文字幕被公侵犯的漂亮人妻| 亚洲成人原创| 国产日韩精品一区观看| 综合久久2019| 欧美一区二区三区日韩视频| 粉嫩精品久久99综合一区| 视频一区二区三区中文字幕| 久久精品一二三区| 日本不卡免费高清视频在线| 亚洲第一区中文99精品| 精品少妇一二三区| 成人丝袜18视频在线观看| 奇米777四色影视在线看| 高清国产一区二区三区四区五区| 色伦专区97中文字幕| 成人一二三四区| 国产欧美日韩麻豆91| 亚洲精品高清无码视频| 国产麻豆精品久久| 国产精品男人的天堂| www日韩tube| 欧美日韩视频一区二区| 大地资源高清在线视频观看| 韩国午夜理伦三级不卡影院| 玖玖精品在线视频| 日本精品国产| 欧美黄色片免费观看| 免费观看黄色一级视频| 天天色综合天天| 免费在线观看你懂的| 日本不卡在线视频| 自拍偷拍99| a级日韩大片| 97视频在线观看亚洲| 三级做a全过程在线观看| 在线观看欧美日本| 日韩一区二区不卡视频| 国产东北露脸精品视频| 国产老熟妇精品观看| 怕怕欧美视频免费大全| 成人激情视频在线观看| 黄色成人在线网| 亚洲香蕉伊综合在人在线视看| 亚洲自拍第二页| 一区二区欧美视频| 美女又爽又黄视频毛茸茸| 日日夜夜免费精品| 最新av在线免费观看| 欧美黄色影院| 成人黄色在线播放| av在线视屏| 色婷婷av一区二区三区在线观看| av资源免费看| 黑人极品videos精品欧美裸| 久久精品三级视频| 国产成人免费在线视频| 毛葺葺老太做受视频| 一区二区三区在线电影| 免费av在线一区二区| 色综合.com| 欧美亚洲午夜视频在线观看| 午夜在线观看视频| 日韩电影大全免费观看2023年上| 中文字幕一区2区3区| 亚洲18色成人| 欧美特黄一级片| 91蝌蚪porny| 免费看91视频| 免费高清不卡av| 2018日日夜夜| 婷婷激情综合| 欧洲精品亚洲精品| 超碰成人福利| 91久久久久久久| 亚洲人成午夜免电影费观看| 欧美精品在线第一页| 成人高清免费在线播放| 亚洲第一视频在线观看| 国产一区二区三区三州| 色婷婷综合久久久久中文一区二区 | 日本精品影院| 99re6热在线精品视频播放速度| 桃子视频成人app| 久久久久久尹人网香蕉| 成人短视频在线| 最新亚洲国产精品| 国产特黄在线| 亚洲精品在线91| 少妇精品视频一区二区| 日韩一区二区在线观看视频播放| 亚洲性猛交富婆| 色综合久久中文字幕| 日韩手机在线观看| 亚洲综合在线免费观看| 国模无码国产精品视频| 中文字幕在线播放不卡一区| 免费看91的网站| 久久精品无码一区二区三区| 国产精品无码毛片| www.日韩av| 中文字幕乱视频| 大尺度一区二区| 亚洲综合中文网| 国产麻豆精品视频| 三年中文在线观看免费大全中国| 男女性色大片免费观看一区二区| www.xxx亚洲| 日韩高清不卡一区| 丝袜制服一区二区三区| 日韩中文字幕一区二区三区| 99精品视频在线看| 久久美女性网| 久久久久久香蕉| 日韩精品免费视频人成| 成人免费毛片播放| 性欧美精品高清| 91色国产在线| 久久99国产精品麻豆| 伊人成人222| 激情五月激情综合网| 亚洲精品乱码久久久久久动漫| 久久国产夜色精品鲁鲁99| 精品久久久99| 国产成人在线视频网站| 四虎成人免费视频| 91亚洲国产成人精品一区二区三| av在线网站观看| 中文字幕欧美日韩一区| 成年人网站在线观看视频| 最新国产成人在线观看| 麻豆亚洲av成人无码久久精品| 亚洲一区二区三区四区的| 日本一级淫片免费放| 精品欧美一区二区三区| 欧美特级黄色片| 91麻豆精品91久久久久同性| 午夜久久久久久久久久| 日韩第一页在线| 91这里只有精品| 美乳少妇欧美精品| hd国产人妖ts另类视频| 国产成人短视频| 国产精品一区免费在线| 国产麻豆一区二区三区在线观看| 日韩啪啪网站| 亚洲精品欧美精品| 国一区二区在线观看| 成人观看免费完整观看| 国产麻豆91精品| 无码人妻精品一区二区三区温州| 欧美国产精品一区二区| 欧美日韩三级在线观看| 一本色道久久综合亚洲91 | 国产精品免费av一区二区| 一本一本大道香蕉久在线精品 | 国产成人亚洲精品青草天美| 免费中文字幕av| 亚洲天堂免费看| 国产精品久免费的黄网站| 91精品国产91综合久久蜜臀| 亚洲 另类 春色 国产| 久久精品91久久久久久再现| free性m.freesex欧美| 国产精品一区二区久久国产| 精品深夜福利视频| 麻豆md0077饥渴少妇| 香蕉视频成人在线观看| 中文字幕12页| 久久久激情视频| 国产成年人免费视频| 7777精品久久久大香线蕉| 亚洲av成人精品日韩在线播放| 久久视频在线视频| 成人在线视频播放| 韩国成人一区| 欧美另类综合| 天天干天天玩天天操| 久久亚洲影视婷婷| 国产在线观看免费av| 7777精品伊人久久久大香线蕉经典版下载 | 免费在线观看日韩视频| 成人一级黄色片| 三级影片在线看| 欧美日韩高清影院| 精品美女视频在线观看免费软件 | 国产一区二区三区黄网站| 欧美日韩免费高清| 99在线观看免费视频精品观看| 中国老熟女重囗味hdxx| 中文字幕中文字幕一区二区 | 秋霞午夜鲁丝一区二区老狼| 粉嫩av懂色av蜜臀av分享| 亚洲综合激情另类小说区| 国产精品久久久午夜夜伦鲁鲁| 亚洲日韩中文字幕在线播放| sm久久捆绑调教精品一区| 99精品在线直播| 雨宫琴音一区二区三区| 女同激情久久av久久| 国产精品少妇自拍| 日本精品入口免费视频| 亚洲美女动态图120秒| 牛牛精品一区二区| 麻豆精品传媒视频| 天堂av在线一区| 国产肥白大熟妇bbbb视频| 日韩欧美中文字幕在线播放| 亚洲 另类 春色 国产| 高清欧美性猛交xxxx| 国产精品网在线观看| 男女私大尺度视频| 成人av在线网站| 日韩av男人天堂| 亚洲精品99久久久久中文字幕| www成人免费观看| 久久av一区二区三区漫画| 香蕉成人久久| 女人又爽又黄免费女仆| 在线免费观看日本一区| 91电影在线播放| 国产中文字幕亚洲| 中文字幕一区二区精品区| 国产a√精品区二区三区四区| 亚洲一区二区欧美| 日韩精品视频无播放器在线看 | 欧美成人黑人猛交| 欧美极品美女视频| 一区二区三区免费在线| 成人444kkkk在线观看| 成午夜精品一区二区三区软件| 男女日批视频在线观看| 91麻豆福利精品推荐| 天天综合久久综合| 久久在线免费观看视频| 国产成人av毛片| av网址在线观看免费| 国产精品伦理一区二区| 国产叼嘿视频在线观看| 午夜精品久久久久久久久久久久| 亚洲制服欧美另类| 一级黄色片国产| 亚洲国产精品久久不卡毛片| 日本v片在线免费观看| 国产精品视频一区二区高潮| 午夜精品亚洲| 欧美丰满少妇人妻精品| 欧美日韩中文精品| 精灵使的剑舞无删减版在线观看| 蜜桃狠狠色伊人亚洲综合网站| 蜜臂av日日欢夜夜爽一区| 久草视频免费在线| 亚洲欧美中文日韩v在线观看| 亚洲精品aa| 5月婷婷6月丁香| 国产精品不卡在线观看| 少妇av一区二区| 国产精品高潮呻吟久久av无限| 欧美黄在线观看| jizz中文字幕| 精品日韩欧美一区二区| 日韩免费小视频| av在线com| 国产精品久久久一区麻豆最新章节| 黄色av免费观看| 国产精品稀缺呦系列在线| 一本综合久久| 青娱乐国产在线| 曰本色欧美视频在线| 国产毛片久久久|