類加載器分兩種:jvm自帶的類加載器和用戶自定義類加載器
jvm自帶的類加載器:啓動類加載器、擴展類加載器、系統類加載器
啓動類加載器(Boostrap ClassLoader):由C++編寫,用於加載%JAVA_HOME%/jre/lib下的jar包,是頂級類加載器。
擴展類加載器(Extension ClassLoader):由java編寫,用於加載%JAVA_HOME%/jre/lib/ext下的jar包,其父加載器是啓動類加載器,這裏所說的父子關係並不是指java語言中的繼承關係,而是和類加載器的雙親委派機制有關係。
系統類加載器(System ClassLoader):由java編寫,用於加載classpath下面的類文件,其父類加載器是擴展類加載器。
用戶自定義類加載器:用戶自定義的類加載器必須繼承ClassLoader抽象類,且可以在構造函數中設置父類加載器,默認是系統類加載器。
類加載的過程分爲:加載--》鏈接--》初始化
其中鏈接過程又分爲:驗證--》準備--》解析
加載:將字節碼文件加載到內存並使用它創建一個Class對象。
驗證:確保Class文件的字節流中包含信息符合當前虛擬機要求,不會危害虛擬機自身的安全。
準備:給類的靜態變量(static)分配內存並賦默認值。
解析:將符號引用替換成直接引用。
初始化:類加載的最後階段,若該類具有超類,則對其進行初始化,這裏的初始化指給變量賦用戶指定的值,而非默認值。
雙親委派機制:指當一個類加載器接收到加載類請求時,並不會馬上自己去加載,而是將請求委託給它的父加載器,如果它的父加載器還有父加載器,則依次向上委託,請求最終到達頂層的啓動類加載器。如果父加載器可以完成加載任務,則成功返回,如果不能則交給子類加載器,依次向下傳遞,直到遇到可以成功加載的子類加載器或者無法加載返回異常。
雙親委派機制的優點:
1.避免類的重複加載,在jvm中不同類加載器加載的同一個類是不相同的,如果父加載器已經加載了該類,則父加載器直接返回該類,那麼子加載器就不會重複加載。
2.更加安全,java核心api中定義的類不會被隨意替換,如果從網絡上傳遞一個名爲java.lang.String的類,通過雙親委派機制傳遞到啓動類加載器後,而啓動類加載器在覈心Java API發現這個名字的類,發現該類已被加載,並不會重新加載網絡傳遞的過來的java.lang.String,而直接返回已加載過的String.class,這樣便可以防止核心API庫被隨意篡改。