深刻源碼看java類加載器ClassLoader

ClassLoader類加載器是負責加載類的對象。ClassLoader 類是一個抽象類。若是給定類的二進制名稱(即爲包名加類名的全稱),那麼類加載器會試圖查找或生成構成類定義的數據。通常策略是將名稱轉換爲某個文件名,而後從文件系統讀取該名稱的「類文件」。java.lang.ClassLoader類的基本職責就是根據一個指定的類的名稱,找到或者生成其對應的字節代碼,而後從這些字節代碼中定義出一個 Java 類,即 java.lang.Class類的一個實例。除此以外,ClassLoader還負責加載 Java 應用所需的資源,如圖像文件和配置文件等。 做爲全部類加載器的基類,ClassLoader的內部實現機制仍是值得咱們細細研究一下的。因此今天我就帶領你們一塊兒來看一下Classloader的內部實現源碼。java

首先咱們來看一下Classloader類的兩個構造方法。c++

從上邊的幫助文檔中咱們能夠發現,在建立一個classloader的實例時咱們能夠顯示的指出他的父加載器,也能夠不指定,不指定的時候他的默認的父加載器是系統加載器。咱們來看一下源碼的實現:this

/**
  * Creates a new class loader using the <tt>ClassLoader</tt> returned by
  * the method {@link #getSystemClassLoader()
  * <tt>getSystemClassLoader()</tt>} as the parent class loader.
  */
protected ClassLoader() {
    SecurityManager security = System.getSecurityManager();
    if (security != null) {
        security.checkCreateClassLoader();
    }
    this.parent = getSystemClassLoader();
    initialized = true;
}

/**
  * Creates a new class loader using the specified parent class loader for
  */
protected ClassLoader(ClassLoader parent) {
    SecurityManager security = System.getSecurityManager();
    if (security != null) {
        security.checkCreateClassLoader();
    }
    this.parent = parent;
    initialized = true;
}

從上面源碼咱們能夠發現,classloader中必定有一個parent的屬性來指定當前loader的附加器。其源碼也證實了咱們剛纔上面的說法。spa

看完構造方法的實現,下一步咱們來看一下ClassLoader中一個特別重要的方法loadclass方法,這個方法就是用來加載類的。這個方法在jdk中有個重載的方法,可是實際上是一個樣的。一個帶有是否連接類的方法,一個不帶。下面咱們就看一下這個方法的源碼:code

public Class<?> loadClass(String name) throws ClassNotFoundException {
    return loadClass(name, false);
}
/**
  * Loads the class with the specified <a href="#name">binary name</a>.  The
  * default implementation of this method searches for classes in the
     
  * @throws  ClassNotFoundException
  *          If the class could not be found
  */
protected synchronized Class<?> loadClass(String name, boolean resolve)
    throws ClassNotFoundException {
    // First, check if the class has already been loaded
    Class c = findLoadedClass(name);
    if (c == null) {
        try {
            if (parent != null) {
                c = parent.loadClass(name, false);
            } else {
                c = findBootstrapClass0(name);
            }
        } catch (ClassNotFoundException e) {
            // If still not found, then invoke findClass in order
            // to find the class.
            c = findClass(name);
        }
    }
    if (resolve) {
        resolveClass(c);
    }
    return c;
}

關於這個方法的源碼解釋,我感受我不必解釋什麼,由於在API中已經有詳細的解釋了。我在解釋確定也不如他解釋的好,因此咱們來看一下API是怎麼解釋的吧:對象

雖然jdk已經解釋的很清楚了,可是有一點我仍是要在補充一下。從上面的源碼咱們能夠看出loadClass方法是一個遞歸的方法,一直往上找,一直找到根類加載器爲止,而後讓類加載器去加載這個類。至於跟加載器是怎麼實現的咱們就不得而知了。由於跟類加載加載類時一個本地方法,他是用c++寫的。咱們沒法看到他的源碼。這樣驗證了在前面咱們所說的類加載器的父類委託機制。遞歸

下面咱們來看一下findClass方法,咱們在上面的代碼中發現。在loadClass方法中有調用這個findclass方法,下面咱們首先來看一下API對這個方法的介紹:ssl

從上面介紹咱們能夠看出,這個方法主要是來查找咱們的類文件的。咱們在自定義咱們本身的類加載器的時候應該重寫這個方法,由於jdk中對這個方法基本沒有實現什麼,這就須要咱們本身來重寫這個方法,用咱們本身的所定義的方法去查找類文件。不信。你能夠看一下他的源碼實現:ci

protected Class<?> findClass(String name) throws ClassNotFoundException {
    throw new ClassNotFoundException(name);
}

暫時先介紹這些吧。其餘的方法基本都差很少,最近感受博客愈來愈難寫,愈來愈吃力。愈來愈發現底層理論的缺少。但願經過本身的努力,能夠慢慢改變這個現狀。資源

相關文章
相關標籤/搜索