Skip to content

Compiling on Module Path with -Werror and -Xlint:all #3437

Closed
@jjohannes

Description

@jjohannes

This is about getting an error like the following when compiling with a module-info.java and the compiler flags -Xlint:all and -Werror:

> Compilation failed; see the compiler output below.
log4j-api-2.24.3.jar(/org/apache/logging/log4j/message/ParameterizedMessage.class): warning: Cannot find annotation method 'replacement()' in type 'InlineMe': class file for com.google.errorprone.annotations.InlineMe not found
log4j-api-2.24.3.jar(/org/apache/logging/log4j/message/ParameterizedMessage.class): warning: Cannot find annotation method 'imports()' in type 'InlineMe'
log4j-api-2.24.3.jar(/org/apache/logging/log4j/status/StatusData.class): warning: Cannot find annotation method 'value()' in type 'SuppressFBWarnings': class file for edu.umd.cs.findbugs.annotations.SuppressFBWarnings not found
log4j-api-2.24.3.jar(/org/apache/logging/log4j/status/StatusData.class): warning: Cannot find annotation method 'justification()' in type 'SuppressFBWarnings'
log4j-api-2.24.3.jar(/org/apache/logging/log4j/util/SystemPropertiesPropertySource.class): warning: Cannot find annotation method 'value()' in type 'ServiceProvider': class file for aQute.bnd.annotation.spi.ServiceProvider not found
log4j-api-2.24.3.jar(/org/apache/logging/log4j/util/SystemPropertiesPropertySource.class): warning: Cannot find annotation method 'resolution()' in type 'ServiceProvider'
log4j-api-2.24.3.jar(/org/apache/logging/log4j/util/Activator.class): warning: Cannot find annotation method 'value()' in type 'Headers': class file for org.osgi.annotation.bundle.Headers not found
log4j-api-2.24.3.jar(/org/apache/logging/log4j/util/Activator.class): warning: Cannot find annotation method 'name()' in type 'Header': class file for org.osgi.annotation.bundle.Header not found
log4j-api-2.24.3.jar(/org/apache/logging/log4j/util/Activator.class): warning: Cannot find annotation method 'value()' in type 'Header'
log4j-api-2.24.3.jar(/org/apache/logging/log4j/util/Activator.class): warning: Cannot find annotation method 'name()' in type 'Header'
log4j-api-2.24.3.jar(/org/apache/logging/log4j/util/Activator.class): warning: Cannot find annotation method 'value()' in type 'Header'
error: warnings found and -Werror specified
1 error
11 warnings

The error is triggered by using classes from Log4j that use annotations on public members from the annotation libraries indicated in the error message. There are two layers of missing dependencies that cause this:

  1. The annotation library's Jar file (e.g. com.google.errorprone:error_prone_annotations:2.36.0) is not on the Classpath/Module Path
  2. The annotation library's Java Module (e.g. com.google.errorprone.annotations) is not defined as require static in the corresponding module-info.class of Log4j

For (1) it's debatable if it can be fixed in a good way, as POM does not have a scope that resembles Gradle's compileOnlyApi scope: visible transitively but ONLY on the compile classpath.

For (2) you can argue that it is a bug, because if the code of Log4j would be compiled on the Module Path (i.e. with the compiler checking the module-info.java) it would not compile.

Workarounds for users

(1)

  • Adding the missing dependencies directly as compileOnly (<provided>) to your own project.
  • Patching the POM metadata with a rule (possible in Gradle)

(2)

  • Calling the compiler with additional --add-reads arguments
  • Patching the module-info.class itself (possible in Gradle with plugin)

This is a minimal example showing all the annotation libraries that need to be "patched in":
https://github.com/jjohannes/gradle-demos/blob/main/log4j-metadata/build.gradle.kts

Possible improvements in Log4j

(1) This was already discussed here. The dependencies marked as <provided> here would need to be switched to <compile>. But that has the unwanted effect that ALL users will get them as unnecessary RUNTIME dependencies.
There is the option to publish additional Gradle Metadata that supports the compileOnlyApi scope. If you are interested, I can make a contribution for that as I maintain the Maven plugin for publishing such metadata with Maven (it's used by Jackson for example). But I can understand if you don't want to have additional complexity in your build setup.

(2) Maybe you can check if the additional requires could be added to all module-info:

    requires static transitive com.google.errorprone.annotations;
    requires static transitive com.github.spotbugs.annotations;
    requires static transitive biz.aQute.bnd.annotation;
    requires static transitive org.osgi.annotation.bundle;

*requires static works also, but conceptually requires static transitive feels more correct as the annotations are transitively visible.


All of this can also be avoided by turning of the classfiles line check of javac...

I can understand if there is nothing you can/want to do at this point. Then, feel free to close this issue.
Having this written down can be helpful for users who run into this in any case.
If you want to do something I can help with, let me know.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    Status

    Done

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions