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包,替換或排除,一會就搞定了。大不了採用暴力破解法,遍
歷自己的依賴,一個一個固定變量排除法,總會解決的~