ClassLoader心得

   
      咱們都知道,jvm執行的代碼,都是經過jvm加載系統加入的。加載系統的第一步是經過ClassLoader加載class二進制信息,jvm規範中並無規定class的來源類型,這就給jvm的實現這塊很大的靈活。能夠放在數據庫裏,能夠放在網絡的其餘地方(之前的applet),zip文件等。如今大多數都是放在zip包裏,咱們引入其餘class都是經過引入zip包的形式。
 
   ClassLoader關係結構以下
          BootStrap ClassLoader
               |
          Extension ClassLoader
               |
          System ClassLoader
               |
          Custom  ClassLoader
 
BootStrap ClassLoader 是由C++編寫,虛擬機的一部分,只用來加載核心類。負責加載目錄[JAVA_HOME]/bin下的jar,或者被參數 -DXbootclasspath說指定目錄的jar,而且是jvm識別的。
 
Extension ClassLoader是java編寫的,對應java系統中的ExtClassLoader類,負責加載java裏的ext包裏的類。
 
System ClassLoader 也是由java編寫,對應系統中的AppClassLoader類,負責加載應用中的代碼。
 
Custom ClassLoader是本身定義的ClassLoader,同AppClassLoader類,不一樣的事,他限定了只加載一部分應用中的代碼。
 
ClassLoader的雙親委派模型
 
     雙親委派模型,主要是整理java加載的秩序性,限定核心,擴展類的重複加載。
 
    BootStrap ClassLoader  —>  Extension ClassLoader  —> System ClassLoader —> Custom ClassLoader 的父子關係,是由組合關係組成的。加載類時,先請求parent加載器,若是加載成功就返回;不然本身再做加載。這樣有個好處是核心jar類或者擴展jar類能夠作到惟一性,不會每一個ClassLoader都加載他。
 
 protected Class<?> loadClass(String name, boolean resolve)
        throws ClassNotFoundException
    {
        synchronized (getClassLoadingLock(name)) {
            // 查找class是否被加載
            Class<?> c = findLoadedClass(name);
            if (c == null) {
                long t0 = System.nanoTime();
                try {
                   // 先讓父加載ClassLoader加載類
                    if (parent != null) { 
                        c = parent.loadClass(name, false);
                    } else {
                       // 啓動類ClassLoader加載
                        c = findBootstrapClassOrNull(name);
                    }
                } catch (ClassNotFoundException e) {
                    // ClassNotFoundException thrown if class not found
                    // from the non-null parent class loader
                }
 
                // 仍然沒加載到,本身去加載
                if (c == null) {
                    // If still not found, then invoke findClass in order
                    // to find the class.
                    long t1 = System.nanoTime();
                    c = findClass(name);
 
                    // this is the defining class loader; record the stats
                    sun.misc.PerfCounter.getParentDelegationTime().addTime(t1 - t0);
                    sun.misc.PerfCounter.getFindClassTime().addElapsedTimeFrom(t1);
                    sun.misc.PerfCounter.getFindClasses().increment();
                }
            }
            if (resolve) {
                resolveClass(c);
            }
            return c;
        }
    }
 
從方法中,咱們看到,ClassLoader先判斷類有沒有被加載,若是有直接返回;若是沒有在請求父ClassLoader,父ClassLoader在遞歸相同的操做;若是父ClassLoader爲null,表面爲啓動類加載器,換成啓動類加載器加載;若是還沒加載,在倫到本身加載。
 
從方法的修飾詞 protected 能夠看出,ClassLoader的雙親模式是不牢靠的,只要自定義的ClassLoader重載這個方法,就可能破壞雙親委派模型。
相關文章
相關標籤/搜索