1.類加載:類加載器將class文件加載到虛擬機的內存
加載:在硬盤上查找並經過IO讀入字節碼文件
鏈接:執行校驗、準備、解析步驟
校驗:校驗字節碼文件的正確性
準備:給類的靜態變量分配內存,並賦予默認值
解析:類裝載器裝入類所引用的其餘全部類
初始化:對類的靜態變量初始化爲指定的值,執行靜態代碼塊java
2.類加載器:spring
啓動類加載器(BootstrapClassLoader):負責加載JRE的核心類庫,如jre目標下的rt.jar,charsets.jar等
擴展類加載器(ExtensionClassLoader):負責加載JRE擴展目錄ext中JAR類包
系統類加載器(ApplicationClassLoader):負責加載ClassPath路徑下的類包
用戶自定義加載器(CustomClassLoader):負責加載用戶自定義路徑下的類包jvm
執行以下代碼,查看對應的類加載器:ide
package com.nijunyang.spring; import com.sun.crypto.provider.BlowfishCipher; /** * @author: create by nijunyang * @date:2019/6/16 */ public class ClassLoaderTest { public static void main(String[] args) { System.out.println(String.class.getClassLoader()); System.out.println(BlowfishCipher.class.getClassLoader().getClass().getName()); System.out.println(ClassLoaderTest.class.getClassLoader().getClass().getName()); System.out.println(ClassLoader.getSystemClassLoader().getClass().getName()); } }
-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------spa
能夠看到String的類加載器null,由於String是在java核心包rt.jar裏面這裏面東西是由啓動類加載器加載的,而啓動類加載器是由C/C++實現的,根本不在JDK裏面。
BlowfishCipher的類加載器是ExtClassLoader,而這個類正是Jre擴展目錄ext中jar包所在的類
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------
3.類加載機制--全盤委託和雙親委派機制3d
全盤委託:當一個ClassLoader加載一個類時,除非顯示的使用另外一個ClassLoader,該類所依賴和引用的類也由這個ClassLoader載入,好比說A依賴B,那麼B的加載器和A的加載器同樣。對象
雙親委派:指先委託父類加載器尋找目標類,在找不到的狀況下在本身的路徑中查找並載入目標類,感受說父類加載器不是很合適,由於沒有這一層關係,感受更像是上下級關係。委託上級加載器尋找目標類。blog
雙親委派的好處:ip
1.避免類重複加載,上級加載了,下級就不須要再加載內存
2.由於核心API都有固定的加載器,能夠防止核心庫被篡改: 自定義一個String類,一樣在java.lang包下,運行代碼會發現啓動報錯,實際加載的java.lang.String類並無main方法,說明實際加載的String類並非咱們自定義的String類,而是由於雙親委派機制,往上委託到啓動類加載器,去加載rt.jar裏面的String類
4.類加載過程
實際上jvm對class文件是按需加載的,須要的時候才加載(運行時動態加載),並不是一次所有加載進去,jvm啓動參數加上:-verbose:class 查看類加載
package com.nijunyang.spring; /** * @author: create by nijunyang * @date:2019/6/16 */ public class ClassLoaderTest { static { System.out.println("靜態塊執行"); } public static void main(String[] args) throws InterruptedException { Thread.sleep(3000); System.out.println(System.currentTimeMillis()); new A(); System.out.println("A對象建立完畢"); new B(); } }
從結果中咱們能夠看到
1.從本地/E:/IdeaProject/tuling/spring/target/classes/下面去加載當前運行類ClassLoaderTest.class文件
2.初始化類,執行靜態代碼塊
3.main方法運行,睡了5s以後打印當前時間,當咱們new A的時候纔去本地加載A.class文件到內存,再實例化A
4.A建立完畢以後,再去加載B.class,完成B的初始化