简体   繁体   English

Java 编译器不允许在使用 JPMS 的项目中使用来自 `compileOnly` 模块的具有 `Source` 保留的注释

[英]The Java compiler does not allow usage of an annotation with `Source` retention from a `compileOnly` module for a project using JPMS

Annotation processors and compiler plugins often define annotations with source or class retention.注释处理器和编译器插件通常定义带有sourceclass保留的注释。 These annotations are not exposed at runtime, thus there is no need to include them in the runtime classpath;这些注解不会在运行时暴露,因此不需要将它们包含在运行时类路径中; they can be used via compileOnly in a Gradle build file.它们可以通过compileOnly在 Gradle 构建文件中使用。 Additionally, there is no need to declare their use in the module-info file.此外,无需在module-info文件中声明它们的用途。 Yet, in the presence of a module-info file, the Java compiler requires the annotation classes to be included in the runtime classpath -- they must be declared in the module-info, which means they must be accessed from Gradle with implementation instead of compileOnly .然而,在存在module-info文件的情况下,Java 编译器要求注释类包含在运行时类路径中——它们必须在模块信息中声明,这意味着它们必须从 Gradle 访问,并使用implementation而不是compileOnly This appears to be a hole in the compiler's support for JPMS.这似乎是编译器对 JPMS 支持的一个漏洞。 Or, is there a good explanation for this odd behavior?或者,对这种奇怪的行为有很好的解释吗?

Here's an example.这是一个例子。

package com.example;
...

@Retention(RetentionPolicy.SOURCE)
public @interface Example {
...
}

The com.example.Example annotation is defined in dependency my-annotation-proc . com.example.Example注释在依赖my-annotation-proc中定义。

dependencies {
    compileOnly 'com.example:my-annotation-proc:0.1-SNAPSHOT'
    annotationProcessor 'com.example:my-annotation-proc:0.1-SNAPSHOT'
}

Usage of ExampleAnnotation in Foo.java.在 Foo.java 中使用ExampleAnnotation

package abc;

public class Foo {
  
  @com.example.Example
  public void something() {
    ...
  }
}

The module-info.java file should not need a requires for usage of the annotation. module-info.java文件不需要使用requires

module MyProject {
  // Should be no need for this. 
  // Plus, adding it requires an `implementation` dependency in Gradle, which brings it into runtime where it does not belong.
  //requires my.annotation.proc;
}

Compiling the project produces a compile error indicating the com.example is not visible etc.编译项目会产生编译错误,指示com.example不可见等。

A requires directive is mandatory for any dependency, not just runtime dependencies.任何依赖项都必须使用requires指令,而不仅仅是运行时依赖项。

Compare with JLS, §7.7.1 :JLS 比较,§7.7.1

7.7.1. 7.7.1. Dependences依赖性

The requires directive specifies the name of a module on which the current module has a dependence. requires指令指定当前模块所依赖的模块的名称。

The requires keyword may be followed by the modifier static . requires关键字后面可以跟修饰符static This specifies that the dependence, while mandatory at compile time, is optional at run time.这指定了依赖关系,虽然在编译时是必需的,但在运行时是可选的。

I don't know whether using requires static my.annotation.proc;不知道使用是否requires static my.annotation.proc; solves your problem with Gradle, but that's how it is supposed to be handled at the language level.用 Gradle 解决了您的问题,但这就是应该在语言级别处理的方式。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM