日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

谈谈双亲委派模型的第四次破坏-模块化

發布時間:2025/3/16 编程问答 26 豆豆
生活随笔 收集整理的這篇文章主要介紹了 谈谈双亲委派模型的第四次破坏-模块化 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

?JDK9引入了模塊化系統來實現可配置的封裝隔離機制,同時JVM對類加載的架構也做出了調整,也就是雙親委派模型的第四次破壞

01 雙親委派模型

簡介

在JDK9引入之前,絕大多數Java程序會用下面三個類加載器進行加載

  • 啟動類加載器(Bootstrap Class Loader):由C++編寫,負責加載<JAVA_HOME>\jre\lib目錄下的類,例如最基本的Object,Integer,這些存在于rt.jar文件中的類,一般這些類都是Java程序的基石。

  • 擴展類加載器(Extension Class Loader):負責加載<JAVA_HOME>\jre\lib\ext目錄下的類,在JDK9之前我們可以將通用性的類庫放在ext目錄來擴展JAVA的功能,但實際的工程都是通過maven引入jar包依賴。并且在JDK9取消了這一類加載器,取而代之的是平臺類加載器(Platform Class Loader),下面會對其介紹。

  • 應用類加載器(Application Class Loader):負責加載ClassPath路徑下的類,通常工程師編寫的大部分類都是由這個類加載器加載。

工作順序

解釋

如果一個ClassLoader收到了類加載的請求,他會先首先將請求委派給父類加載器完成,只有父類加載器加載不了,子加載器才會完成加載。

源代碼

下面代碼保留了核心邏輯,并添加了注釋,主要是2個步驟

  • 如果父類加載器不為空則用父類加載器加載

  • 父類加載器加載不成功則本身再加載

  • ? ? ? ? ? ?Class<?> c = findLoadedClass(name);//如果該類沒加載過if (c == null) {try {//如果有父類加載器if (parent != null) {//使用父類加載器加載c = parent.loadClass(name, false);...}}if (c == null) {...//父類加載器沒有加載成功則調用自身的findClass進行加載c = findClass(name); ...}}

    圖示

    如果覺得上面的解釋比較抽象可以看看下面比較形象的圖示,這里的敵人就是我們要加載的jar包

    缺點


    通過上面的漫畫不言而喻,當真正的敵人來了,靠這種低效的傳達機制,怎么可能打一場勝仗呢?

    • 啟動類加載器負責加載<JAVA_HOME>\jre\lib目錄

    • 擴展類加載器負責加載<JAVA_HOME>\jre\lib\ext目錄

    • 應用類加載器負責加載ClassPath目錄。

    既然一切都是各司其職,為什么不能加載類的時候一步到位呢?

    通過分析JDK9的類加載器源碼,我發現最新的類加載器結構在一定程度上是緩解了這種情況的

    02 JDK的模塊化

    在JDK9之前,JVM的基礎類以前都是在rt.jar這個包里,這個包也是JRE運行的基石。這不僅是違反了單一職責原則,同樣程序在編譯的時候會將很多無用的類也一并打包,造成臃腫。

    在JDK9中,整個JDK都基于模塊化進行構建,以前的rt.jar, tool.jar被拆分成數十個模塊,編譯的時候只編譯實際用到的模塊,同時各個類加載器各司其職,只加載自己負責的模塊。

    03 模塊化加載源碼

    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);}}

    上面代碼就是破壞雙親委派模型的“鐵證”,而當我們繼續跟進findLoadedModule,會發現是根據路徑名找到對應的模塊,而維護這一數據結構的就是下面這個Map。

    Map<String, LoadedModule> packageToModule= new ConcurrentHashMap<>(1024);

    可以看到LoadedModule里面不僅有該模塊的loader信息,還有用于描述依賴模塊,對外暴露模塊的信息的mref,LoadedModule也是模塊化實現封裝隔離機制的一塊重要實現。

    每一個module信息都有一個BuiltinClassloader,這個類有三個子類,我們通過源碼分析他們的父子關系

    在ClassLoaders類中可以發現,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 結論

  • 經過破壞后的雙親委派模型更加高效,減少了很多類加載器之間不必要的委派操作

  • JDK9的模塊化可以減少Java程序打包的體積,同時擁有更好的隔離線與封裝性

    每個module擁有專屬的類加載器,程序在并發性上也會更加出色

  • 有道無術,術可成;有術無道,止于術

    歡迎大家關注Java之道公眾號

    好文章,我在看??

    總結

    以上是生活随笔為你收集整理的谈谈双亲委派模型的第四次破坏-模块化的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。