java.lang.NoSuchMethodError 之 依賴衝突解決方案

NoSuchMethodError 解決方案大全

 

問題:

本機測試環境運行無誤,在服務器和別的jar包一起打包在一起運行報錯,這種大概率爲依賴衝突問題

java.lang.NoSuchMethodError:com.google.protobuf.CodedInputStream.readStringRequireUtf8()Ljava/lang/String

 

第一層:

--> calass類名寫錯了

解決方案:

修改一下submit submit腳本的類名

 

第二層:

--> 對應包未打入Jar包

解決方案:

檢查mvn package打的包裏有沒有這個依賴或者項目,這裏推薦JD-GUI,可以查看jar包中包含了哪些項目的class,如果沒有打入包裏,

可以查看pom文件是否加入對應依賴或者對應依賴被標記爲provided而運行環境未提供該jar包

JD-GUI下載地址:http://java-decompiler.github.io/

 

第三層:

--> 如果排除前兩種情況,恭喜進入第三層,jar包衝突,這是我的報錯信息:

java.lang.NoSuchMethodError:com.google.protobuf.CodedInputStream.readStringRequireUtf8()Ljava/lang/String

具體的報錯信息:

 

1.確定原始衝突jar包:

這裏通過具體報錯信息可以看到是ConfigProto類的com.google.protobuf接口出了問題,所以原始衝突jar包就是包含Configproto的maven

依賴,這裏是org.tensorflow。如果對屬於哪個依賴不清楚,就到項目裏找import函數,看Configproto的前綴是那個依賴。

2.通過Maven依賴樹尋找其他包含com.google.protobuf包的項目

mvn -Dverbose dependency:tree

在命令行輸入命令可以看到maven依賴樹:

可以看到搜索出來多個com.google.protobuf,報錯的protobuf版本是3.x版本,可以看到搜到的很多項目中依賴爲2.5.0版本,所以引發了

jar包的衝突依賴。ok,現在已經鎖定了出問題的jar包就在右側紅線標亮的這些jar中,版本衝突就是3.x和2.x。接下來需要的就是逐一解

決。

3.解決衝突的依賴包

A.通過exclude即可解決的衝突

第一個衝突的地方是hadoop-client,這裏hadoop環境配置的protobuf版本爲2.5.0,可以增加exclude改爲如下配置:

        <dependency>
            <groupId>org.apache.hadoop</groupId>
            <artifactId>hadoop-client</artifactId>
            <version>2.6.0</version>
            <scope>provided</scope>
            <exclusions>
                <exclusion>
                    <groupId>com.google.protobuf</groupId>
                    <artifactId>protobuf-java</artifactId>
                </exclusion>
            </exclusions>
        </dependency>

B.通過shaded才能解決的衝突

第二個衝突的地方是hbase-client,這裏protobuf環境同樣爲2.5.0

使用上面同樣的exclude方法可以打包,但是運行時會導致hbase報錯,因此這裏還有另一種解決方法:

這裏shaded考慮使用別名,類似於maven-shaded-plugin中的重命名的relocation方法一樣,問題解決

        <dependency>
            <groupId>org.apache.hbase</groupId>
            <artifactId>hbase-shaded-client</artifactId>
            <version>1.2.6</version>
        </dependency>

C.通過maven-shade-plugin才能解決的衝突

上述兩種都無法解決就需要請maven插件來實現包的別名,不過在我上述場景下,這個方法無效,所以也不展開了。有興趣的小夥伴搜一

下這個打包插件的使用,使用relocation就能給自己項目的包起別名。

                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-shade-plugin</artifactId>

 

Tips:

遇到問題不要慌,jar包衝突其實也沒什麼,鎖定原始jar包,尋找重名類jar包,替換或排除,一會就搞定了。大不了採用暴力破解法,遍

歷自己的依賴,一個一個固定變量排除法,總會解決的~

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章