jvm使用java類的方式
- java源程序經(jīng)過java編譯器編譯之后轉(zhuǎn)換成java字節(jié)碼文件(.class) ,類加載器負責讀取java字節(jié)碼文件,并把此字節(jié)碼轉(zhuǎn)換成java.lang.Class類的一個實例,每個實例用來表示一個java類,可以通過實例的newInstance()函數(shù)創(chuàng)建出類的一個實例對象。
類加載器介紹
基本上所有的類加載器都是java.lang.ClassLoadeer類的一個實例(實現(xiàn)類)
類加載器的職責就是根據(jù)一個指定類的名稱,找到此類并生成相應的字節(jié)碼,并生成一個Class類型的實例,加載器還負責加載java所需的一系列資源
類加載器系統(tǒng)結(jié)構(gòu)
-引導類加載器(bootstrap class loader):用來加載java的核心類庫,是用原生代碼實現(xiàn)的
- 原生代碼:被編譯后直接依附于系統(tǒng)運行,不需要通過虛擬機,匯編成cpu的目標執(zhí)行文件
-擴展類加載器(extensions class loader):它用來加載 Java 的擴展庫。Java 虛擬機的實現(xiàn)會提供一個擴展庫目錄。該類加載器在此目錄里面查找并加載 Java 類。
-系統(tǒng)類加載器(system class loader):用來加載java應用的類路徑(自己寫的java應用),獲取此加載器通過ClassLoader.getSystemClassLoader()獲取
自己定義的類加載器 需要繼承java.lang.ClassLoader類
除了引導類加載器外,其他加載器都有一個父加載器,對于系統(tǒng)提供的類加載器來說,系統(tǒng)類加載器的父類加載器是擴展類加載器,而擴展類加載器的父類加載器是引導類加載器;對于開發(fā)人員編寫的類加載器來說,其父類加載器是加載此類加載器 Java 類的類加載器。因為類加載器 Java 類如同其它的 Java 類一樣,也是要由類加載器來加載的。一般來說,開發(fā)人員編寫的類加載器的父類加載器是系統(tǒng)類加載器。
類加載器的代理模式(雙親委派機制)
- 描述:某個特定的類加載器在接收到加載類的請求時,首先將請求委托給父類加載器,如果父類加載成功,就成功返回
類的加載過程
- 在前面介紹類加載器的代理模式的時候,提到過類加載器會首先代理給其它類加載器來嘗試加載某個類。這就意味著真正完成類的加載工作的類加載器和啟動這個加載過程的類加載器,有可能不是同一個。真正完成類的加載工作是通過調(diào)用defineClass來實現(xiàn)的;而啟動類的加載過程是通過調(diào)用loadClass來實現(xiàn)的。前者稱為一個類的定義加載器(defining loader),后者稱為初始加載器(initiating loader)。在 Java 虛擬機判斷兩個類是否相同的時候,使用的是類的定義加載器。也就是說,哪個類加載器啟動類的加載過程并不重要,重要的是最終定義這個類的加載器。兩種類加載器的關聯(lián)之處在于:一個類的定義加載器是它引用的其它類的初始加載器。如類com.example.Outer引用了類com.example.Inner,則由類com.example.Outer的定義加載器負責啟動類com.example.Inner的加載過程。
- 方法 loadClass()拋出的是 java.lang.ClassNotFoundException異常;方法defineClass()拋出的是java.lang.NoClassDefFoundError異常。
類加載器在成功加載某個類之后,會把得到的java.lang.Class類的實例緩存起來。下次再請求加載該類的時候,類加載器會直接使用緩存的類的實例,而不會嘗試再次加載。也就是說,對于一個類加載器實例來說,相同全名的類只加載一次,即loadClass方法不會被重復調(diào)用。