我們知道,我們在Java中用到的所有的類都是通過類加載器ClassLoader加載到JVM中的,我們還知道類加載器也對應著一個類,既然這樣那麼我們會想那麼ClassLoader類是由誰加載的呢?
其實在Java中有許許多多的類加載器,我們甚至可以寫自己的類加載器。
其中主要三個類加載器(他們是樹形關系)是:
BootStrap:在java虛擬機啟動的時候會利用這個類加載器來加載 JDK安裝目錄下的 /JRE/LIB/rt.jar 也就是系統默認導入的一些類例如System類,這個類加載器不是類 。只是作為一個Java中類的起源工具。
ExpClassLoader:這個類加載器加載JDK安裝目錄下的/JRE/LIB/ext 目錄中的類 我們只要把我們的類打包成JAR包放在這裡即可。
AppClassLoader:我們在Java程序中classpath對應的類都有這個AppClassLoader導入進來。
看下面一段代碼:
- package me.test;
- /**
- * BootStrap
- * 加載 JRE/lib/rt.jar 包中的類 包括我們常用到的類
- *
- * ExtClassLoader
- * 專門家在 JDK/JRE/libEXT/*.jar 中的類 只要把我們的類放在這裡 就會被 這個加載器加載
- *
- * AppClassLoader
- * 加載ClassPath指定的所有jar和目錄
- *
- * **/
- public class Test1
- {
- public static void main(String []args)
- {
- System.out.println(Test1.class.getClassLoader().getClass().getName() ); //獲取主類的類加載器
- System.out.println(System.class.getClassLoader());
- //BootStrap 獲取System類的類加載器 因為加載器是 BootStrap所以返回null 以為內他不是一個類
- ClassLoader l=Test1.class.getClassLoader() ; //獲取Test1的類加載器
- while(l!=null) //循環出 ClassLoader樹
- {
- System.out.println(l.getClass().getName());
- l=l.getParent();
- }
- System.out.println(l);
- }
- }
ClassLoader的委托模型
比如說我們在加載一個類的時候AppClassLoader他先讓BootStrap來加載類,如果BootStrap已經加載了,那麼就返回。如果找不到這個類那麼BootStrap就傳遞給ExtClassLoader 來查找,和BootStrap一樣。如果找到就加載,如果找不到就繼續傳遞給AppClassLoader 來加載。如果AppClassLoader還找不到的話,那麼AppClassLoader就會跑出ClassNotFoundException 異常。
我們為什麼不利用AppClassLoader下級的加載器呢? 因為AppClassLoader下級可能有多個類加載器多個類加載器相互獨立,如果加載類那麼就會導致內存中出現多份字節碼,造成不必要的的內存浪費。這就是類加載器的委托模型