传递依赖的冲突应该怎么做才是最好

2022-01-16 18:22:09 +08:00
 golangLover

最近在管理 gradle / maven 写的源码,想问下平时是不需要做这个传递依赖的冲突检查吗,等抛出异常的时候才做还是每次安装依赖的时候都要做一次?

最怕的问题在于不知道为什么编译期的版本冲突没有检查出来。而我们已经依赖了好多个 library,例如库 A 依赖 库 C 和库 D 的 1.0 ,但是库 B 是依赖库 C 和 D 的 2.0 。

我在网上看了 maven 和 gradle 会自动帮我以某种最短路径策略去选择依赖库。但是这种选择我也不懂是不是能够保证选择出来的版本就是没问题的,总不能每次都重新测试整个 app 吧。

而这种传递依赖的层级可能有 3/4 层。而我恰好前两天就遇到一个 java.lang.IncompatibleClassChangeError 。查了一下好像是关于依赖不兼容的问题, 编译期间没有检查出来,还是使用哪个 method 的时候才出现的 runtime exception 。

问题是我在最上层 dependency management 例如写了是 2.0 ,那我也不能保证依赖 1.0 的一定没问题的。但写成 2.0 的,那风险也同样大。

所以想向大家求教应该怎么做依赖的管理的最好方法。谢谢大家

2692 次点击
所在节点    Java
9 条回复
lzrainchen
2022-01-16 18:41:53 +08:00
我也遇到了一样的问题,我参考了这篇文章解决了我的问题 aHR0cHM6Ly93d3cucGxheXBpLm9yZy8yMDE5MTIwMTAxLmh0bWw=( Base64 )希望对你有帮助
paxnil
2022-01-16 18:51:53 +08:00
项目里引入依赖,至少要了解加进来的是个什么东西,跟现有的依赖有没有冲突,这个工作应该放在前面。
不同版本是一个问题,需要什么版本就在 pom 里把它排在前面。如果你的 A 在 C/D 2.0 下不正常,考虑一下 A 是不是过时了。
还有就是同样的东西却有不同名称,比如 Bouncy Castle 有针对不同 JDK 版本的包,那就得排除不需要的。
golangLover
2022-01-16 22:05:00 +08:00
好的, 谢谢两位 @lzrainchen @paxnil
intmax2147483647
2022-01-16 22:58:35 +08:00
其实完善的单元测试可以屏蔽掉很多编程中的烦恼。
ClarkAbe
2022-01-16 23:14:51 +08:00
看你名字还以为是 golang 问题
kassadin
2022-01-17 01:36:12 +08:00
Gradle 自动解决的方案就是所有依赖里的最高版本,最外层定义版本是覆盖了最高版本策略
编译能检测出重复类、不兼容类,一般是 fat jar ,大版本依赖冲突
没检测出来的一般是反射、序列化、业务逻辑变化

一般都遵循 semver ,小版本就随意了,谁也没时间挨个看,大版本还是要搂一眼兼容性变化的

额外可以做的就是打印 dep tree ,日常过滤明显问题,如依赖 alpha 、beta 、过老的版本等,以及你遇到的跨大版本问题

理想状态就是隐式传递依赖里的版本就是最终版本,而不是自动解决依赖冲突后抬上来的版本
XieGP
2022-01-17 09:36:59 +08:00
我一个 golanglover 出门问个 java 很合理吧
hingbong
2022-01-17 09:53:47 +08:00
IncompatibleClassChangeError 这个异常出现过
我这边是通过 gradle 依赖两个本地的模块, 然后有两个全路径一样, 里面方法签名一样的类, 但是一个是具体类一个是接口, 编译器编译的顺序和类加载器的顺序不一样吧, 编译器和运行时的行为就不一样了
golangLover
2022-01-17 22:11:08 +08:00
@kassadin @hingbong 谢谢赐教

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/828587

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX