日本综合一区二区|亚洲中文天堂综合|日韩欧美自拍一区|男女精品天堂一区|欧美自拍第6页亚洲成人精品一区|亚洲黄色天堂一区二区成人|超碰91偷拍第一页|日韩av夜夜嗨中文字幕|久久蜜综合视频官网|精美人妻一区二区三区

RELATEED CONSULTING
相關(guān)咨詢
選擇下列產(chǎn)品馬上在線溝通
服務(wù)時間:8:30-17:00
你可能遇到了下面的問題
關(guān)閉右側(cè)工具欄

新聞中心

這里有您想知道的互聯(lián)網(wǎng)營銷解決方案
Java歷史上有三次破壞雙親委派模型,是哪三次?

本文轉(zhuǎn)載自微信公眾號「yes的練級攻略」,作者是Yes呀。轉(zhuǎn)載本文請聯(lián)系yes的練級攻略公眾號。

從事西部信息中心,服務(wù)器租用,云主機(jī),網(wǎng)頁空間,國際域名空間,CDN,網(wǎng)絡(luò)代維等服務(wù)。

你好,我是yes。

這個面試題來自一位群友的面試題分享,就是我組建的那個面試交流群。

其實(shí)不止三次,有四次。

今天我們就來盤一盤這個面試題,不過在說雙親委派模型之前,我們得先簡單了解下類加載。

類加載

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

當(dāng)然,加載到 JVM 生成 class 對象的來源不一定得是.class文件,也可以來自網(wǎng)絡(luò)等等,反正只要是符合 JVM 規(guī)范的都行。

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

加載

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

鏈接

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

驗(yàn)證就是檢驗(yàn)一下加載的類是否滿足 JVM 的約束條件,也就是判斷是否合規(guī)。

準(zhǔn)備就是為加載類的靜態(tài)變量申請內(nèi)存空間,并賦予初始值,例如是 int 類型那初始值就是 0。

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

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

初始化

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

所以可以用一個內(nèi)部靜態(tài)類來實(shí)現(xiàn)延遲初始化的單例設(shè)計模式,同時保證了線程安全。

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

雙親委派模型

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

那什么是雙親委派模型?

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

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

  • 啟動類加載器(Bootstrap ClassLoader),它是屬于虛擬機(jī)自身的一部分,用 C++ 實(shí)現(xiàn)的,主要負(fù)責(zé)加載 \lib目錄中或被 -Xbootclasspath 指定的路徑中的并且文件名是被虛擬機(jī)識別的文件。它是所有類加載器的爸爸。
  • 擴(kuò)展類加載器(Extension ClassLoader),它是 Java 實(shí)現(xiàn)的,獨(dú)立于虛擬機(jī),主要負(fù)責(zé)加載 \lib\ext目錄中或被 java.ext.dirs 系統(tǒng)變量所指定的路徑的類庫。
  • 應(yīng)用程序類加載器(Application ClassLoader),它是Java實(shí)現(xiàn)的,獨(dú)立于虛擬機(jī)。主要負(fù)責(zé)加載用戶類路徑(classPath)上的類庫,如果我們沒有實(shí)現(xiàn)自定義的類加載器那這玩意就是我們程序中的默認(rèn)加載器。

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

其實(shí)就是為了讓基礎(chǔ)類得以正確地統(tǒng)一地加載。

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

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

第一次破壞

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

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

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

第二次破壞

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

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

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

MySQL 有 MySQL 的 JDBC 實(shí)現(xiàn),Oracle 有 Oracle 的 JDBC 實(shí)現(xiàn),我 Java 不管你內(nèi)部如何實(shí)現(xiàn)的,反正你們這些數(shù)據(jù)庫廠商都得統(tǒng)一按我這個來,這樣我們 Java 開發(fā)者才能容易的調(diào)用數(shù)據(jù)庫操作,所以在 Java 核心包里面定義了這個 SPI。

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

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

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

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

第三次破壞

這次破壞是為了滿足熱部署的需求,不停機(jī)更新這對企業(yè)來說至關(guān)重要,畢竟停機(jī)是大事。

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

這就是第三次破壞。

第四次破壞

在 JDK9 引入模塊系統(tǒng)之后,類加載器的實(shí)現(xiàn)其實(shí)做了一波更新。

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

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

關(guān)于 JDK9 相關(guān)的知識點(diǎn)就不展開了,有興趣的自行查閱。

所以這就是第四次破壞。

其他注意點(diǎn)

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

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

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

所以說類加載器還有命名空間的作用,我記得這個知識點(diǎn)也是一個面試題喲~


網(wǎng)站題目:Java歷史上有三次破壞雙親委派模型,是哪三次?
分享鏈接:http://www.dlmjj.cn/article/dhjecic.html