Page 157 - 《软件学报》2025年第7期
P. 157
3078 软件学报 2025 年第 36 卷第 7 期
置文件中则为 1.0.0. 由于 mod 在源码中调用了仅存在于 1.0.0 版本中的方法 methodV1, 试图 A 使用 Maven 进行
构建时无法找到对应方法, 因此出现构建错误.
import lib.Dup
(a) 危害 1
Dup classDup= new Dup (); 构建错误
包含 classDup.methodV1 ();
lib.Dup
Maven 中配置 包含类 public class Dup {
依赖于 void methodV2 ();
}
依赖库 lib: v2.0.0
lib.Dup
模块 mod 依赖库 lib Gradle 中配置 包含类 public class Dup{
void methodV1 ();
}
依赖库 lib: v1.0.0
(b) 危害 3 Class c=Class.forName (“lib.DupV1”);
包含
Maven 中配置 包含类 lib.DupV1 运行时错误
依赖于
依赖库 lib: v2.0.0
lib.DupV1
模块 mod 依赖库 lib Gradle 中配置 包含类 public class DupV1 {
void methodV1 ();
}
依赖库 lib: v1.0.0
(c) 危害 4 import lib.Dup
Dup classDup=new Dup ();
lib.Dup
包含 System.out.println (classDup.methodDup ()); 包含类 public class Dup { 运行时语义冲突
Maven 中配置 String methodDup (){
return “Lib1”
依赖于 }
依赖库 lib: v2.0.0 }
包含类 lib.Dup
模块 mod 依赖库 lib Gradle 中配置
public class Dup {
String methodDup (){
return “Lib2”
依赖库 lib: v1.0.0
}
}
(d) 危害 11
<dependency>
依赖于 Maven 中配置 <groupId>example</groupId>
<artifactId>lib</artifactId> 维护成本增加
<version>1.0.0</version>
模块 mod
</dependency>
冲突
依赖库 lib Gradle 中配置
implementation “example: lib: 2.0.0”
图 A11 异味 1.8 可能危害与对应触发场景
(2) 运行时错误: 其触发场景为模块运行时调用了某冲突依赖库中独有的特性. 以图 A11(c) 为例, 与上例类似,
mod 在 Maven 中依赖于 lib:1.0.0 而在 Gradle 中依赖于 lib:2.0.0. 此时 mod 以反射形式获取仅存在于 1.0.0 版本中
的类 lib.DupV1, 能正常通过构建, 但在运行 Maven 对应构建产物时, 会因找不到 lib.DupV1 而出现运行时错误.
(3) 运行时语义冲突: 其触发场景为模块运行时调用了冲突依赖库中签名相同但实现不同的方法. 以图 A11(d)
为例, 与上例类似, mod 在 Maven 中依赖于 lib:1.0.0 而在 Gradle 中依赖于 lib:2.0.0. 虽然类 Dup 中的方法
methodDup 在两个版本中都存在, 但其具体实现不同. 当 mod 试图调用 methodDup 时会出现语义冲突, 在运行
Maven 构建产物时的输出为“Lib1”, 而运行 Gradle 构建产物时输出则为“Lib2”.
(4) 依赖库维护难度增加: 这类危害在出现异味时始终存在. 以图 A11(a) 为例, 模块 mod 同时维护了 Maven
和 Gradle 对应的配置文件, 但依赖库 lib 在 Maven 配置文件中的版本为 1.0.0, 而在 Gradle 配置文件中为 2.0.0. 开
发者在进行版本升级时需要同步更新至所有构建工具对应的配置文件, 导致维护难度增加.
9) 类别 2.1 构建工具配置缺失
构建工具配置缺失可能导致无法获取预期版本的构建工具, 进而导致构建错误.
(1) 构建错误: 其触发场景为项目实际使用的构建工具版本与预期不一致, 且使用了仅存在于预期版本中的
特性. 以图 A12(a) 为例, 项目预期使用 Gradle 4.1 版本及其中新引入的 java-library 特性, 但实际上未对 Gradle 版
本进行配置, 导致实际使用的是本地的 Gradle 3.1 版本. 因此, 无法识别 java-library 特性, 导致构建错误.
10) 类别 2.2 构建工具启动器 JAR 缺失
构建工具启动器 JAR 缺失与异味 2.1 类似, 同样可能导致无法获取预期版本的构建工具, 进而导致构建错误.
(1) 构建错误: 其触发场景为项目使用构建工具启动器运行构建工具. 以图 A13(a) 为例, 项目预期使用 Gradle 4.1

