天天看點

JVM類加載&雙親委派-JVM(二)

作者:後端從入門到精通

上篇文章說了java類的加載,驗證、準備、解析、初始化。類的初始化必須是類加載完才執行,是以類的構造方法初始化是在靜态方法之後執行。

一、類加載和雙親委派機制

前面類加載主要通過類加載器實作,類加載器有這幾種:

1、引導類加載器:負責加載支撐JVM運作的位于JRE的lib目錄下核心類庫,比如chaset.jar和rt.jar等。(c++實作)

2、擴充類加載器:負責加載支撐JVM運作的位于jre的lib目錄下的ext擴充目錄中的jar類包。

3、應用程式加載器:負責加載classPath路徑下的類包,主要加載自己寫的類。

4、自定義加載器:負責加載使用者自定義路徑下的類包。

JVM類加載&雙親委派-JVM(二)
JVM類加載&雙親委派-JVM(二)

由上面代碼執行的結果可以看到:

為什麼第一個列印的是null呢,因為引導類加載器是c++實作的,java不會顯示。

同理parentBootStrap就是加載器就是基類加載器,也是null。它的子類是ext加載器,ext的子類是app加載器,可以通過getSystemClassLoader來擷取到。

為什麼appClassLoader明明是最子類,而它會列印所有的包呢?

這就是雙親委派設定導緻如此的,因為每次加載會從他的父加載器去加載,當bootStrap從核心類庫加載不到,才會依次讓子加載器嘗試加載。

JVM類加載&雙親委派-JVM(二)

Launcher類最核心的代碼是這兩塊

getExtClassLoader() 和 getAppClassLoader()

ExtClassLoader是構造擴充類加載器,構造過程中将其父加載器設定為null。

getAppClassLoader構造應用類加載器,構造過程中将父加載器設定為ExtClassLoader。

JVM類加載&雙親委派-JVM(二)
JVM類加載&雙親委派-JVM(二)

需要設定一下,equals我們自己的類,就可以隻看我們自己的斷點。

當我們運作昨天寫的代碼,斷點就會走到loadClass這裡,點進去他的super。

這裡的findLoaderClass代表如果找到就直接傳回。

這裡第一次進來肯定是null,是以判斷他的parent。

我們這裡的this指的是appClassLoader,

是以他的父加載器我們之前看了是ExtClassLoader。

這時候遞歸調用這個loadClass,這時候則是ExtClassLoader調用。

這時候ExtClassLoader的父加載器是null,這時候走下面findBootstrap引導類加載器。

這時bootStrap類加載器肯定傳回null。

于是開始進入findClass。

這裡的findClass則是會調用URLClassLoader裡的findClass方法。

這裡會嘗試加載又會回到appClassLoader。

繼續閱讀