系统Java编译器的行为不同,具体取决于Maven中定义的依赖项

发布于 2025-02-10 05:59:03 字数 3879 浏览 2 评论 0原文

最近,我观察到了Java编译器“ ToolProvider.getSystemjavacompiler()”(至少对我来说)的奇怪行为。

  • 如果我尝试在“裸” Maven项目中编译不兼容的Java文件,我可以根据预期获得错误。

  • 如果我添加了某些依赖项(在添加log4j时我首先观察到了),则编译器不再提供有关编译器错误的任何信息。

为了证明这种行为,我为此创建了一个示例存储库: https://github.com/github.com/dfuchss/dfuchss/javacompilerstrange

在此存储库中,我添加了一个简单的主方法,该方法试图解析无效的Java文件的AST。如果诊断对象不包含错误,则主要方法会引发异常。该主要方法将通过一次测试调用。 在我的pom.xml中,我创建了一个简单的配置文件“奇怪”,该配置文件仅添加了项目的依赖性(未使用,但显然会在激活配置文件后将其添加到ClassPath中)。对于此示例,这是“ metainf-services”依赖性。 在run.sh文件中,我只是两次执行MVN Test。 首先没有轮廓激活,然后使用激活的轮廓。

如果运行脚本,您将获得成功的测试(因为检测到无效的语法)和失败的测试(因为在添加依赖项后未检测到无效的语法)

## 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] ------------------------------------------------------------------------
[....]

是否有人知道如何解决此行为?

编辑: MVN依赖关系:TREE没有显示“ MetAinf -Services”

[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的进一步依赖关系(编译)II:我已经添加了输出MVN -X CLAIN验证,而无需激活的配置文件和 https://github.com/dfuchss/javacompilerisstrange/javacompilerisstrange/blob/blob/main/main/result.txtxtxtxt

Recently I've observed a (at least for me) strange behavior of the Java Compiler "ToolProvider.getSystemJavaCompiler()".

  • If I try to compile a not-compilable java file in a "bare" maven project, I can obtain the errors as expected.

  • If I add certain dependencies (I've first observed this when adding log4j), the compiler does not provide any information regarding compiler errors anymore.

To demonstrate this behavior, I've created an example repository for this: https://github.com/dfuchss/JavaCompilerIsStrange

In this repository I've added a simple main method that tries to parse the AST of an invalid Java File. The main method throws an exception if the diagnostics object contains no errors. This main method will be invoked by a single test.
In my pom.xml I've created a profile "strange" that simply adds a dependency to the project (that is not used but obviously will be added to the classpath after activating the profile). For this example it's the "metainf-services" dependency.
In the run.sh file, I simply execute mvn test twice.
First without the profile activated and after that with the activated profile.

If you run the script you get a successful test (because the invalid syntax was detected) and an failed test (because the invalid syntax was not detected after adding the dependency)

## 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] ------------------------------------------------------------------------
[....]

Does anyone has an idea how to resolve this behavior?

EDIT:
mvn dependency:tree does not show any further dependency (compile) for "metainf-services"

[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

Edit II: I've added the output mvn -X clean verify without and with activated profile to https://github.com/dfuchss/JavaCompilerIsStrange/blob/main/result.txt

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

花落人断肠 2025-02-17 05:59:03

您可以通过禁用注释处理来“解决”此问题:

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

这看起来像是JDK中的一个错误:当注释处理是否需要发生时(似乎不需要使用明确的注释处理器,因此此问题发生在此问题时发生log4j之类的依赖项将错误报告包裹在deferreddiagnostichandler中。我认为目的是在处理处理后,reportdeferreddiagnostics()将被调用,这将把诊断转移到原始处理程序中,但由于某种原因,这并没有发生。

调试器的更多时间可以正确回答此问题。

You can "fix" this problem by disabling annotation processing:

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

This looks like a bug in the JDK to me: when annotation processing is meant to happen (which doesn't seem to require an explicit annotation processor being used, hence this problem occurs with dependencies like log4j) the error reporting is wrapped in a DeferredDiagnosticHandler. I think the intention is that after the processing is done, reportDeferredDiagnostics() will be called, which will transfer the diagnostics to the original handler, but for some reason this isn't happening.

A bit more time with the debugger would answer this properly.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文