中文字幕av专区_日韩电影在线播放_精品国产精品久久一区免费式_av在线免费观看网站

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

Java的三次破壞雙親委派模型是什么

發布時間:2021-10-11 10:54:19 來源:億速云 閱讀:118 作者:iii 欄目:編程語言

這篇文章主要介紹“Java的三次破壞雙親委派模型是什么”,在日常操作中,相信很多人在Java的三次破壞雙親委派模型是什么問題上存在疑惑,小編查閱了各式資料,整理出簡單好用的操作方法,希望對大家解答”Java的三次破壞雙親委派模型是什么”的疑惑有所幫助!接下來,請跟著小編一起來學習吧!

Java的三次破壞雙親委派模型是什么

類加載

我們平常寫的代碼是保存在一個 .java文件里面,經過編譯會生成.class文件,這個文件存儲的就是字節碼,如果要用上我們的代碼,那就必須把它加載到  JVM 中。

Java的三次破壞雙親委派模型是什么

當然,加載到 JVM 生成 class 對象的來源不一定得是.class文件,也可以來自網絡等等,反正只要是符合 JVM 規范的都行。

而類加載的步驟主要分為:加載、鏈接、初始化。

加載

其實就是找到字節流,然后將其加載到 JVM 中,生成類對象。這個階段就是類加載器派上用場的階段,等下我們再細說。

鏈接

這個階段是要讓生成的類對象融入到 JVM 中,分別要經歷以下三個步驟:

Java的三次破壞雙親委派模型是什么

驗證就是檢驗一下加載的類是否滿足 JVM 的約束條件,也就是判斷是否合規。

準備就是為加載類的靜態變量申請內存空間,并賦予初始值,例如是 int 類型那初始值就是 0。

解析就是將符號引用解析成為實際引用,講人話就是:例如 Yes 類里面引用了一個 XX 類,那一開始 Yes 類肯定不知道 XX  類在內存里面的地址,所以就先搞個符號引用替代一下,假裝知道,等類加載解析的時候再找到 XX 類真正地址,做一個實際引用。

這就是解析要做的事情。還有一點,雖說把解析放到鏈接階段里面,但是 JVM 規范并沒有要求在鏈接過程中完成解析。

初始化

這個階段就是為常量字段賦值,然后執行靜態代碼塊,將一堆要執行的靜態代碼塊方法包裝成 clinit 方法執行,這個方法會加鎖,由 JVM 來保證  clinit 方法只會被執行一次。

所以可以用一個內部靜態類來實現延遲初始化的單例設計模式,同時保證了線程安全。

這個階段完畢之后,類加載過程就 ok 了,可以投入使用啦,再來畫個圖匯總一下:

Java的三次破壞雙親委派模型是什么

雙親委派模型

加載階段,需要用到類加載器來將 class 文件里面的內容搞到 JVM 中生成類對象。

那什么是雙親委派模型?

雙親委派模型用一句話講就是子類加載器先讓父類加載器去查找該類來加載,父類又繼續請求它的父類直到最頂層,在父類加載器沒有找到所請求的類的情況下,子類加載器才會嘗試去加載,這樣一層一層上去又下來。

Java的三次破壞雙親委派模型是什么

每個類加載器都有固定的查找類的路徑,在 JDK8 的時候一共有三種類加載器。

  • 啟動類加載器(Bootstrap ClassLoader),它是屬于虛擬機自身的一部分,用 C++  實現的,主要負責加載

    \lib目錄中或被 -Xbootclasspath  指定的路徑中的并且文件名是被虛擬機識別的文件。它是所有類加載器的爸爸。
  • 擴展類加載器(Extension ClassLoader),它是 Java  實現的,獨立于虛擬機,主要負責加載

    \lib\ext目錄中或被 java.ext.dirs 系統變量所指定的路徑的類庫。
  • 應用程序類加載器(Application  ClassLoader),它是Java實現的,獨立于虛擬機。主要負責加載用戶類路徑(classPath)上的類庫,如果我們沒有實現自定義的類加載器那這玩意就是我們程序中的默認加載器。

Java的三次破壞雙親委派模型是什么

為什么要提出雙親委派模型?

其實就是為了讓基礎類得以正確地統一地加載。

從上面的圖可以看出,如果你也定義了一個  java.lang.Object類,通過雙親委派模式是會把這個請求委托給啟動類加載器,它掃描\lib目錄就找到了 jdk 定義的  java.lang.Object 類來加載,所以壓根不會加載你寫的 java.lang.Object類,這就可以避免一些程序不小心或者有意的覆蓋基礎類。

