模块化加载_Java9模块化的类加载机制实现剖析
前言
JDK9引入了Java模塊化系統(tǒng)(Java Platform Moudle System)來實現(xiàn)可配置的封裝隔離機制,同時JVM對類加載的架構也做出了調整,也就是雙親委派模型的第四次破壞。前三次破壞分別是:雙親委派模型推出之前,SPI機制,以及OSGI為代表的熱替換機制,這里不細說。
雙親委派模型
簡介
在JDK9引入之前,絕大多數(shù)Java程序會用下面三個類加載器進行加載
- 啟動類加載器(Bootstrap Class Loader):由C++編寫,負責加載jrelib目錄下的類,例如最基本的Object,Integer,這些存在于rt.jar文件中的類,一般這些類都是Java程序的基石。
- 擴展類加載器(Extension Class Loader):負責加載jrelibext目錄下的類,在JDK9之前我們可以將通用性的類庫放在ext目錄來擴展JAVA的功能,但實際的工程都是通過maven引入jar包依賴。并且在JDK9取消了這一類加載器,取而代之的是平臺類加載器(Platform Class Loader),下面會對其介紹。
- 應用類加載器(Application Class Loader):負責加載ClassPath路徑下的類,通常工程師編寫的大部分類都是由這個類加載器加載。
工作順序
解釋
如果一個ClassLoader收到了類加載的請求,他會先首先將請求委派給父類加載器完成,只有父類加載器加載不了,子加載器才會完成加載。
源代碼
下面代碼保留了核心邏輯,并添加了注釋,主要是2個步驟
值得注意的是這里的parent并不是繼承上的父子關系,而是組合關系的父子,parent只是類加載器的一個參數(shù)。
圖示
如果覺得上面的解釋比較抽象可以看看下面比較形象的圖示,這里的敵人就是我們要加載的jar包
缺點
通過上面的漫畫不言而喻,當真正的敵人來了,靠這種低效的傳達機制,怎么可能打一場勝仗呢?
- 啟動類加載器負責加載jrelib目錄
- 擴展類加載器負責加載jrelibext目錄
- 應用類加載器負責加載ClassPath目錄。
既然一切都是各司其職,為什么不能加載類的時候一步到位呢?
通過分析JDK9的類加載器源碼,我發(fā)現(xiàn)最新的類加載器結構在一定程度上是緩解了這種情況的
JDK的模塊化
在JDK9之前,JVM的基礎類以前都是在rt.jar這個包里,這個包也是JRE運行的基石。這不僅是違反了單一職責原則,同樣程序在編譯的時候會將很多無用的類也一并打包,造成臃腫。
在JDK9中,整個JDK都基于模塊化進行構建,以前的rt.jar, tool.jar被拆分成數(shù)十個模塊,編譯的時候只編譯實際用到的模塊,同時各個類加載器各司其職,只加載自己負責的模塊。
模塊化加載源碼
Class> c = findLoadedClass(cn); if (c == null) { // 找到當前類屬于哪個模塊 LoadedModule loadedModule = findLoadedModule(cn); if (loadedModule != null) { //獲取當前模塊的類加載器 BuiltinClassLoader loader = loadedModule.loader(); //進行類加載 c = findClassInModuleOrNull(loadedModule, cn); } else { // 找不到模塊信息才會進行雙親委派 if (parent != null) { c = parent.loadClassOrNull(cn); } }上面代碼就是破壞雙親委派模型的“鐵證”,而當我們繼續(xù)跟進findLoadedModule,會發(fā)現(xiàn)是根據(jù)路徑名找到對應的模塊,而維護這一數(shù)據(jù)結構的就是下面這個Map。
Map packageToModule = new ConcurrentHashMap<>(1024);可以看到LoadedModule里面不僅有該模塊的loader信息,還有用于描述依賴模塊,對外暴露模塊的信息的mref,LoadedModule也是模塊化實現(xiàn)封裝隔離機制的一塊重要實現(xiàn)。
每一個module信息都有一個BuiltinClassloader,這個類有三個子類,我們通過源碼分析他們的父子關系
在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 { BOOT_LOADER = new BootClassLoader((append != null && !append.isEmpty()) ? new URLClassPath(append, true) : null); PLATFORM_LOADER = new PlatformClassLoader(BOOT_LOADER); ... APP_LOADER = new AppClassLoader(PLATFORM_LOADER, ucp); } }結論
總結
以上是生活随笔為你收集整理的模块化加载_Java9模块化的类加载机制实现剖析的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 网商贷降额度原因 网商贷降额度的原因
- 下一篇: Java31 gt gt gt 2_Ja