Eclipse两个Dynamic Web项目引用机制及调试错位问题排查
问题背景
Eclipse环境下project-A需要调用project-B的功能,project-A的pom.xml中已配置如下compile范围依赖:
<dependency> <groupId>someId</groupId> <artifactId>projectB</artifactId> <version>1.0.0-SNAPSHOT</version> <type>jar</type> <scope>compile</scope> </dependency>
该依赖的groupId、artifactId与project-B的pom.xml中配置完全匹配,但调试时单步进入project-B的函数会出现固定30行左右的偏移:调试器停留显示在90行时,实际执行的是60行位置的代码。project-A的WEB-INF/lib目录下存放有project-B的jar包,但调试时不会加载该目录下的jar代码。
已尝试操作:
- 删除本地Maven依赖目录下的project-B.jar,执行项目清理、更新、重新构建
- 删除WEB-INF/lib目录下的project-B相关jar包,执行项目清理、更新、重新构建,问题未解决
Eclipse Dynamic Web项目Maven依赖的引用逻辑
Eclipse搭配m2e(官方Maven插件)的环境下,依赖加载有明确优先级,从高到低排序:
- 同工作空间内打开的、GAV坐标(groupId+artifactId+version)完全匹配的项目源码编译输出目录(即对应项目下的
target/classes路径) - 本地Maven仓库中存放的对应版本jar包
- 项目自身WEB-INF/lib目录下存放的jar包
你看到调试不加载WEB-INF/lib下的jar是正常现象:m2e默认开启工作空间依赖解析,只要工作空间里开着project-B且坐标匹配,就会直接关联project-B的源码编译产物做调试关联,优先级远高于WEB-INF/lib下的包,后者只有在项目打包发布到容器、或者手动关闭工作空间项目关联的时候才会被加载。
行号偏移的根因
固定行号偏移本质就是调试器关联的字节码版本,和你当前打开的源码版本不匹配。你之前的操作没生效,核心是没清对缓存:
- 删本地Maven仓库的jar没用,因为当前调试场景下优先级最高的是工作空间里project-B的
target/classes下的class文件,这些是旧代码编译出来的,和你现在看到的最新源码行号对不上 - 删WEB-INF/lib下的jar更没用,本来调试的时候就不会加载这个路径下的包,删了不影响实际的依赖关联
- Eclipse自带的Clean功能经常漏删增量编译残留的class缓存,靠它清不干净旧文件。
修复步骤
按顺序操作就能解决:
- 完全关闭Eclipse,直接打开两个项目在本地磁盘的存储目录,手动把project-A和project-B根目录下的整个
target文件夹删掉,不要依赖Eclipse自带的清理功能 - 重新打开Eclipse,先右键project-B,选择
Run As -> Maven install,等控制台输出BUILD SUCCESS,确认最新代码被正确编译并安装到本地Maven仓库 - 右键project-A,选择
Maven -> Update Project,勾选Update project configuration from pom.xml、Refresh workspace resources from local filesystem、Clean projects三个选项,点击OK等待更新完成 - 打开project-A的
Properties -> Deployment Assembly配置页,确认Maven Dependencies的发布路径是WEB-INF/lib,且没有手动重复添加project-B的相关jar包 - 重新启动调试服务即可,行号偏移问题会直接消失。
如果操作完还是有偏移,就去检查project-B的pom.xml里maven-compiler-plugin的配置,看有没有写<debug>false</debug>,这个参数设为false的时候,编译出来的class不会带正确的源码行号映射信息,也会导致调试行号错乱,默认配置下这个值是true,一般很少有人主动改。
内容的提问来源于stack exchange,提问作者Aspiring Dev 23000

