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
   152   153   154   155   156   157   158   159   160   161   162