曹工雜談:用好verbose,Jar包衝突再也不難

Jar包衝突的相關文章:html

了不起,我可能發現了Jar 包衝突的祕密java

1、前言

jar包衝突分多種,簡單理解來講,就是同package且同名的類在多個jar包內出現,若是兩個jar包在同一個classloader下,那麼最終的結果是,只會加載其中的一個。linux

有時,這個錯誤通常在運行時出現,報的錯多是,找不到某方法,或者呢,更隱蔽的,不會報錯,可是邏輯不對。apache

針對運行中的應用,能夠考慮使用阿里出品的arthas來處理。bootstrap

 

我今天呢,只是簡單的找不到方法的狀況,因此不須要用到那個。 我這裏的場景是,在學習rocketMq的過程當中,其依賴的jar包以下:windows

<dependency>
   <groupId>org.apache.rocketmq</groupId>
   <artifactId>rocketmq-client</artifactId>
   <version>4.3.0</version>
</dependency>

該jar包間接依賴以下:jvm

 

上圖是截的idea插件,maven helper。可是一開始並沒想起來去看這裏。maven

 

爲何會衝突呢,由於我把測試類寫在了一個使用了netty 5 版本的工程裏。(爲了偷懶。。)ide

 

2、解決衝突的方式一

我這裏報錯以下:post

1 Exception in thread "main" java.lang.NoSuchMethodError: io.netty.bootstrap.Bootstrap.channel(Ljava/lang/Class;)Lio/netty/bootstrap/AbstractBootstrap; 2     at org.apache.rocketmq.remoting.netty.NettyRemotingClient.start(NettyRemotingClient.java:165) 3     at org.apache.rocketmq.client.impl.MQClientAPIImpl.start(MQClientAPIImpl.java:225) 4     at org.apache.rocketmq.client.impl.factory.MQClientInstance.start(MQClientInstance.java:234) 5     at org.apache.rocketmq.client.impl.producer.DefaultMQProducerImpl.start(DefaultMQProducerImpl.java:171) 6     at org.apache.rocketmq.client.impl.producer.DefaultMQProducerImpl.start(DefaultMQProducerImpl.java:144) 7     at org.apache.rocketmq.client.producer.DefaultMQProducer.start(DefaultMQProducer.java:172) 8     at rocketmq.TestRocketMq$SyncProducer.main(TestRocketMq.java:21)

 

上面意思就是,io/netty/bootstrap/AbstractBootstrap 不存在 channel(Ljava/lang/Class;) 這個方法。

 

我在ide裏,打開了netty 5 jar包裏的這個類,確實沒找到這個方法,估計就是這個緣由了。

怎麼驗證程序加載了這個類呢?直接在啓動參數裏,加入 -verbose:class ,而後從新啓動,過程當中會打印出加載的class:

 

 

上圖能夠看到,果真是從5.0版本的netty里加載的。

 

3、解決jar包衝突的方式2

idea裏安裝maven helper插件,而後選擇pom,下圖便可看出衝突的jar包:

 

可是,說實話,這個通常事先並不會去看,頗有可能都是過後出問題纔去這裏看。

 

4、總結

今天這個場景很簡單,文章開頭那個連接裏的案例要複雜一點(windows上能夠,linux不行)。你們也能夠看下。

jar包爲何衝突?這裏再理解下,由於在jvm裏,一個類是惟一的,說明類加載器相同 + 類的全路徑名相同。

若是同一個類加載器下出現了兩個全路徑相同的類,天然就衝突了。

相關文章
相關標籤/搜索