欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

編譯大型Java項目class沖突導(dǎo)致報錯的解決方案

 更新時間:2023年10月19日 10:25:02   作者:在下uptown  
這篇文章給大家盤點編譯大型項目class沖突導(dǎo)致報錯的解決方案,文中通過代碼示例介紹的非常詳細,具有一定的參考價值,需要的朋友可以參考下

前言

作為一名合格的JavaBoy,想必大家都遇到過調(diào)試大型項目的時候編譯完都遇到過一些奇奇怪怪的問題,比如說下面這種。

看起來是一個序列化框架報出來的異常,但是沿著堆棧排查又找不到什么線索,最后把剛開發(fā)的模塊排除后就會發(fā)現(xiàn)這個異常又消失了,代碼里并沒有用到報錯的類,這種情況很有可能遇到了二方庫中的類沖突。

本質(zhì)上就是項目模塊太多,依賴錯綜復(fù)雜,新模塊引入的二方庫中的類與原項目二方庫中的類沖突了??赡苁窃瓉硪蕾嚨陌姹九c新模塊中依賴的版本不一致,導(dǎo)致加載類結(jié)束后缺少一些類的情況。比較直觀的報錯有

java.lang.ClassNotFundException
java.lang.NoSuchMethodError
java.lang.NoClassDefFoundError
java.lang.LinkageError

如果直接報出這些異常還有思路去排查,就怕報出一些奇奇怪怪的異常,今天盤點一下遇到類沖突之后如何解決。

查找沖突

mvn dependency:tree

maven提供了一個命令打印項目中所有的依賴樹,打印出的消息類似下面的圖,從樹中可以找到?jīng)_突class是來自哪個包哪個模塊。增加-Dverbose: verbose參數(shù)將詳細顯示項目所依賴的所有Jar包

但是這樣有個致命弱點,就是只能在開發(fā)階段排查,假如編譯期間報錯還好,如果運行期間加載到某個類出現(xiàn)沖突報錯就尷尬了,如果已經(jīng)打好包在集成環(huán)境出現(xiàn)這種問題,這種情況我們就無法通過命令直接去編譯源代碼查看沖突。

其次就是編譯項目太慢了,一個大型項目有幾十個模塊,編譯一次5分鐘過去了,雖然可以用著5分鐘去掘金摸會魚,但作為一個成熟的JavaBoy摸魚建立在把手頭工作搞好的前提下~

使用第三方工具排查

點名Arthas

bash腳本

這個腳本我屢試不爽,非常好用

#!/bin/bash
# 獲取傳入的參數(shù)
search_directory="$1"
search_class="$2"


# 檢查參數(shù)是否為空
if [ -z "$search_directory" ] || [ -z "$search_class" ]; then
    echo "請?zhí)峁┮阉鞯哪夸浐皖愇募Q作為參數(shù)。"
    exit 1
fi


# 搜索指定目錄及子目錄下的Jar包
find "$search_directory" -name "*.jar" -type f | while read -r jarfile; do
    # 在Jar包中查找包含指定類文件名稱的文件
    jar tf "$jarfile" | grep "$search_class" | while read -r classfile; do
        # 輸出Jar包名稱和包含的類文件名稱
        echo "Jar包:$jarfile  類文件:$classfile"      
    done
done

shell腳本也很簡單,執(zhí)行下面命令就能找到指定目錄下jar包中包含com.esotericsoftware.kryo.io.Input.inputStream類的包,這種方式不僅快而且很高效。

sh find_class.sh /tmp com.esotericsoftware.kryo.io.Input.inputStream

解決方案

找到?jīng)_突的類只是第一步,如何解決呢,這個問題本質(zhì)上是項目中出現(xiàn)了不同模塊引入了相同的類,如何定義相同得類,java的類加載器認為如果兩個class的全限定名完全一樣那就是相同的類。那想辦法讓這倆類的全限定名不一樣不就行了。

maven-shade-plugin

maven-shade-plugin是maven的一個插件,配置了這個插件打包的時候會自動觸發(fā)shade,shade直譯為陰影,顧名思義就是幫你把某個class藏起來。

hideOnBush

一般大型項目通常都是用maven來構(gòu)建項目,比如一個大項目有10個子模塊,你添加第11個子模塊時候com.google.common類沖突了,那么你在第11個模塊中配置如下

<plugins>
    <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-shade-plugin</artifactId>
        <version>3.1.0</version>
        <executions>
            <execution>
                <phase>package</phase>
                <goals>
                    <goal>shade</goal>
                </goals>
                <configuration>
                    <relocations>
                        <relocation>
                            <pattern>com.google.common</pattern>
                            <shadedPattern>shade.core.com.google.common</shadedPattern>
                        </relocation>
                    </relocations>
                </configuration>
            </execution>
        </executions>
    </plugin>

這樣在編譯的過程中com.google.common類會被隱藏為shade.core.com.google.common,全限定名不一樣了自然就不會再有沖突了。

解壓jar包

還有一種情況是通過引入外部jar包的方式引入依賴,代碼已經(jīng)被打成了jar包,但是jar包里有一些class沖突怎么辦呢。

這時候再用maven-shade-plugin也可以,但是一般我們都優(yōu)先修改外部的代碼,不輕易動原有的代碼結(jié)構(gòu),這時候有個騷操作就是解壓掉jar包,根據(jù)全限定名把沖突的包全刪了,再壓縮成jar包即可解決。

  • 將jar包解壓到一個臨時文件夾中
unzip a.jar -d /tmp/tmpdir
  • 進入文件夾刪除掉指定的包路徑
  • 重新打包jar文件,注意最后有個.
jar cf a-new.jar -C /tmp/tmpdir .

將新的jar包重新加入模塊你會發(fā)現(xiàn)項目暢通無阻。

到此這篇關(guān)于編譯大型Java項目class沖突導(dǎo)致報錯的解決方案的文章就介紹到這了,更多相關(guān)Java class沖突內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

最新評論