至此我們已經清楚了什么是雙親委派,和為什么要雙親委派。接下來我們來看看三次破壞。

第一次破壞

在 jdk 1.2 之前,那時候還沒有雙親委派模型,不過已經有了 ClassLoader 這個抽象類,所以已經有人繼承這個抽象類,重寫 loadClass  方法來實現用戶自定義類加載器。

而在 1.2 的時候要引入雙親委派模型,為了向前兼容, loadClass 這個方法還得保留著使之得以重寫,新搞了個 findClass  方法讓用戶去重寫,并呼吁大家不要重寫 loadClass 只要重寫 findClass。

這就是第一次對雙親委派模型的破壞,因為雙親委派的邏輯在 loadClass 上,但是又允許重寫  loadClass,重寫了之后就可以破壞委派邏輯了。

第二次破壞

第二次破壞指的是 JNDI、JDBC 之類的情況。

首先得知道什么是 SPI(Service Provider Interface),它是面向拓展的,也就是說我定義了個規矩,就是 SPI  ,具體如何實現由擴展者實現。

像我們比較熟的 JDBC 就是如此。

MySQL 有 MySQL 的 JDBC 實現,Oracle 有 Oracle 的 JDBC 實現,我 Java  不管你內部如何實現的,反正你們這些數據庫廠商都得統一按我這個來,這樣我們 Java 開發者才能容易的調用數據庫操作,所以在 Java 核心包里面定義了這個  SPI。

而核心包里面的類都是由啟動類加載器去加載的,但它的手只能摸到\lib或Xbootclasspath指定的路徑中,其他的它鞭長莫及。

而 JDBC 的實現類在我們用戶定義的 classpath  中,只能由應用類加載器去加載,所以啟動類加載器只能委托子類來加載數據庫廠商們提供的具體實現,這就違反了自下而上的委托機制。

具體解決辦法是搞了個線程上下文類加載器,通過setContextClassLoader()默認情況就是應用程序類加載器,然后利用Thread.current.currentThread().getContextClassLoader()獲得類加載器來加載。

這就是第二次破壞雙親委派模型。

第三次破壞

這次破壞是為了滿足熱部署的需求,不停機更新這對企業來說至關重要,畢竟停機是大事。

OSGI  就是利用自定義的類加載器機制來完成模塊化熱部署,而它實現的類加載機制就沒有完全遵循自下而上的委托,有很多平級之間的類加載器查找,具體就不展開了,有興趣可以自行研究一下。

這就是第三次破壞。

第四次破壞

在 JDK9 引入模塊系統之后,類加載器的實現其實做了一波更新。

像擴展類加載器被重命名為平臺類加載器,核心類加載歸屬了做了一些劃分,平臺類加載器承擔了更多的類加載,上面提到的  -Xbootclasspath、java.ext.dirs 也都無效了,rt.jar 之類的也被移除,被整理存儲在 jimage 文件中,通過新的 JRT  文件系統訪問。

當收到類加載請求,會先判斷該類在具名模塊中是否有定義,如果有定義就自己加載了,沒的話再委派給父類。

關于 JDK9 相關的知識點就不展開了,有興趣的自行查閱。

所以這就是第四次破壞。

其他注意點

首先,雖說是子類父類,但是加載器之間的關系不是繼承,而是組合。

Java的三次破壞雙親委派模型是什么

看下代碼就很清晰了,具體的邏輯如下:

Java的三次破壞雙親委派模型是什么

在 JVM 中,類的唯一性是由類加載器實例和類的全限定名一同確定的,也就是說即使是同一個類文件加載的類,用不同的類加載器實例加載,在 JVM  看來這也是兩個類。

到此,關于“Java的三次破壞雙親委派模型是什么”的學習就結束了,希望能夠解決大家的疑惑。理論與實踐的搭配能更好的幫助大家學習,快去試試吧!若想繼續學習更多相關知識,請繼續關注億速云網站,小編會繼續努力為大家帶來更多實用的文章!

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

兴山县| 高唐县| 永康市| 彭阳县| 于都县| 饶河县| 淳安县| 梅河口市| 溧水县| 大埔区| 泾川县| 依兰县| 吉木萨尔县| 灌云县| 铁岭市| 唐山市| 宁陕县| 上饶县| 会理县| 出国| 兴文县| 长阳| 大余县| 达州市| 交城县| 方山县| 邳州市| 白山市| 嘉兴市| 四子王旗| 旺苍县| 红安县| 岳西县| 呼和浩特市| 左权县| 油尖旺区| 临桂县| 广丰县| 丰镇市| 陇西县| 泰和县|