JVM類加載過程與雙親委派模型

類加載過程

類加載過程爲JVM將類描述數據從.class文件中加載到內存,並對數據進行解析和初始化,最終造成被JVM直接使用的Java類型。包含:java

  • 加載:獲取該類的二進制字節流,將字節流表明的靜態存儲結構轉化爲方法區的運行時數據結構,並在內存生成表明該類的 java.lang.Object 對象做爲方法區該類的訪問入口
  • 驗證:確保 Class 文件的字節流中包含的信息符號當前虛擬機的要求(文件格式驗證、元數據驗證、字節碼驗證、符號引用驗證)
  • 準備:爲類變量分配內存並設置類變量初始值
  • 解析:將常量池內的符號引用替換爲直接引用
  • 初始化:執行類構造器 () 方法

類加載器

類加載過程當中的加載操做由類加載去完成。類加載器分爲:數據結構

  • 啓動類加載器/Bootstrap ClassLoader:負責加載JAVA_HOME/lib目錄中的全部類,或者加載由選項-Xbootcalsspath指定的路徑下的類;
  • 擴展類加載器/ExtClasLoader:負責加載JAVA_HOME/lib/ext目錄中的全部類型,或者由參數-Xbootclasspath指定路徑中的全部類型;
  • 應用程序類加載器/AppClassLoader:負責加載用戶類路徑ClassPath下的全部類型
  • 自定義加載器:全部繼承抽象類java.lang.ClassLoader的類加載器

雙親委派模型

image

雙親委派過程:當一個類加載器收到類加載任務時,當即將任務委派給它的父類加載器去執行,直至委派給最頂層的啓動類加載器爲止。若是父類加載器沒法加載委派給它的類時,將類加載任務退回給它的下一級加載器去執行。this

雙親委派模型最大的好處就是讓Java類同其類加載器一塊兒具有了一種帶優先級的層次關係。舉個例子來講明下:好比咱們要加載頂層的Java類——java.lang.Object類,不管咱們用哪一個類加載器去加載Object類,這個加載請求最終都會委託給啓動類加載器(Bootstrap ClassLoader),這樣就保證了全部加載器加載的Object類都是同一個類。若是沒有雙親委派模型,就會出現 Wupx::Object 和 Huyx::Object 這樣兩個不一樣的Object類。spa

雙親委派模型案例

java.lang.ClassLoader 的 loadClass() 方法code

protected Class<?> loadClass(String name, boolean resolve)
        throws ClassNotFoundException
    {
        synchronized (getClassLoadingLock(name)) {
            // First, check if the class has already been loaded
            Class<?> c = findLoadedClass(name);
            if (c == null) {
                long t0 = System.nanoTime();
                try {
                    if (parent != null) {
                        c = parent.loadClass(name, false);
                    } else {
                        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;
        }
    }複製代碼

本文由博客一文多發平臺 OpenWrite 發佈!cdn

相關文章
相關標籤/搜索