天天看點

JVM之雙親委派機制1什麼是雙親委派機制?2使用雙親委派機制的好處?3如何破壞雙親委派機制

1什麼是雙親委派機制?

在類A.java被編譯成A.class位元組碼檔案時,要使用類加載器來将A.class位元組碼檔案加載到JVM中轉換為Class(A)對象(一個類隻有唯一的Class(A)對象),這是之前也提到過的類加載器的主要功能。

對于雙親委派機制就是加載的實作方法,當類A要被執行個體化等應用時,類加載器首先由底向上逐層檢視Class(A)是否加載過,若加載過則直接加載,若到最頂層發現沒加載過,則從最頂層逐層向下進行查找加載,若到最低層也沒有找到則抛出異常。

檢視是否加載過:

自定義類加載–>AppClassLoader–>ExtClassLoader–>BootStrapClassLoader

由頂向下查找加載(之前沒加載過):

BootStrapClassLoader–>ExtClassLoader–>AppClassLoader–>自定義類加載

JVM之雙親委派機制1什麼是雙親委派機制?2使用雙親委派機制的好處?3如何破壞雙親委派機制

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方法。