getClassLoader():取得當前類的加載器ClassName.class.getClassLoader()(以下內容為轉載他人)
JVM啟動,會形成3個類加載器組成的初始化加載器層次結構:
bootstap classloader (加載核心類)
||
extension classloader(加載ext(目錄),即java.ext.dirs())
||
system classloader (加載-classpath或者java.class.path或者CLASSPATH)
ClassLoader機制:
a)全盤負責:一個classloader加載一個class后,這個class所引用或者依賴的類也由這個classloader載入,除非顯示的用另一個classloader載入
b)委托機制:先由父加載器加載,除非父加載器找不到時才從自己的類路徑中去尋找
c)Cache機制:classloader采用緩存機制,即先查cache;若cache中保存了這個class就直接返回;若無,才從文件讀取和轉化為class并放入cache
ClassLoader加載類順序:
1)檢查cache是否有該類:
11)若有直接返回
12)若無,請求父類加載
121) 若無父,則從bootstap classloader加載
2)加載:
21)尋找class文件(叢與此classloader相關的類路徑中尋找)
22)從文件載入class
23)找不到則拋出ClassNotFoundeException
3)擴展:
記載時即2),覆寫findClass可以實現自己的載入策略
記載時即2),覆寫loadClass來實現自己的載入過程
如何實現運行時動態載入與更新
本質:只要動態改類搜索路徑和清除classloader的cache已載入的class就ok
做法:
1)繼承ClassLoader:覆寫loadClass方法,動態尋找class文件
2)只要重新使用一個新的類搜索路徑來new一個classloader就可以,這樣既更新了類的搜索路徑以便來載入新的class,也更新生成了一個空白的cache
classloader載入的方式
1)Pre-loading 預先載入,載入基礎類
2)load-on-demand 按需求載入
JDK為啥有兩個JRE?
JDK中jre是運行java本身的程序,如javac
ProgramFile(默認安裝)中jre是運行用戶編寫的java程序
classloader有啥妙用(1)?
這個問題得從自定義的classloader身上說,那自定義classloader緣由是什么呢?
告訴你:大多是因為編譯時無法預知運行時需要哪些類,特別是app server;因此自定義classloader,運行時指定路徑,來加載這個路徑下的class
特殊說明
特殊說明1:如果沒有特殊指定,用戶自定義的classloader都把system classloader作為它的父加載器
特殊說明2:jvm認為不同的classloade載入相同名字的class是不同的,即使從同一個class文件載入
classloader有啥妙用(2)?
看到特殊說明2,你或許就會感覺疑惑或者不爽;啥概念?
以servlet、ejb等容器來剖析這個問題:
將接口或者基類放入classpath <---------system classloader
執行時,動態載入實現或者繼承這些接口或者基類的子類;<---------customized classloader
||
||
用customized classloader載入類時,發現它有一個父類class(extends);
但是在載入它時,jvm先加載父類class; 這個父類是system classloader能識別的; 根據“委托機制”它將由system classloader來加載;
然后customized classloader(實際是system classloader來加載)再載入這個class,創建一個實例,轉型為父類;
jvm就使用system classloader再次載入父類class,然后將此實例轉型為這個父類class;
這個過程加載了兩個父類class,都是由system classloader載入;即同一個classloader載入同一個文件,造型不會由異常
web app server大概是這樣工作的;這樣載入了任何繼承了servlet的class并正確運行它們,不管class是什么,都它們實例化為一個servlet class
