類加載器有哪些:
1、啟動類加載器(Bootstrap ClassLoader):這個類加載器負責將存放在<JAVA_HOME>\lib目錄中的,或被-Xbootclasspath參數所指定的路徑中的,並且是虛擬機識別的(例如rt.jar)類庫加載到虛擬機內存中;
2、擴展類加載器(Extension ClassLoader):它負責加載<JAVA_HOME>\lib\ext目錄中的,或者被java.ext.dirs系統變量所指定的路徑中的所有類庫,開發者可以直接使用擴展類加載器;
3、應用程序類加載器(Application ClassLoader):由於這個類加載器是ClassLoader中的getSystemClassLoader()方法的返回值,所以一般也稱為系統類加載器。它負責加載用戶類路徑(claspath)上所指定的類庫,開發者可以直接使用這個類加載器。
4、線程上下文類加載器,面試的時候知道的也可以說下,它是為了解決基礎類掉調用回用戶代碼而引入的設計,也就是兼容雙親委派模型的缺陷。
類加載器雙親委派模型如下:
破壞雙親委派模型的三大情況:
1、雙親委派模型的第一次“被破壞”是發生在雙親委派模型出現之前——即JDK1.2發布之前;
2、雙親委派模型的第二次“被破壞”是由於模型自身的缺陷導致的;
一個典型的例子便是JNDI服務,JNDI現在已經是Java的標准服務,它的代碼由啟動類加載器去加載(在JDK1.3時放進去的rt.jar),但JNDI的目的就是對資源進行集中管理和查找,它需要調用由獨立廠商實現並部署在應用程序的Classpath下的JNDI接口提供者(SPI)的代碼,但啟動類記載不可能“認識”這些代碼?
為了解決這個問題,Java設計團隊只好引入了一個不太優雅的設計,線程上下文類加載器。這個類加載器可以通過java.lang.Thread類的setContextClassLoader方法設置,如果創建線程時還未設置,它將從父線程中繼承一個,如果在應用程序的全局范圍內都沒有設置過的話,那這個類加載器默認就是應用程序類加載器。
有了這個線程上下文來加載器,就可以做一些“舞弊”的事情了,JNDI服務使用這個縣城上下文類加載器去加載所需要的SPI代碼,也就是父類加載器請求子類加載器去完成類加載器的動作,這種行為實際上打通了雙親委派模型的層次結構來逆向使用類加載器,實際上已經違背了雙親委派模型的一般性原則;
java中所有涉及SPI的加載懂基本上都采用這種方式,例如JNDI、JDBC、JCE、JAXB和JBI等。
3、雙親委派模型的第三次“被破壞”是由於用戶對程序動態性的追求而導致的,即熱部署(OSGI實現模塊化熱部署)