最近,我观察到(至少对我来说)Java编译器"ToolProvider.getSystemJavaCompiler()"的一个奇怪行为.

  • 如果我试图在一个"裸"maven项目中编译一个不可编译的java文件,我可以获得预期的错误.

  • 如果我添加了某些依赖项(我在添加log4j时第一次观察到这一点),编译器将不再提供有关编译器错误的任何信息.

为了演示这种行为,我创建了一个示例存储库:https://github.com/dfuchss/JavaCompilerIsStrange

在这个存储库中,我添加了一个简单的main方法,试图解析无效Java文件的AST.如果diagnostics对象不包含错误,main方法将引发异常.此主方法将由单个测试调用.

如果运行脚本,则测试成功(因为检测到无效语法),测试失败(因为添加依赖项后未检测到无效语法)

## Build without activated profile
[INFO] Scanning for projects...
[....]
[INFO] -------------------------------------------------------
[INFO]  T E S T S
[INFO] -------------------------------------------------------
[INFO] Running SimpleExecTest
src/main/resources/Example.java:4: error: ';' expected
                System.out.println("Hello World!")
                                                  ^
[INFO] Tests run: 1, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 0.19 s - in SimpleExecTest
[INFO] 
[INFO] Results:
[INFO]
[INFO] Tests run: 1, Failures: 0, Errors: 0, Skipped: 0
[INFO]
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time:  6.832 s
[INFO] Finished at: 2022-06-24T00:57:46+02:00
[INFO] ------------------------------------------------------------------------

## Build with activated profile
[INFO] Scanning for projects...
[....]
[INFO] -------------------------------------------------------
[INFO]  T E S T S
[INFO] -------------------------------------------------------
[INFO] Running SimpleExecTest
[ERROR] Tests run: 1, Failures: 0, Errors: 1, Skipped: 0, Time elapsed: 0.203 s <<< FAILURE! - in SimpleExecTest
[ERROR] SimpleExecTest.testMain  Time elapsed: 0.171 s  <<< ERROR!
java.lang.Error: Shall not be possible to compile.
        at org.fuchss.Main.main(Main.java:46)
        at SimpleExecTest.testMain(SimpleExecTest.java:7)
[....]
[INFO]
[INFO] Results:
[INFO]
[ERROR] Errors: 
[ERROR]   SimpleExecTest.testMain:7 »  Shall not be possible to compile.
[INFO]
[ERROR] Tests run: 1, Failures: 0, Errors: 1, Skipped: 0
[INFO]
[INFO] ------------------------------------------------------------------------
[INFO] BUILD FAILURE
[INFO] ------------------------------------------------------------------------
[INFO] Total time:  6.323 s
[INFO] Finished at: 2022-06-24T00:57:54+02:00
[INFO] ------------------------------------------------------------------------
[....]

有人知道如何解决这种行为吗?

EDIT:

[INFO] --- maven-dependency-plugin:2.8:tree (default-cli) @ strange ---
[INFO] org.fuchss:strange:jar:1.0-SNAPSHOT
[INFO] +- org.junit.jupiter:junit-jupiter-engine:jar:5.8.2:test
[INFO] |  +- org.junit.platform:junit-platform-engine:jar:1.8.2:test
[INFO] |  |  +- org.opentest4j:opentest4j:jar:1.2.0:test
[INFO] |  |  \- org.junit.platform:junit-platform-commons:jar:1.8.2:test
[INFO] |  +- org.junit.jupiter:junit-jupiter-api:jar:5.8.2:test
[INFO] |  \- org.apiguardian:apiguardian-api:jar:1.1.2:test
[INFO] \- org.kohsuke.metainf-services:metainf-services:jar:1.9:compile

编辑II:我已将输出mvn-X clean verify with activated profile添加到https://github.com/dfuchss/JavaCompilerIsStrange/blob/main/result.txt

推荐答案

您可以通过禁用注释处理来"修复"此问题:

final JavaCompiler.CompilationTask task = javac.getTask(
     null, fileManager, listener, List.of("-proc:none"), null, javaFiles
);

在我看来,这似乎是JDK中的一个bug:当要进行注释处理时(这似乎不需要使用显式的注释处理器,因此这个问题会出现在依赖项(如log4j)中),错误报告会被包装在DeferredDiagnosticHandler中.我认为这样做的目的是,在处理完成后,将调用reportDeferredDiagnostics(),这将把诊断传输到原始处理程序,但由于某种原因,这不会发生.

多花点时间使用调试器可以正确地回答这个问题.

Java相关问答推荐

在for—each循环中的AnimationTimer中的if语句'

滚动视图&不能在alert 对话框中工作(&Q;&Q;)

如何获得执行人?

如何在Java中从XML中获取特定的 node ,然后将其删除?

第二次按下按钮后,我需要将按钮恢复到其原始状态,以便它可以再次工作

二进制数据的未知编码/序列化

错误:不兼容的类型:Double不能转换为Float

如何使用MapStrCut转换双向链接

在Eclipse中可以使用外部字体吗?

我该如何为我的类编写getter和setter方法?

如何通过用户ID向用户发送私信

如何使用Rascal Evaluator从编译的JAR访问Rascal函数?

无泄漏函数的Java DRY

转换为JSON字符串时,日期按天递减-Java

using case default on switch语句返回;预览特征切换中的模式匹配仅在源级别20及以上的情况下可用;

java.util.LinkedList()是如何成为MutableList的实例的?

ArrayAdapter 中何时使用构造函数一和构造函数二?

setMaxTotal实际上是做什么的? (MySQL与Java和Apache BasicDataSource连接池)

jpackage 之后如何使图像、属性和其他资源可供我的模块化应用程序使用?

如何将表示特殊字符的字符串转换为其字符表示形式