Page 150 - 《软件学报》2025年第7期
P. 150

孙伟杰 等: Java 依赖异味的实证研究与统一检测技术                                                    3071



                                 (a) 危害 1        import mod.Dup
                                          执行     Dup classDup=new Dup ();
                                                 classDup.methodLib ();     构建错误
                                             依赖于
                                       模块 mod        依赖库 lib
                                          包含类          包含类
                                         mod.Dup        mod.Dup
                                     public class Dup{  public class Dup{
                                      void methodHost ();  void methodLib ();
                                     }              }
                                 (b) 危害 3       import mod.RunDup
                                                RunDup runner = new RunDup();
                                         执行
                                                runner.runMtdLib();       运行时错误
                                            依赖于          包含类              lib.RunDup
                                                                   import mod.Dup;
                                                                   public class RunDup{
                                      模块 mod        依赖库 lib          public void runMtdLib (){
                                          包含类         包含类              Dup classDup=new Dup ();
                                        mod.Dup        mod.Dup         classDup.methodLib ();
                                    public class Dup{  public class Dup{  }
                                     void methodHost ();  void methodLib ();  }
                                    }              }
                                 (c) 危害 4        import mod.Dup
                                                 Dup classDup=new Dup();
                                           执行
                                                 System.out.println (classDup.methodDup ());
                                              依赖于
                                                                       运行时语义冲突
                                        模块 mod       依赖库 lib
                                           包含类          包含类
                                        mod.Dup            mod.Dup
                                  public class Dup{  public class Dup{
                                    String methodDup (){  String methodDup (){
                                      return “mod”       return “Lib”
                                   }                  }
                                  }                  }
                                            图 A3 异味   1.1  可能危害与对应触发场景

                    (1) 构建错误: 其触发场景为模块源码中调用了仅存在于被遮蔽的同名冲突类中的方法. 以图                            A4(a) 为例, 模
                 块  mod  的依赖库  lib1  和  lib2  中存在冲突类  Dup, mod  试图调用仅存在于  lib2  中的方法  methodLib2, 但由于  lib1  在
                 依赖树中与    mod  距离更近, 最终   lib2  中的类  Dup  被忽略, 导致构建错误.
                    (2) 运行时错误: 其触发场景为项目运行时调用了仅存在于被遮蔽的同名冲突类中的方法. 以图                             A4(b) 为例,
                 模块  mod  的依赖库  lib1  和  lib2  中存在冲突类  Dup, mod  试图调用  lib2  中的方法  runMtdLib, 其间接调用了  Dup  中
                 的方法   methodLib2. 由于并未直接调用     methodLib2, 模块可以正常进行构建. 但在运行时, JVM         会忽略   lib2  中的
                 类  Dup, 因此在运行时则无法找到       lib  对应方法, 导致运行时错误.
                    (3) 运行时语义冲突: 其触发场景为模块运行时调用了冲突类中签名相同但实现不同的方法. 以图                             A4(c) 为例,
                 模块  mod  的依赖库   lib1  和  lib2  中存在冲突类  Dup  和同签名方法  methodLib, 但其具体实现不同. 当      mod  调用
                 methodLib  时就会出现语义冲突, 预期调用的是         lib2  中的  Dup  类, 对应的  methodDup  返回“lib2”, 而实际调用的是
                 lib1  中的  Dup  类, 对应的  methodDup  返回“lib1”.
                    3) 类别  1.3  库版本冲突
                    库版本冲突可能引发一系列严重的后果, 包括但不限于模块构建错误、运行时错误以及运行时语义冲突. 以
                 下将详细阐述这些危害的具体触发场景.
                    (1) 构建错误: 其触发场景为模块源码中调用了仅存在于被遮蔽的库中的特性                         (例如方法). 以图   A5(a) 为例,
                 模块  mod  的依赖树中同时存在      lib1  的  1.0.0  和  2.0.0  版本. 根据  Maven  和  Gradle 的版本冲突解决机制, 最终  1.0.0
   145   146   147   148   149   150   151   152   153   154   155