類加載器就是加載一個類的一塊功能代碼,實現了將類通過加載全過程。進而將類放到內存分配空間和初始化,再接下來就是愉快的使用類裏面的屬性和方法完成自己的業務開發需求啦。
類加載器有很多種,主要是爲了根據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 轉的時候就出問題: