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

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程语言 > java >内容正文

java

模块化加载_Java9模块化的类加载机制实现剖析

發(fā)布時間:2023/12/15 java 19 豆豆
生活随笔 收集整理的這篇文章主要介紹了 模块化加载_Java9模块化的类加载机制实现剖析 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

前言

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個步驟

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

    值得注意的是這里的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); } }

    結論

  • 經過破壞后的雙親委派模型更加高效,減少了很多類加載器之間不必要的委派操作
  • JDK9的模塊化可以減少Java程序打包的體積,同時擁有更好的隔離線與封裝性
  • 每個moudle擁有專屬的類加載器,程序在并發(fā)性上也會更加出色
  • 創(chuàng)作挑戰(zhàn)賽新人創(chuàng)作獎勵來咯,堅持創(chuàng)作打卡瓜分現(xiàn)金大獎

    總結

    以上是生活随笔為你收集整理的模块化加载_Java9模块化的类加载机制实现剖析的全部內容,希望文章能夠幫你解決所遇到的問題。

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