Page 162 - 《软件学报》2025年第7期
P. 162
孙伟杰 等: Java 依赖异味的实证研究与统一检测技术 3083
初始化未使用依赖库集合 JS (第 1 行). 接着, 创建一个集合 directDeps 用于存储直接依赖库 (第 2 行). 然后, 算法
遍历依赖树 DT 中深度为 1 的依赖库 dep (第 3 行). 对于每一个直接依赖库 dep, 算法检查该依赖库是否不在调用图 CG
的调用依赖集合 CG.calledDeps 中 (第 4 行). 如果该依赖库未被调用, 则将其添加到直接依赖库集合 directDeps
中 (第 5 行). 最后, 算法结束对依赖树的遍历 (第 7 行), 并完成未使用依赖的检测.
6) 类别 1.7 依赖范围冲突 (如算法 A6 所示)
算法 A6. 依赖范围冲突检测.
输入: DT: 依赖树;
输出: JS: 出现冲突依赖范围误用的直接依赖集合.
1. JS ⇐ {}
2. depToScopeMap ⇐ {}
3. for dep ∈ DT and dep.depth = 1 do
4. depToScopeMap[dep] = dep.scope
5. end for
6. for dep ∈ DT and dep.depth ≠ 1 do
7. if dep ∈ depToScopeMap.keys and dep.scope ≠ depToScopeMap[dep] then
8. JS.add(dep)
9. end if
10. end for
该算法接受依赖树 DT 作为输入, 并输出出现冲突依赖范围误用的直接依赖集合 JS. 算法的工作流程如下:
首先, 初始化冲突依赖集合 JS (第 1 行). 接着, 创建一个哈希表 depToScopeMap 用于存储直接依赖库及其对应的
依赖范围 (第 2 行). 然后, 算法遍历依赖树 DT 中深度为 1 的依赖库 dep (第 3 行), 并将每个直接依赖库的依赖范
围 dep.scope 添加到哈希表 depToScopeMap 中 (第 4 行). 完成直接依赖库的遍历后, 算法继续遍历依赖树中深度不
等于 1 的依赖库 dep (第 5 行). 对于每一个依赖库, 算法检查该依赖库是否在哈希表 depToScopeMap 的键中, 且其
依赖范围 dep.scope 是否与哈希表中记录的依赖范围不一致 (第 6 行). 如果存在不一致, 算法将该依赖库添加到冲
突依赖集合 JS 中 (第 7 行). 最后, 算法结束对依赖树的遍历 (第 9 行), 并完成依赖范围冲突的检测.
7) 类别 1.8 依赖树冲突 (如算法 A7 所示)
算法 A7. 依赖树冲突检测.
输入: DT: 依赖树; BI: 基本信息;
输出: JS: Maven 和 Gradle 下出现不一致的直接依赖库.
1. currentToolMap ⇐ {}
2. otherToolMap ⇐ resolveDepFile(BI.otherToolDepFile)
3. for dep ∈ DT and dep.depth = 1 do
4. currentToolMap[dep.depName] = dep.depVer
5. end for
6. JS ⇐ difference(currentToolMap, otherToolMap)
该算法接受依赖树 DT 和基本信息 BI 作为输入, 并输出 Maven 和 Gradle 下出现不一致的直接依赖库集合
JS. 算法的工作流程如下: 首先, 初始化一个哈希表 currentToolMap 用于存储当前工具 (如 Maven 或 Gradle) 的直

