You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

Guava版本不兼容引发Maven依赖冲突的解决方案咨询

解决Guava版本冲突的Maven依赖问题

这种跨组件的依赖版本僵局确实头疼,尤其是像Guava这种API变化较大的核心库。结合你的POM配置,我给你几个递进的解决方案,你可以根据实际测试情况选择:

第一步:先明确冲突来源

首先执行Maven命令精准定位所有引入Guava的依赖链,搞清楚每个组件到底依赖哪个版本:

mvn dependency:tree -Dverbose -Dincludes=com.google.guava:guava

这个命令会列出所有涉及Guava的依赖路径,你能清楚看到grpc、spark各自依赖的版本,以及当前Maven仲裁后实际生效的版本,方便后续针对性调整。

方案一:强制统一Guava版本(最简单优先尝试)

Maven的dependencyManagement可以强制项目中所有依赖使用指定版本的Guava,优先尝试找到一个能兼容grpc和spark的中间版本:

  1. 先移除你POM中显式引入的Guava 23.0(这个版本和另外两个版本差异太大,会加剧冲突)
  2. 在POM的<project>节点下添加dependencyManagement块,强制统一版本:
<dependencyManagement>
    <dependencies>
        <!-- 先尝试grpc依赖的19.0版本,测试spark是否兼容 -->
        <dependency>
            <groupId>com.google.guava</groupId>
            <artifactId>guava</artifactId>
            <version>19.0</version>
        </dependency>
    </dependencies>
</dependencyManagement>
  1. 执行mvn clean compile test测试项目是否能正常编译运行。如果spark的hadoop组件在Guava 19.0下没有报错,那这个方案就完美解决问题了。

如果19.0版本不兼容spark,你可以尝试中间版本(比如18.0、20.0),看哪个版本能同时满足两边的API需求。

方案二:使用Shade插件重命名冲突依赖(终极解决办法)

如果找不到能兼容两边的Guava版本,那就用Maven Shade插件把其中一方的Guava包重命名,实现完全隔离。比如把grpc依赖的Guava重命名为独立的包名,避免和spark的Guava冲突:

在POM的<build>节点下添加Shade插件配置:

<build>
    <plugins>
        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-shade-plugin</artifactId>
            <version>3.2.4</version>
            <executions>
                <execution>
                    <phase>package</phase>
                    <goals>
                        <goal>shade</goal>
                    </goals>
                    <configuration>
                        <!-- 重命名Guava的包路径 -->
                        <relocations>
                            <relocation>
                                <pattern>com.google.common</pattern>
                                <shadedPattern>shaded.com.google.common</shadedPattern>
                            </relocation>
                            <relocation>
                                <pattern>com.google.thirdparty</pattern>
                                <shadedPattern>shaded.com.google.thirdparty</shadedPattern>
                            </relocation>
                        </relocations>
                        <!-- 只对grpc相关的Guava依赖进行重命名 -->
                        <filters>
                            <filter>
                                <artifact>io.grpc:*</artifact>
                                <includes>
                                    <include>com/google/**</include>
                                </includes>
                            </filter>
                            <filter>
                                <artifact>com.google.guava:guava</artifact>
                                <includes>
                                    <include>com/google/**</include>
                                </includes>
                            </filter>
                        </filters>
                    </configuration>
                </execution>
            </executions>
        </plugin>
    </plugins>
</build>

执行mvn clean package打包后,你的jar包中会同时存在两个版本的Guava:一个是spark使用的原始路径com.google.common,另一个是grpc使用的重命名路径shaded.com.google.common,两者完全隔离,不会再出现API冲突。

方案三:升级/降级组件缩小版本差异

如果上面的方案都有问题,你可以考虑调整组件版本:

  • 升级Spark版本:Spark 2.2.1比较老,升级到2.4.x版本(比如2.4.8),它依赖的Guava版本会更高(20.0左右),和grpc的19.0版本差异很小,冲突概率会大大降低。
  • 调整grpc版本:找一个依赖Guava版本和Spark依赖版本更接近的grpc版本,比如grpc 1.5.x系列依赖Guava 18.0,和Spark的Guava 11.0.2差异比19.0小一些(不过这个可能不太现实,因为grpc旧版本可能存在其他稳定性问题)。

内容的提问来源于stack exchange,提问作者Nagireddy Hanisha

火山引擎 最新活动