JVM 類加載器 (二)

一、類加載器(ClassLoader)負責加載class文件,class文件在文件開頭有特定的文件標識,而且ClassLoader只負責 class 文件的加載,至於class文件是否可以運行則由Execution Engine決定;java

  

 

二、類的加載過程安全

加載class文件 ---> 鏈接(驗證、準備、解析class文件)----> 初始化類的對象 ----> 使用類的對象 -----> 卸載。jvm

(1)加載class文件spa

  取類的二進制字節流,經過類的全量命名,將靜態存儲結構房到方法區中,Class(類的定義或結構,即類對象)放到堆中; 設計

(2)初始化類對象3d

  執行類的構造器<clinit>,爲類的靜態變量賦予正確的初值;code

  構造器包含:static變量、static塊;根據代碼中的順序來決定先執行哪一個;對象

  先執行構造器(static變量、static塊),再執行構造方法;blog

 

三、JDK中的類加載器:遞歸

  <1> 啓動類加載器(BootStrap ClassLoader): C++編寫的,虛擬機自帶的加載器;加載$JAVA_HOME/jre/lib/rt.jar 

  <2> 擴展類加載器(Extension ClassLoader):java編寫;加載$JAVA_HOME/jre/lib/ext/*.jar

  <3> 應用程序類加載器(App ClassLoader):java編寫;也叫系統類加載器,加載當前應用的 $classpath 下全部類

     <4> 用戶自定義加載器:Java.Lang.ClassLoader 的子類,用戶能夠定製類的加載方式;

   

 

三、類加載器說明

 第一步:將 MyHello 類打包成 jar包,而後放入$JAVA_HOME/jre/lib/ext/ 目錄下。  MyHello內容以下:

public class MyHello
{
    public static void main(String[] args)
    {

    }
}

 

   第二步:編寫以下代碼

public class Demo1 { public static void main(String[] args) throws ClassNotFoundException { //啓動類加載器(BootStrap ClassLoader)
        Object object = new Object(); System.out.println("Object-classLoader: " + object.getClass().getClassLoader()); //結果: Object-classLoader: null //擴展類加載器 (Extension ClassLoader)
        Class myHello = Class.forName("com.yufeng.jvm.hello.MyHello"); System.out.println("MyHello-classLoader: " + myHello.getClassLoader()); //結果:MyHello-classLoader: sun.misc.Launcher$ExtClassLoader@7ea987ac //應用類加載器 (App ClassLoader)
        Demo1 classLoaderDemo1 = new Demo1(); System.out.println("Demo1-classLoader: " + classLoaderDemo1.getClass().getClassLoader()); //①結果:Demo1-classLoader: sun.misc.Launcher$AppClassLoader@18b4aac2
 System.out.println("Demo1-classLoader-parent: " + classLoaderDemo1.getClass().getClassLoader().getParent()); //②結果:Demo1-classLoader-parent: sun.misc.Launcher$ExtClassLoader@2503dbd3
 System.out.println("Demo1-classLoader-parent-parent: " + classLoaderDemo1.getClass().getClassLoader().getParent().getParent()); //③結果:Demo1-classLoader-parent-parent: null
 } }

從以上的①、②、③能夠看出,啓動類加載器是擴展類加載器的父類,擴展類加載器是應用加載器的父類。

打印出的Object的類加載器爲null,表示它是根加載器,即啓動類加載器。

 

四、類加載器的雙親委派機制

   某個特定的類加載器在接到加載類的請求時,首先將加載任務委託給父類加載器,依次遞歸,若父類加載器能夠完成類加載任務,就成功返回;只有父類加載器沒法完成此加載任務時,才本身去加載。 

  這樣設計爲了保證java的一種安全特性--------沙箱機制(防止惡意代碼對java的破壞);

  例:若本身新建了一個String類(classpath路徑下),則類加載器是應用程序類加載器;加載的時候程序類加載器委託父類加載器加載(即擴展類加載器),擴展類加載器去委託啓動類加載器去加載,rt.jar中有String.class文件,則會加載這個Class,不會加載本身新建的那個String類。

相關文章
相關標籤/搜索