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

歡迎訪問 生活随笔!

生活随笔

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

编程问答

一次Maven依赖冲突采坑,把依赖调解、类加载彻底整明白了

發布時間:2025/3/16 编程问答 19 豆豆
生活随笔 收集整理的這篇文章主要介紹了 一次Maven依赖冲突采坑,把依赖调解、类加载彻底整明白了 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

今年年初的時候,閱讀過《Maven實戰》,當時有了解到Maven可以依賴調解,即當包版本不一致時,會根據一定規則選擇相應的包來加載,從而避免沖突。當時不解的是既然Maven都能解決沖突,為何還經常聽到“發生了依賴沖突”,沖突不是解決了嗎,還存在什么問題呢?直到這周在工作中自己遇到了,就明白是咋回事了。下面先從我的實際經歷說起。

1. Maven依賴沖突經歷

我在Y模塊中,寫了一個Encryptor類,主要是使用了DigestUtils、MessageDigest、HmacUtils等類對字符串進行加密(下面代碼是隨便寫的,只表示使用到了這些類),如下:

import?org.apache.commons.codec.binary.Hex; import?org.apache.commons.codec.digest.DigestUtils; import?org.apache.commons.codec.digest.HmacUtils;import?java.nio.charset.StandardCharsets; import?java.security.MessageDigest;public?class?Encryptor?{public?String?encrype(String?s)?{MessageDigest?sha256Digest?=?DigestUtils.getSha256Digest();String?result?=?Hex.encodeHexString(sha256Digest.digest(s.getBytes(StandardCharsets.UTF_8)));return?Hex.encodeHexString(HmacUtils.getHmacSha256(result.getBytes()).doFinal(result.getBytes()));}public?static?void?main(String[]?args)?{Encryptor?encryptor?=?new?Encryptor();String?s?=?"test";String?result?=?encryptor.encrype(s);System.out.println(result);}/**output:?fdd04dcac94e9803a72e4268141f773e2024a8fe46ba19a263be22c5ca83e931**/}

執行單元測試可以正常運行。但是當整個應用啟動時,則會報IllegalAccessError錯誤。

應用啟動報錯IllegalAccessError

在Y模塊下的單元測試運行時不會報錯,但是當整個應用啟動,作為程序入口的X模塊,調用Y模塊中的Encryptor時,發生了IllegalAccessError報錯。根據圖中的具體報錯信息,是說沒有權限訪問getSha256Digest方法,我Ctrl+B點進getSha256Digest方法查看,如下:

getSha256Digest是public

getSha256Digest方法是public的訪問級別,我一臉懵。由于這個方法很簡單,既然報錯,那我就索性不用了,換成下面這種寫法。

public?String?encrype(String?s)?{try?{MessageDigest?sha256Digest?=?MessageDigest.getInstance("SHA-256");String?result?=?Hex.encodeHexString(sha256Digest.digest(s.getBytes(StandardCharsets.UTF_8)));return?Hex.encodeHexString(HmacUtils.getHmacSha256(result.getBytes()).doFinal(result.getBytes()));}?catch?(NoSuchAlgorithmException?e)?{e.printStackTrace();return?"error";} }

又報錯了,好吧,真是躲不過了!報錯如下:

應用啟動報錯ClassNotFoundException

這次報的是ClassNotFoundException,HmacUtils這個類找不到。可是我Ctrl+B進去,這個類好好的就在那里啊。這時我才把注意力集中在思考是不是發生了Maven依賴沖突。我打開pom.xml,用Dependency Analyzer查看,果然我使用的commons-codec包發生了沖突。

X模塊的依賴樹

在Y模塊中,依賴關系:Y -> B -> C -> commons-codec-1.10。而在X模塊中,引用了A包:X -> A -> commons-codec-1.6,也引用了Y模塊:X -> Y -> B -> C -> commons-codec-1.10。可見commons-codec包有兩個版本1.6和1.10,所以Maven會進行依賴調解,第一原則是“路徑最短者優先”,自然只會使用1.6版本的包。而我再去查看1.6的包下,getSha256Digest方法是private的訪問級別,HmacUtils這個類也不存在。解釋了之前的報錯。解決該沖突,通過排除依賴便能解決了,將A包下的commons-codec排除,如下:

<dependencies><dependency><groupId>com.chaycao.maven.dependency</groupId><artifactId>A</artifactId><version>1.0-SNAPSHOT</version><exclusions><exclusion><artifactId>commons-codec</artifactId><groupId>commons-codec</groupId></exclusion></exclusions></dependency><dependency><groupId>com.chaycao.maven.dependency</groupId><artifactId>Y</artifactId><version>1.0-SNAPSHOT</version></dependency> </dependencies>

排除后,這時將只有1.10版本的包,程序也可以正常運行了。

2. 為什么需要Maven依賴調解

問題已經解決了,大家是不是也明白了,為什么依賴沖突會常導致發生NoClassDefFoundError、NoSuchMethodException、IllegalAccessError等錯誤。雖然Y模塊在編譯時,由于引入了commons-codec 1.10能正常編譯,但是在運行時,由于依賴沖突,只加載了1.6版本的包,所以不能正常運行。

注意:代碼的編譯僅僅是編譯當前的代碼。編譯成功后,最后能否正常運行,還要取決于運行時的環境是否等同或兼容編譯時環境。

下面我們想想為什么需要Maven依賴調解,如果不調解行不行。

當使用Maven的過程中,如果同時引入了groupId和artifactId相同而version不同的包時,Maven會認為發生了依賴沖突,將進行依賴調解,通過兩個原則決定使用哪個版本的包:第一原則,路徑最近者優先,如前文。如果路徑相同,則使用第二原則,在pom中第一聲明者優先。而當我們在點擊Run運行時,classpath中將只會有一個明確版本的包。

思考一下。Java在運行時,是否能引入版本不同的包。其實這個問題是在問,java命令的classpath參數中能不能有多個版本不同的包,當然是可以的。classpath參數的是用于指示JVM如何搜索class文件,當你在classpath中指定的路徑下有多個版本不同的包,JVM都會去jar包下搜索class文件進行加載,而至于class能不能成功加載,則在于ClassLoader的邏輯,當同名類被加載時,則不會再被加載,即同一個類只會被加載一次。這也意味,當有多個版本不同的包時,包在classpath中的順序,決定了哪個包中的類能先被加載。而這樣具有不確定性。因為在生產環境下通常使用shell命令將jar包拼接:

LIB_DIR=lib LIB_JARS=`ls?$LIB_DIR|grep?.jar|awk?'{print?"'$LIB_DIR'/"$0}'|tr?"\n"?":"`

不同環境下得到的jar包順序可能是不同的。而Maven依賴調解將使得只有一個明確版本的包參與構建,從而避免不確定性

3. 排查在線問題的利器-Arthas

Arthas,早有聽說,但一直未使用過,這次我嘗試了下,覺得確實可以,安利下。對于前文說的依賴沖突情況,當發生IllegalAccessError報錯時,可以通過Arthas直接查看運行情況下的DigestUtils。我們把代碼變為最初的情況,且在Main類中加個死循環,為了讓程序不死掉,以通過Arthas觀察。

public?class?Main?{public?static?void?main(String[]?args)?{while?(true)?{try?{Encryptor?encryptor?=?new?Encryptor();String?s?=?"1234567890";String?result?=?encryptor.encrype(s);System.out.println(result);}?catch?(Throwable?e)?{}}}}

打開Arthas,連接上我們的程序(可以通過官方教程學習),然后通過sc命令查看DigestUtils:

[arthas@32328]$?sc?-d?org.apache.commons.codec.digest.DigestUtilsclass-info????????org.apache.commons.codec.digest.DigestUtilscode-source???????/D:/mavenrepo/commons-codec/commons-codec/1.6/commons-codec-1.6.jarname??????????????org.apache.commons.codec.digest.DigestUtilsisInterface???????falseisAnnotation??????falseisEnum????????????falseisAnonymousClass??falseisArray???????????falseisLocalClass??????falseisMemberClass?????falseisPrimitive???????falseisSynthetic???????falsesimple-name???????DigestUtilsmodifier??????????publicannotationinterfacessuper-class???????+-java.lang.Objectclass-loader??????+-sun.misc.Launcher$AppClassLoader@58644d46+-sun.misc.Launcher$ExtClassLoader@24e74ca5classLoaderHash???58644d46

