侬娜·杰尔_杰尔·地狱
儂娜·杰爾
什么是JAR地獄? (或者是classpath地獄?還是依賴(lài)地獄?)在考慮使用Maven或OSGi等現(xiàn)代開(kāi)發(fā)工具時(shí),哪些方面仍然有意義?
有趣的是,似乎沒(méi)有對(duì)這些問(wèn)題的結(jié)構(gòu)化答案(即,即使第二頁(yè)也沒(méi)有希望的頭條新聞)。 該職位應(yīng)填補(bǔ)這一空白。
總覽
我們將從構(gòu)成JAR地獄的一系列問(wèn)題開(kāi)始,暫時(shí)忽略構(gòu)建工具和組件系統(tǒng)。 當(dāng)我們?cè)u(píng)估當(dāng)前的狀況時(shí),我們將回到第二部分。
杰爾·地獄
JAR Hell是一個(gè)可愛(ài)的術(shù)語(yǔ),指的是Java的類(lèi)加載機(jī)制的特性所引起的問(wèn)題。 其中一些相互依存。 其他人是獨(dú)立的。
未表達(dá)的依賴(lài)性
JAR無(wú)法以JVM可以理解的方式來(lái)表示它依賴(lài)的其他JAR。 需要一個(gè)外部實(shí)體來(lái)識(shí)別和實(shí)現(xiàn)依賴(lài)關(guān)系。 開(kāi)發(fā)人員必須通過(guò)閱讀文檔,找到正確的項(xiàng)目,下載JAR并將其添加到項(xiàng)目中來(lái)手動(dòng)執(zhí)行此操作。 可選的依賴(lài)項(xiàng)(如果開(kāi)發(fā)人員要使用某些功能,則JAR可能僅需要另一個(gè)JAR)會(huì)使該過(guò)程更加復(fù)雜。
運(yùn)行時(shí)直到需要訪問(wèn)它們之前,它都不會(huì)檢測(cè)到它們。 這將導(dǎo)致NoClassDefFoundError崩潰正在運(yùn)行的應(yīng)用程序。
傳遞依存關(guān)系
為了使應(yīng)用程序正常工作,可能只需要少數(shù)幾個(gè)庫(kù)。 每個(gè)反過(guò)來(lái)可能需要少量其他庫(kù),依此類(lèi)推。 由于未表達(dá)的依賴(lài)關(guān)系的問(wèn)題變得更加復(fù)雜,因此它變得更加費(fèi)力且容易出錯(cuò)。
遮蔽
有時(shí),類(lèi)路徑上的不同JAR包含具有相同完全限定名稱(chēng)的類(lèi)。 可能由于不同的原因而發(fā)生這種情況,例如,當(dāng)同一庫(kù)有兩個(gè)不同版本時(shí),當(dāng)胖JAR包含的依賴(lài)項(xiàng)也作為獨(dú)立JAR引入時(shí),或者當(dāng)一個(gè)庫(kù)被重命名并在不知不覺(jué)中兩次添加到類(lèi)路徑中時(shí)。
由于將從類(lèi)路徑上的第一個(gè)JAR加載類(lèi)以包含它們,因此該變體將“陰影化”所有其他類(lèi)并使它們不可用。
如果變體在語(yǔ)義上有所不同,則可能導(dǎo)致從微妙到通知錯(cuò)誤的行為到破壞破壞性錯(cuò)誤的一切。 更糟糕的是,此問(wèn)題本身表現(xiàn)出來(lái)的形式似乎不確定。 這取決于搜索JAR的順序。 這在不同的環(huán)境中可能會(huì)有所不同,例如在開(kāi)發(fā)人員的IDE和最終將運(yùn)行代碼的生產(chǎn)機(jī)之間。
版本沖突
當(dāng)兩個(gè)所需的庫(kù)依賴(lài)于第三個(gè)庫(kù)的不同的,不兼容的版本時(shí),就會(huì)出現(xiàn)此問(wèn)題。
如果兩個(gè)版本都存在于類(lèi)路徑中,則該行為將不可預(yù)測(cè)。 首先,由于存在陰影,兩個(gè)版本中都存在的類(lèi)將僅從其中一個(gè)加載。 更糟糕的是,如果訪問(wèn)一個(gè)中存在但另一個(gè)不存在的類(lèi),則該類(lèi)也將被加載。 因此,調(diào)用庫(kù)的代碼可能會(huì)同時(shí)找到這兩個(gè)版本。
由于需要不兼容的版本,如果缺少其中一個(gè)版本,則該程序很可能無(wú)法正確運(yùn)行。 同樣,這可以表現(xiàn)為意外行為或NoClassDefFoundErrors。
復(fù)雜類(lèi)加載
默認(rèn)情況下,所有應(yīng)用程序類(lèi)均由同一類(lèi)加載器加載,但開(kāi)發(fā)人員可以自由添加其他類(lèi)加載器。
這通常是通過(guò)組件系統(tǒng)和Web服務(wù)器之類(lèi)的容器完成的。 理想情況下,這種隱式使用對(duì)應(yīng)用程序開(kāi)發(fā)人員是完全隱藏的,但是,眾所周知, 所有抽象都是泄漏的 。 在某些情況下,開(kāi)發(fā)人員可能會(huì)明確添加類(lèi)加載器以實(shí)現(xiàn)功能,例如,允許其用戶(hù)通過(guò)加載新類(lèi)來(lái)擴(kuò)展應(yīng)用程序,或者能夠使用具有相同依賴(lài)關(guān)系的沖突版本。
不管多個(gè)類(lèi)加載器如何進(jìn)入畫(huà)面,它們都可以Swift導(dǎo)致顯示出意料之外且難以理解的行為的復(fù)雜機(jī)制。
類(lèi)路徑地獄和依賴(lài)地獄
Classpath地獄和JAR地獄本質(zhì)上是同一件事,盡管后者似乎更加關(guān)注由復(fù)雜的類(lèi)加載器層次結(jié)構(gòu)引起的問(wèn)題。 這兩個(gè)術(shù)語(yǔ)都特定于Java和JVM。
另一方面, 依賴(lài)地獄是一個(gè)使用更廣泛的術(shù)語(yǔ)。 它描述了軟件包及其依賴(lài)項(xiàng)的一般問(wèn)題,適用于操作系統(tǒng)以及各個(gè)開(kāi)發(fā)生態(tài)系統(tǒng)。 考慮到它的通用性,它并不涵蓋特定于單個(gè)系統(tǒng)的問(wèn)題。
從上面的列表中,它包括可傳遞的和可能未表達(dá)的依賴(lài)關(guān)系以及版本沖突。 類(lèi)的加載和屏蔽是Java特定的機(jī)制,依賴(lài)地獄將不會(huì)涵蓋這些機(jī)制。
發(fā)布時(shí)間由惠康圖書(shū)館在CC-BY 4.0
事態(tài)
制作工具
在問(wèn)題列表中,我們看到了構(gòu)建工具如何幫助解決其中的一些問(wèn)題。 它們擅長(zhǎng)使依賴(lài)關(guān)系顯式化,以便可以沿著傳遞依賴(lài)關(guān)系樹(shù)的眾多邊緣查找每個(gè)所需的JAR。 這在很大程度上解決了未表達(dá)和傳遞依賴(lài)的問(wèn)題。
但是Maven等。 對(duì)陰影不做任何事情。 雖然它們通常會(huì)努力減少重復(fù)的類(lèi), 但不能阻止它們 。 除了指出版本沖突之外,構(gòu)建工具也無(wú)濟(jì)于事。 而且由于類(lèi)加載是運(yùn)行時(shí)構(gòu)造,因此它們也不會(huì)涉及。
組件系統(tǒng)
我從未使用過(guò)OSGi或Wildfly之類(lèi)的組件系統(tǒng),因此無(wú)法證明它們的工作情況。 根據(jù)他們的說(shuō)法,他們似乎能夠解決大多數(shù)JAR地獄問(wèn)題。
但是,這帶來(lái)了額外的復(fù)雜性,并且經(jīng)常要求開(kāi)發(fā)人員更深入地研究類(lèi)加載器機(jī)制。 具有諷刺意味的是,上面的列表中也有一點(diǎn)。
但是,無(wú)論組件系統(tǒng)是否確實(shí)在很大程度上緩解了JAR地獄的痛苦,我的印象是,絕大多數(shù)項(xiàng)目都沒(méi)有使用它們。 在這種假設(shè)下,絕大多數(shù)人仍然遭受與類(lèi)路徑有關(guān)的問(wèn)題。
這在哪里離開(kāi)我們?
由于它們未被廣泛使用,因此組件系統(tǒng)不會(huì)影響大局。 但是,構(gòu)建工具的普遍存在極大地改變了JAR地獄不同圈子的嚴(yán)重性。
我參與或聽(tīng)說(shuō)過(guò)的任何構(gòu)建工具都不支持的項(xiàng)目都花了相當(dāng)長(zhǎng)的時(shí)間來(lái)處理來(lái)自未表達(dá)或可傳遞依賴(lài)的問(wèn)題。 陰影有時(shí)會(huì)抬起丑陋的頭,需要花費(fèi)不同的時(shí)間來(lái)解決-但最終總是如此。
版本沖突是JAR地獄中最棘手的問(wèn)題。
但是每個(gè)項(xiàng)目遲早都要依靠相互沖突的版本進(jìn)行戰(zhàn)斗,并且必須做出一些艱難的決定才能解決這些問(wèn)題。 通常,必須推遲某些所需的更新,因?yàn)檫@將強(qiáng)制執(zhí)行當(dāng)前無(wú)法執(zhí)行的其他更新。
我敢說(shuō),對(duì)于大多數(shù)大小合適的應(yīng)用程序,服務(wù)和庫(kù),版本沖突是何時(shí)以及如何更新依賴(lài)項(xiàng)的主要決定因素之一。 我覺(jué)得這是無(wú)法忍受的。
對(duì)于非平凡的類(lèi)加載器層次結(jié)構(gòu),我經(jīng)驗(yàn)不足,無(wú)法評(píng)估它們是多少個(gè)重復(fù)出現(xiàn)的問(wèn)題。 但是考慮到我到目前為止從事的所有項(xiàng)目都不要求它們,所以我敢說(shuō)它們并不常見(jiàn)。 在網(wǎng)絡(luò)上搜索使用它們的原因通常會(huì)發(fā)現(xiàn)我們已經(jīng)討論的內(nèi)容:依賴(lài)關(guān)系導(dǎo)致版本沖突。
因此,根據(jù)我的經(jīng)驗(yàn),我會(huì)說(shuō)版本沖突是JAR地獄中最棘手的問(wèn)題。
反射
我們已經(jīng)討論了JAR地獄的構(gòu)成要素:
- 未表達(dá)的依賴(lài)性
- 傳遞依賴(lài)
- 遮蔽
- 版本沖突
- 復(fù)雜類(lèi)加載
根據(jù)為游戲帶來(lái)的構(gòu)建工具和組件系統(tǒng)以及它們的使用范圍,我們得出結(jié)論,很大程度上解決了未表達(dá)的和可傳遞的依賴(lài)關(guān)系,這至少掩蓋了減輕的負(fù)擔(dān)和不常見(jiàn)的復(fù)雜類(lèi)加載。
這使版本沖突成為JAR地獄中最有問(wèn)題的方面,影響了大多數(shù)項(xiàng)目中的日常更新決策。
翻譯自: https://www.javacodegeeks.com/2015/10/jar-hell.html
儂娜·杰爾
總結(jié)
以上是生活随笔為你收集整理的侬娜·杰尔_杰尔·地狱的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 什么是武术精神 武术精神是什么
- 下一篇: a4大小 a4大小是怎样的