1什麼是雙親委派機制?
在類A.java被編譯成A.class位元組碼檔案時,要使用類加載器來将A.class位元組碼檔案加載到JVM中轉換為Class(A)對象(一個類隻有唯一的Class(A)對象),這是之前也提到過的類加載器的主要功能。
對于雙親委派機制就是加載的實作方法,當類A要被執行個體化等應用時,類加載器首先由底向上逐層檢視Class(A)是否加載過,若加載過則直接加載,若到最頂層發現沒加載過,則從最頂層逐層向下進行查找加載,若到最低層也沒有找到則抛出異常。
檢視是否加載過:
自定義類加載–>AppClassLoader–>ExtClassLoader–>BootStrapClassLoader
由頂向下查找加載(之前沒加載過):
BootStrapClassLoader–>ExtClassLoader–>AppClassLoader–>自定義類加載
![](https://img.laitimes.com/img/__Qf2AjLwojIjJCLyojI0JCLiAzNfRHLGZkRGZkRfJ3bs92YsYTMfVmepNHLxUEVPVTSU90dRpHW4Z0MMBjVtJWd0ckW65UbM5WOHJWa5kHT20ESjBjUIF2X0hXZ0xCMx81dvRWYoNHLrdEZwZ1Rh5WNXp1bwNjW1ZUba9VZwlHdssmch1mclRXY39CXldWYtlWPzNXZj9mcw1ycz9WL49zZuBnL4UzMwUzM1ATM3ATMxkTMwIzLc52YucWbp5GZzNmLn9Gbi1yZtl2Lc9CX6MHc0RHaiojIsJye.png)
2使用雙親委派機制的好處?
(1)可以避免加載多份同樣的位元組碼,先檢查是否加載過,若加載過則直接加載,不必重新加載。
(2)可以避免核心類被篡改,假設通過網絡傳遞一個名為java.lang.Integer的類,通過雙親委派機制傳遞到啟動類加載器,然而啟動類加載器在核心API中發現了這個類,發現該類已被加載。并不會重新加載網絡傳遞的java.lang.Integer而是直接傳回已經加載過的Integer.class。這樣可以預防核心API被随意篡改。
3如何破壞雙親委派機制
在某些情況下父類加載器需要委托子類加載器去加載class檔案,受到加載範圍的限制,父類加載器無法加載到需要的檔案,需要破壞雙親委派機制去實作。
這裡舉破壞雙親委派的一個情況:DriverManager要加載各個實作了Driver接口的實作類來進行管理,但是DriverManager由啟動類加載器加載,隻能加載JAVA_HOME的lib下檔案,而Driver接口的實作是由服務商提供的,由系統類加載器(線程類上下文加載器)加載,這個時候就需要啟動類加載器來委托子類來加載Driver實作,進而破壞了雙親委派機制。
對于破壞雙親委派機制的方法主要有兩種方式:
(1)引入線程類上下文加載器(上面例子用到的方式):線程上下文類加載器破壞了雙親委派模型,可以在執行線程中抛棄雙親委派加載鍊模式,使程式可以逆向使用類加載器。
(2)自定義ClassLoader:
如果不想不破壞雙親委派模型,隻要去重寫findClass方法。
如果想要去破壞雙親委派模型,需要去重寫loadClass方法。