可以從code-source中清晰的查到DigestUtils是哪個包下的Class,這時就該意識到發生了依賴沖突問題。

而通過jad命令,還能反編譯,在線看代碼。好用!

參考

  • Arthas 實戰,助你解決同名類依賴沖突問題(https://www.cnblogs.com/goodAndyxublog/p/12424734.html)

  • Maven依賴沖突問題原理簡析(https://blog.csdn.net/qq_27529917/article/details/79741607)

  • 重新看待Jar包沖突問題及解決方案(http://www.yangbing.club/2017/07/15/solution-for-jar-conflicts/)

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

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

    好文章,我在看??

    總結

    以上是生活随笔為你收集整理的一次Maven依赖冲突采坑,把依赖调解、类加载彻底整明白了的全部內容,希望文章能夠幫你解決所遇到的問題。

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

    主站蜘蛛池模板: 天堂中文字幕免费一区 | 大香伊人| 欧美高清一区二区 | 日本高清在线观看 | 中文字幕一区二区三区乱码不卡 | 日韩欧美在线观看一区 | 欧美浓毛大泬视频 | 三上悠亚久久 | 亚洲熟妇丰满大屁股熟妇 | 亚洲免费小视频 | 久久6视频 | 含羞草一区二区三区 | 日本一区二区三区在线免费观看 | 欧美熟妇精品久久久久久 | 和黑帮大佬的365 | 91精品国产综合久久久密臀九色 | 国产福利免费 | 国产精品无码AV | jizz性欧美23| 中文久久精品 | 免费日韩视频 | 美女的奶胸大爽爽大片 | 日韩视频第一页 | 国产精品99久久久久久久久 | 色永久| www久久久久久久 | 亚洲日日骚| 极品美女被c | 岛国av毛片| 黄色香港三级三级三级 | 色先锋av | 日韩五月天 | 欧美亚洲伦理 | 蜜桃精品视频在线观看 | 欧美日韩99 | 午夜啪视频 | 制服丝袜国产精品 | 亚洲欧美激情在线观看 | 丰满秘书被猛烈进入高清播放在 | 国内外免费激情视频 | 欧美在线一卡 | 日韩欧美自拍偷拍 | 日本一道本在线 | 色婷婷www| 欧美日韩综合 | 欧美不卡在线 | 一区二区三区视频在线观看免费 | 老师上课夹震蛋高潮了 | 国产精品一区二区欧美 | 亚洲成人www | 欧美黑人激情 | 久久这里只有精品6 | 国产成人久久精品 | 日本特级黄色录像 | 91天堂视频| 老师用丝袜脚帮我脚交 | 午夜肉伦伦 | 国产又粗又猛又黄又爽无遮挡 | 少妇精品久久久一区二区三区 | youjizz麻豆| 在线观看亚洲一区 | av不卡免费在线观看 | www.午夜视频 | 直接看av的网站 | 色哟哟免费视频 | 韩国午夜影院 | av在线亚洲天堂 | 成人一二三 | 欧美放荡办公室videos4k | 黄色片免费在线观看 | 97超在线| av高清在线观看 | 中文字幕免费高清在线 | 91久久精品夜夜躁日日躁欧美 | 日韩91| 大尺度做爰床戏呻吟舒畅 | 成人欧美一区二区三区在线播放 | 欧美区在线 | 在线观看成年人网站 | 国产精品欧美综合 | 色老头影视 | 国产丰满大乳奶水在线视频 | 国产一级在线观看 | 天天操免费视频 | 成人av手机在线 | 你懂的网站在线观看 | 香蕉在线视频播放 | 波多野结衣在线一区 | 日韩亚洲欧美精品 | 日韩视频播放 | 天天插日日插 | 国产精品麻豆果冻传媒在线播放 | 高清一区二区 | 成人h视频在线 | 激情福利社 | 日本xx视频| 久久这里只有精品首页 | 国产午夜免费 | 精品国精品国产 |