上周做业务迭代,本地 mvn compile 在 javac 阶段卡了二十多分钟,最后既没报错也没生成 class 文件。那会儿我一度以为是 Maven 本地缓存损坏、JDK 版本不兼容,连重装 IDE 的念头都动过。绕了一大圈才发现,根子是两处藏在业务代码里的类型不匹配,整个排查过程的几个误区,后来证明都很典型。
先别动环境,按代码证据找变更
编译卡住的第一反应往往是怀疑环境:清本地 Maven 缓存、换 JDK、关掉并行编译……我也走了这条弯路,折腾半小时没进展。冷静下来才想通:要是环境问题,其他同事本地编译应该也挂,可只有我这边出问题,那大概率就是代码层面的回归。
顺着最近的改动,定位到一组业务逻辑修改,先把最明显的字段类型不一致修掉,本以为稳了,再跑 mvn compile 还是卡。这时候才意识到:可能还有没输出的隐藏编译错误,尤其类型不匹配、泛型擦除这类,常常不抛明确异常,就闷在编译阶段。
把错误日志逼出来
要让隐藏错误现形,关键不是看最终结果,而是拿到完整编译日志。之前一直开着多模块并行编译,错误输出早被其他模块日志淹了。于是我加了单模块编译、前台输出的参数:
mvn compile -pl 对应模块名 -am -Dmaven.compile.fork=true -DskipTests
不到 5 分钟,两处明确的编译错误就冒出来了,都是类型不匹配:
- 返回值类型不匹配:业务方法
qryStepInfo的返回值定义是Long,但所有调用方都期待String类型的步骤信息,属于回归修改时漏改返回值定义:
// 错误代码:返回值类型与调用方预期不一致
public Long qryStepInfo(String bizId) {
return stepInfoService.getStepInfo(bizId);
}
// 调用方逻辑
String stepInfo = stepService.qryStepInfo(bizId); // 编译报错:类型不匹配
- 泛型方法引用类型擦除冲突:流处理里用了泛型方法的方法引用,类型擦除后编译器匹配不上泛型参数,卡在类型推导:
// 错误代码:泛型方法引用在类型擦除后无法匹配
List<StepDTO> stepList = stepIdList.stream()
.map(this::convertStep) // convertStep是泛型方法<T> StepDTO convertStep(T id)
.collect(Collectors.toList());
// 改成显式Lambda后立刻通过编译
List<StepDTO> stepList = stepIdList.stream()
.map(id -> convertStep(id))
.collect(Collectors.toList());
修完不能只跑 compile
两处改完,mvn compile 顺利通过。但按之前的教训,编译过不等于业务逻辑没问题,更不能直接 claim 修好了。我先跑了一遍模块下的现有单测,确认原有功能没受影响,顺手把单测里同样存在的泛型方法引用问题也修掉,保证 mvn test 也能跑。
为了不让类似重复代码再冒出来,我把业务逻辑里重复的状态更新逻辑抽成一个私有 helper,又补了一个新单测,专门验证 start/complete/updateStepInfo 三个接口的调用逻辑。到这里,我才敢说这次编译阻塞真正解决了。