知識補充:
jvm在初期是將.java文件,編譯成.class文件,當程序運行的時候,Java 虛擬機就將編譯生成的 . class 文件按照需求和一定的規則加載進內存,組織成爲一個完整的 Java 應用程序,jvm會把每個單獨的類和接口編譯成一個單獨的.class文件,這些文件對於 Java 運行環境來說就是一個個可以動態加載的單元。我們可以在不重新編譯其它代碼的情況下,只編譯需要修改的單元,並把修改文件編譯後的 . class 文件放到 Java 的路徑當中, 等到下次該 Java 虛擬機器重新激活時,這個邏輯上的 Java 應用程序就會因爲加載了新修改的 .class 文件,自己的功能也做了更新,這就是 Java 的動態性。
1. 預先加載與依需求加載
Java 運行所需要的基本類採用預先加載,的方法全部加載要內存當中,因爲這些單元在 Java 程序運行的過程當中經常要使用的,主要包括 JRE 的 rt.jar 文件裏面所有的 .class 文件。
我們在程序中需要使用自己定義的類的時候就要使用依需求加載方法。
2. 隱式加載和顯示加載
程序中用 new 關鍵字來定義一個實例變量, JRE 在執行到 new 關鍵字的時候就會把對應的實例類加載進入內存,用的也很多, JRE 系統在後臺自動的幫助用戶加載,減少了用戶的工作量,也增加了系統的安全性和程序的可讀性。
程序員自己寫程序把需要的類加載到內存當中(顯示加載)
Class c = Class.forName("TestClass");
TestClass object = (TestClass)c.newInstance
我們通過 Class 類的 forName (String s) 方法把自定義類 TestClass 加載進來,並通過 newInstance ()方法把實例初始化
Test test = new Test();//Test 類爲自定義的一個測試類;
ClassLoader cl = test. getClass().getClassLoader();
// 獲取 test 的類裝載器;
Class c = Class.forName("TestClass", true, cl);
因爲一個類要加載就必需要有加載器,這裏我們是通過獲取加載 Test 類的加載器 cl 當作加載 TestClass 的類加載器來實現加載的。
3. 自定義類加載機制
URL url = new URL("file:/d:/test/lib/");
URLClassLoader urlCL = new URLClassLoader(new URL[]{url});
Class c = urlCL.loadClass("TestClassA");
TestClassA object = (TestClassA)c.newInstance();
object.method();
首先定義 URL 指定類加載器從何處加載類, URL 可以指向網際網絡上的任何位置,也可以指向我們計算機裏的文件系統 ( 包含 JAR 文件 ) .上述範例當中我們從 file:/d:/test/lib/ 處尋找類;然後定義 URLClassLoader 來加載所需的類,最後即可使用該實例了。
4. 類加載器的階層體系
當執行hllo.class時候,java.exe會自動找到很顯眼的jre位置,接着會在其中找到jvm.dll,(在jdk和jre中都有jvm)有了.dll文件之後激活jvm加載動態庫,jvm活後,先做一些初始化的動作,比如說讀取系統參數等。
然後,一旦初始化動作完成之後,就會產生第一個類加載器―― Bootstrap Loader (靴帶機制,就是繫上鞋帶就要走路了), Bootstrap Loader 是由 C++ 所撰寫而成,這個 Bootstrap Loader 所做的初始工作中,除了一些基本的初始化動作之外,最重要的就是加載 Launcher.java 之中的 ExtClassLoader ,並設定其 Parent 爲 null ,代表其父加載器爲 BootstrapLoader .然後 Bootstrap Loader 再要求加載 Launcher.java 之中的 AppClassLoader ,並設定其 Parent 爲之前產生的 ExtClassLoader 實體。這兩個加載器都是以靜態類的形式存在的。這裏要請大家注意的是, Launcher$ExtClassLoader.class 與 Launcher$AppClassLoader.class 都是由 Bootstrap Loader 所加載,所以 Parent 和由哪個類加載器加載沒有關係。
這三個加載器就構成我們的 Java 類加載體系。他們分別從以下的路徑尋找程序所需要的類:
BootstrapLoader : sun.boot.class.path
ExtClassLoader: java.ext.dirs
AppClassLoader: java.class.path
這三個系統參量可以通過 System.getProperty() 函數得到具體對應的路徑。大家可以自己編程實現查看具體的路徑。