天天看點

JAVA知識

JAVA知識

**classloader

JVM裝載**

在說java的ClassLoader機制之前,我先了解下jvm的裝載過程和其中的原理。

裝載就是尋找一個類或者一個接口的二進制形式并且用二進制形式構造代表這個類或者是這個接口的class對象的過程。

類的生命周期是從被加載到虛拟機記憶體中開始,到解除安裝出記憶體結束。

加載->驗證->準備->解析->初始化->使用->解除安裝

在java中,類裝載器把一個類裝入java虛拟機中,要經過三個步驟完成:裝載、連結和初始化

這是java的裝載流程,後面要說下java中,類的表現形式。

在java中,一個類代表着這個類要執行的代碼,但是這個類可以有對應的各種不同的執行個體,不同的執行個體就是通過類中資料的表示狀态來區分。狀态是動态的,但是代碼則不會。當我們将一個特定的狀态和一個類對應起來,也就是意味着将一個類執行個體化。盡管相同的類呢,對應的執行個體有各種各樣不同的狀态,但是其基本底層還都是同一份代碼,隻是其中的資料狀态有不同。jvm一般隻加載一次類,以後相同的類就不會再加載。

JAVA知識

下面就講下JVM是如何區分不同的類的:

在Java中,一個類用其完全比對類名(fully qualified class name)作為辨別,這裡指的完全比對類名包括包名和類名。但在JVM中一個類用其全名和一個加載類ClassLoader的執行個體作為唯一辨別。是以,如果一個名為Pg的包中,有一個名為Cl的類,被類加載器KlassLoader的一個執行個體kl1加載,Cl的執行個體,即C1.class在JVM中表示為(Cl, Pg, kl1)。這意味着兩個類加載器的執行個體(Cl, Pg, kl1) 和 (Cl, Pg, kl2)是不同的,被它們所加載的類也是以完全不同,互不相容的。

JVM規範定義了兩種類型的類裝載器:啟動内裝載器(bootstrap)和使用者自定義裝載器(user-defined class loader)。

JVM在運作時會産生三個ClassLoader:Bootstrap ClassLoader、Extension ClassLoader和AppClassLoader。Bootstrap是用C++編寫的,我們在Java中看不到它,是null,是JVM自帶的類裝載器,用來裝載核心類庫,如java.lang.*等。

AppClassLoader的Parent是ExtClassLoader,而ExtClassLoader的Parent為Bootstrap ClassLoader。

package javatest;
public class TestClassLoader{
    public static void main(String[] args){
        Class cl = null;
        ClassLoader cLoader;
        cLoader = ClassLoader.getSystemClassLoader();
        System.out.println(cLoader);
        while(cLoader != null){
            cLoader = cLoader.getParent();
            System.out.println(cLoader);
        }
        try{
            cl = Class.forName("java.lang.Object");
            cLoader = cl.getClassLoader();
            System.out.println("java.lang.Object loader is "+cl);
            cl = Class.forName("javatest.TestClassLoader");
            cLoader = cl.getClassLoader();
            System.out.println("LoadTest loader is "+cl);
        }catch(Exception e){
            e.printStackTrace();
        }
    }
}
           

output:

sun.misc.Launcher$AppClassLoader@73d16e93

// 系統的類裝載器來自類sun.misc.Launcher$AppClassLoader@73d16e93的執行個體化,

sun.misc.Launcher$ExtClassLoader@15db9742

// 系統的類裝載器的parent來自sun.misc.Launcher$ExtClassLoader@15db9742的執行個體化

null

//系統的類裝載器的爺爺是由上面的Bootstrap ClassLoader執行個體而來,但是呢,這個Bootstrap ClassLoader是由C++實作的(嘿嘿嘿,混血兒),在java中是看不到滴。

java.lang.Object loader is null

//核心類都是由Bootstrap ClassLoader進行裝載滴

LoadTest loader is sun.misc.Launcher$AppClassLoader@73d16e93

//使用者自己的類都是由AppClassLoader進行加載滴。

JAVA知識

那麼問題來了,JAVA為啥需要這麼多類加載器(當然是多層負責每層對應的類系統,而且多态這個磨人的妖精很是厲害,需要多層加載機制進行處理。–個人了解)

因為java是動态加載類的,這樣的話,用到什麼類就加載什麼類,不用的就不加載(模仿Linux的記憶體管理機制!!!也讓我想起了C++裡面的記憶體申請,如果申請記憶體,先不配置設定實際實體記憶體,當需要通路的時候,再進行配置設定記憶體進行操作)

點選關注 阿裡雲科技快訊 ,跟多精美禮品等你來拿!
JAVA知識

參考:

兔子哥哥