谈谈双亲委派模型的第四次破坏-模块化
“?JDK9引入了模塊化系統(tǒng)來實現(xiàn)可配置的封裝隔離機制,同時JVM對類加載的架構(gòu)也做出了調(diào)整,也就是雙親委派模型的第四次破壞”
01 雙親委派模型
簡介
在JDK9引入之前,絕大多數(shù)Java程序會用下面三個類加載器進行加載
啟動類加載器(Bootstrap Class Loader):由C++編寫,負責(zé)加載<JAVA_HOME>\jre\lib目錄下的類,例如最基本的Object,Integer,這些存在于rt.jar文件中的類,一般這些類都是Java程序的基石。
擴展類加載器(Extension Class Loader):負責(zé)加載<JAVA_HOME>\jre\lib\ext目錄下的類,在JDK9之前我們可以將通用性的類庫放在ext目錄來擴展JAVA的功能,但實際的工程都是通過maven引入jar包依賴。并且在JDK9取消了這一類加載器,取而代之的是平臺類加載器(Platform Class Loader),下面會對其介紹。
應(yīng)用類加載器(Application Class Loader):負責(zé)加載ClassPath路徑下的類,通常工程師編寫的大部分類都是由這個類加載器加載。
工作順序
解釋
如果一個ClassLoader收到了類加載的請求,他會先首先將請求委派給父類加載器完成,只有父類加載器加載不了,子加載器才會完成加載。
源代碼
下面代碼保留了核心邏輯,并添加了注釋,主要是2個步驟
如果父類加載器不為空則用父類加載器加載
父類加載器加載不成功則本身再加載
圖示
如果覺得上面的解釋比較抽象可以看看下面比較形象的圖示,這里的敵人就是我們要加載的jar包
缺點
通過上面的漫畫不言而喻,當(dāng)真正的敵人來了,靠這種低效的傳達機制,怎么可能打一場勝仗呢?
啟動類加載器負責(zé)加載<JAVA_HOME>\jre\lib目錄
擴展類加載器負責(zé)加載<JAVA_HOME>\jre\lib\ext目錄
應(yīng)用類加載器負責(zé)加載ClassPath目錄。
既然一切都是各司其職,為什么不能加載類的時候一步到位呢?
通過分析JDK9的類加載器源碼,我發(fā)現(xiàn)最新的類加載器結(jié)構(gòu)在一定程度上是緩解了這種情況的
02 JDK的模塊化
在JDK9之前,JVM的基礎(chǔ)類以前都是在rt.jar這個包里,這個包也是JRE運行的基石。這不僅是違反了單一職責(zé)原則,同樣程序在編譯的時候會將很多無用的類也一并打包,造成臃腫。
在JDK9中,整個JDK都基于模塊化進行構(gòu)建,以前的rt.jar, tool.jar被拆分成數(shù)十個模塊,編譯的時候只編譯實際用到的模塊,同時各個類加載器各司其職,只加載自己負責(zé)的模塊。
03 模塊化加載源碼
Class<?> c = findLoadedClass(cn); if (c == null) { // 找到當(dāng)前類屬于哪個模塊LoadedModule loadedModule = findLoadedModule(cn); if (loadedModule != null) { //獲取當(dāng)前模塊的類加載器BuiltinClassLoader loader = loadedModule.loader(); //進行類加載c = findClassInModuleOrNull(loadedModule, cn);} else {// 找不到模塊信息才會進行雙親委派 if (parent != null) {c = parent.loadClassOrNull(cn);}}上面代碼就是破壞雙親委派模型的“鐵證”,而當(dāng)我們繼續(xù)跟進findLoadedModule,會發(fā)現(xiàn)是根據(jù)路徑名找到對應(yīng)的模塊,而維護這一數(shù)據(jù)結(jié)構(gòu)的就是下面這個Map。
Map<String, LoadedModule> packageToModule= new ConcurrentHashMap<>(1024);可以看到LoadedModule里面不僅有該模塊的loader信息,還有用于描述依賴模塊,對外暴露模塊的信息的mref,LoadedModule也是模塊化實現(xiàn)封裝隔離機制的一塊重要實現(xiàn)。
每一個module信息都有一個BuiltinClassloader,這個類有三個子類,我們通過源碼分析他們的父子關(guān)系
在ClassLoaders類中可以發(fā)現(xiàn),PlatformClassLoader的parent是BootClassLoader,而AppClassLoader的parent則是PlatformClassLoader。
public class ClassLoaders {// the built-in class loaders private static final BootClassLoader BOOT_LOADER; private static final PlatformClassLoader PLATFORM_LOADER; private static final AppClassLoader APP_LOADER;static {????????//BootClassLoader BOOT_LOADER = new BootClassLoader((append != null && !append.isEmpty()) ? new URLClassPath(append, true) : null);????????//PlatformClassLoader PLATFORM_LOADER = new PlatformClassLoader(BOOT_LOADER);????????...????????//AppClassLoader APP_LOADER = new AppClassLoader(PLATFORM_LOADER, ucp); } }04 結(jié)論
經(jīng)過破壞后的雙親委派模型更加高效,減少了很多類加載器之間不必要的委派操作
JDK9的模塊化可以減少Java程序打包的體積,同時擁有更好的隔離線與封裝性
每個module擁有專屬的類加載器,程序在并發(fā)性上也會更加出色
有道無術(shù),術(shù)可成;有術(shù)無道,止于術(shù)
歡迎大家關(guān)注Java之道公眾號
好文章,我在看??
總結(jié)
以上是生活随笔為你收集整理的谈谈双亲委派模型的第四次破坏-模块化的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: NYOJ 30 Gone Fishin
- 下一篇: NYOJ 711 最舒适的路线(并查集)