对存在依赖的Java文件并行运行多个javac实例是否安全?
多javac实例并行编译存在的风险说明
这两种风险都是真实存在的,具体场景如下:
输出文件互相覆盖的风险
- 只要多个
javac实例配置了相同的输出目录,且存在两个实例编译生成的.class文件全限定名(包名+类名)完全一致,后完成写入的实例就会直接覆盖已有文件,默认不会抛出任何告警。哪怕源文件不同,只要最终生成类的全限定名重复就会触发该问题。 - 即使源文件对应的类名全局唯一,如果项目中用到了注解处理器,多个
javac实例同时触发同一注解逻辑生成同名辅助类时,也会出现写覆盖冲突。
因文件系统状态预期错误导致的编译异常风险
javac编译过程中会主动读取类路径下的.class文件做依赖校验,多个实例并行编译互相依赖的类时,极大概率出现依赖类的.class文件未生成、未完全写入的情况,直接触发类不存在、类格式错误这类编译失败报错。- 即使刚好撞上依赖文件都已写完的时序,也可能出现竞态问题:比如A实例刚读取完旧版本的X.class,另一边编译X类的实例刚好写完新版本的X.class,A后续流程用旧的元数据完成编译,最终生成的字节码会隐含运行时才会暴露的依赖错误,排查成本极高。
- 部分文件系统对多进程同时写同一目录的元数据有锁限制,并发量大的情况下也可能直接触发
javac写文件失败的异常。
注意:不要手动启动多个独立
javac实例做并行编译,官方已经提供了内置的并行编译能力,直接给javac加--parallel参数即可,或者用Maven、Gradle这类标准化构建工具的并行编译功能,它们会内部处理依赖顺序和文件冲突问题,规避上述风险。
内容的提问来源于stack exchange,提问作者merlin2011
相关产品推荐
相关产品推荐

