执行Maven构建时,提示找不到package/symbol
问题现象
执行Maven构建任务时,日志报异常信息提示找不到package或symbol,例如:
com/xxx/xxx/configserver/encryptor/xxx.java:[11,40] package com.sun.jersey.api.client.config does not exist
原因分析
分析日志可知,项目中引用了“com.sun.jersey.api.client.config”包下面的内容,但构建时无法从项目中以及所有解析出的依赖包中找到此包导致。导致此结果的原因一般有两大类:
- 代码问题:代码中包引用不正确,此类问题较易排查,如有遇到可优先排查代码。
- 环境/组件问题:依赖包损坏或不一致,此类问题常表现为本地可编译而云端构建失败;此章节主要为此类问题提供一些可能的解决方案。其中可能的环境/组件问题有:
依赖包冲突
部分场景下,因为操作失误或一些第三方依赖被动引入,项目中可能同时存在同一依赖的多个版本。同时引入不同版本可能会导致实际使用的版本与预期不符,进而导致找不到指定的包。处理此类问题操作步骤:
- 确认使用的依赖包版本,有两种方式可参考。
- 参考Maven定义的两个依赖调解原则:
- 第一原则:路径最近者优先, 如:A->B->C->X(1.0)、A->D->X(2.0),则最终引用X版本为2.0。
- 第二原则:第一声明者优先, 两个引入路径长度相同时,先引入的版本为最终版本。
2. 使用dependency插件,在构建任务执行mvn dependency:tree查看。
- 参考Maven定义的两个依赖调解原则:
- 如果确定构建使用的依赖与预期不符,导致构建失败,在pom最外层引入需要的依赖并重试:
<dependencies> <dependency> <groupId></groupId> <artifactId></artifactId> <version></version> </dependency> </dependencies>
依赖范围错误
使用Maven管理依赖时,Maven坐标中scope属性定义了依赖的有效范围。错误地指定依赖范围会导致该依赖在compile时无效,如果此时在项目主代码中使用了此依赖中的包,则会导致编译错误。处理步骤:
- 使用mvn dependency:tree查看项目使用的依赖及依赖范围。
- 对比依赖范围以及项目中使用依赖的位置。
若在主代码中使用了依赖中的包,且要求依赖在编译时有效,则依赖的范围需要为以下之一:
- compile
- provided
- system:系统依赖范围必须通过systemPath指定依赖文件位置,且依赖文件必须存在于指定目录。
使用GAV模式上传依赖包
- 在私有依赖仓库上传自研依赖包A时,如果选择GAV模式,只需要上传jar文件,系统会自动生成对应的pom文件;但是,此pom文件中只包含此依赖本身的坐标定义,原来的<dependencies>节点则会全部丢失。
- 假设当前构建项目D,使用了项目A构建的依赖A,依赖A引入了第三方依赖B(D > A > B),此时,在构建D项目时,因为以上原因,Maven解析依赖A时,无法识别引入的依赖B,最终导致项目D中找不到依赖B的内容,遇到此场景时,可尝试按以下步骤排查:
- 查看项目D的依赖树,确定缺失的内容是否由项目A的pom文件引入,如果是则进入下一步,否则请尝试其他解决方案。
- 从私有依赖仓库下载依赖A的pom文件,与项目A中pom对比,如果线上pom缺失了B依赖的引入,进入下一步,否则请尝试其他解决方案。
- 更新依赖A的版本号并重新上传,此处提供两种解决方案:
- 使用编译构建服务构建项目A,使用deploy命令将依赖A上传到Maven私有仓库(推荐:可集成于流水线中实现自动化)。
- 在Maven私有仓库重新上传依赖A,此时选择POM模式,分别上传jar文件和pom文件。
- 更新完成后,尝试重新构建项目D。
依赖包损坏
依赖包损坏可能会导致依赖包中某些文件缺失,此时构建可以找到相应依赖包,但无法找到其中的class文件或者package,导致此类问题。此场景下可按包类型分不同方式处理:
- 第三方依赖包:直接联系技术支持处理。
- 自研(手动上传到Maven私有仓库)的依赖包,按如下步骤排查:
- 从Maven私有依赖仓库下载依赖包。
- 解压缩并查看依赖包内容是否正常。
- 若依赖包内容异常,再分两种情况排查:
- 如果是第三方提供的包手动上传到maven私有依赖仓库,确认包文件无误并尝试重新上传(注意同时上传pom与jar文件)。
- 如果是自己构建(本地/云端构建)的依赖包,且已确认代码无误,则检查是否是多任务同时构建导致构建生成jar包内容缺失。