1. 程式人生 > >uber jar,shade jar和包衝突

uber jar,shade jar和包衝突

我們日常遇到的包衝突主要是依賴jar的版本衝突。在包都向下相容的前提下,這類問題比較容易解決,exclusion對低版本的依賴即可。但也有不相容導致多個依賴無法兼顧的情況,如何解決,下文再說。

考慮另一種情況,完全不同的jar實現了同名類,而且包名也一模一樣。此時對java類載入器而言,和上一類問題是同質的。基於JVM的有則執行,無則載入的類處理原則,實際上生效的也將是載入順序在前的類。

這種情況在uber jar中出現機會較多。uber jar簡單地說就是使用maven-shade-plugin直接打入了依賴類的jar,減少了對外部jar lib的依賴。舉個例子,hive-exec-2.0.0就是個典型的uber jar。我們看一下他的pom檔案和類檔案就明白了。

<artifactSet>
<includes>
……
<include>com.google.protobuf:protobuf-java</include>
……
</includes>
</artifactSet>

include的項可以是直接的也可以是間接的,實際include的版本號可以從pom下的dependency中找到。 在hive-exec-2.0.0的jar下能看到com.google.protobuf包以及該包名下的所有class檔案。

從外部來看,相當於hive-exec用一樣的包名類名自己實現了谷歌上面這一堆類,而且不是外部依賴,所以無法用exclusion排除。於是問題來了,當專案原來依賴了和hive-exec中的protobuf版本不相容的protobuf,衝突就不可避免。

那麼,怎麼解決這個問題呢?解鈴還須繫鈴人,maven-shade-plugin除了構建uber jar之外,還能構建shade jar。shade jar有一個好,就是能按開發者的意圖把jar封裝一層,從而java的類載入器就能把這些類區分開,同時載入進去。對原有com.google.protobuf的處理如pom檔案所示。

<relocations>
<relocation>                            
<pattern>com.google.protobuf</pattern>                           
<shadedPattern>xxx.com.google.protobuf</shadedPattern>
</relocation>
</relocations>


在專案程式碼中,除hive外原有的對com.google.protobuf的依賴變更為對xxx.com.google.protobuf的依賴即可。同時,hive-exec中用的依然是他自有的com.google.protobuf,如此則兩全其美。上文中第一類不相容也可以用這個方法解決。