雙親委派模式和類加載器(自定義類加載器)

類加載器就是加載一個類的一塊功能代碼,實現了將類通過加載全過程。進而將類放到內存分配空間和初始化,再接下來就是愉快的使用類裏面的屬性和方法完成自己的業務開發需求啦。

類加載器有很多種,主要是爲了根據Java定義的項目目錄結構去加載不同的路徑下的類,一般都是根據功能類型劃分。

類加載器的分類:

(1) BootStrapClassLoad啓動類加載器

主要負責加載lib文件夾目錄下的jar包。(idea創建普通Java類不會自帶,要手動生成)

(2)ExtendsionClassLoad擴展類加載器

主要加載ext目錄下的擴展類。

(3)ApplicationClassLoad應用程序類加載器

加載class path 下面的類(idea中是target->classes目錄下)
線程加載器:
線程加載器也有個名稱線程上下文加載器,其實它是JVM在啓動線程進行類加載的時候把應用程序類加載器賦予了當前線程而已。

(4)自定義類加載器

這是爲了實現自己的需求自定義的類加載器;比如

1:你想加載一些其它目錄路徑下的類文件,
2:或者做一些不同版本的類兼容(同時運行,不自定義類加載器就只會運行一份,因爲判斷是否加載同一個類的標準就是三點:類名,包名,類加載器),
3:或者設計一些自主研發的框架結構等等都需要用到自定義類加載器。

類加載器的雙親委派模式:

設想一種情況,你寫了一個String類,這很明顯是不行的因爲JVM已經有這個內存類了,但是因爲存放目錄不同,加載器不同,也成功加載了,那麼調用的時候就亂套了。所以JVM裏面設計了雙親委派模式防止這種情況。
當一個類通過自定義加載器或者應用程序加載器加載時,會先向上一級父類的加載器詢問判斷是否已經加載過這個類,比如:
自定義加載器------》應用程序加載器------》擴展類加載器------》啓動類加載器
通過這一層層詢問如果都沒有,那麼就確定這個類不會是Java自身定義的內部類。那麼就再反方向推回,直到找到一個加載器可以加載(加載不了就是class not found error):
啓動類加載器------》擴展類加載器------》應用程序加載器------》自定義加載器

自定義類加載器代碼實現:

在這裏插入圖片描述

但是我做實驗的時候,遇到一個很奇怪的沒能解決的問題,就是明明已經讀取成功字節碼文件,在執行defineClass的時候就直接跳出debug,也沒有catch到什麼錯誤信息。

先上debug的圖,可以很清晰看到字節碼文件已經成功讀取出來了,然後調用defineClass 轉的時候就出問題:

在這裏插入圖片描述
在這裏插入圖片描述

後來問了大佬,傳入的那個name不是.class文件的name。而是.class文件的全限定名。讀取class文件和傳入的name調用defineClass 方法是兩回事,後來將代碼改成這樣就成功了,我之所以不把Hello.class放在SRC目錄下是因爲寫全限定名加載時候,調用的是父類的加載器,我自定義的裏面兩個System.out輸出都沒打印出來,所以就換了個路徑放,在這裏也可以看出,不管文件放在哪裏,自定義的類加載器都是可以加載到的:

在這裏插入圖片描述

謝謝這位大佬,鞠躬!

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章