我参考了lombok.在jdk21中打开jdk.compile的方法,在注解处理器的初始化阶段打开jdk.complie
private static void addOpensForLombok() {
Class<?> cModule;
try {
cModule = Class.forName("java.lang.Module");
} catch (ClassNotFoundException e) {
return; //jdk8-; this is not needed.
}
Unsafe unsafe = getUnsafe();
Object jdkCompilerModule = getJdkCompilerModule();
Object ownModule = getOwnModule();
String[] allPkgs = {
"com.sun.tools.javac.code",
"com.sun.tools.javac.comp",
"com.sun.tools.javac.file",
"com.sun.tools.javac.main",
"com.sun.tools.javac.model",
"com.sun.tools.javac.parser",
"com.sun.tools.javac.processing",
"com.sun.tools.javac.tree",
"com.sun.tools.javac.util",
"com.sun.tools.javac.jvm",
};
try {
Method m = cModule.getDeclaredMethod("implAddOpens", String.class, cModule);
long firstFieldOffset = getFirstFieldOffset(unsafe);
unsafe.putBooleanVolatile(m, firstFieldOffset, true);
for (String p : allPkgs) m.invoke(jdkCompilerModule, p, ownModule);
} catch (Exception ignore) {}
}
我使用
maven clear install
命令将注释处理器打包成jar文件。将此注释处理器应用到其他项目。其他项目编译时出错
class org.example.async.log.client.annotation.AsyncLogProcessor (in unnamed module @0x201c3cda) cannot access class com.sun.tools.javac.api.JavacTrees (in module jdk.compiler) because module jdk.compiler does not export com.sun.tools.javac.api to unnamed module @0x201c3cda
我通过IDEA调试了编译过程。我发现 getOwnModule 方法返回未命名的模块
private static Object getOwnModule() {
try {
Method m = Permit.getMethod(Class.class, "getModule");
return m.invoke(LombokProcessor.class);
} catch (Exception e) {
return null;
}
}
当其他项目依赖注释处理器时,此方法将获取未命名模块。
try {
Method m = cModule.getDeclaredMethod("implAddOpens", String.class, cModule);
long firstFieldOffset = getFirstFieldOffset(unsafe);
unsafe.putBooleanVolatile(m, firstFieldOffset, true);
for (String p : allPkgs) m.invoke(jdkCompilerModule, p, ownModule);
} catch (Exception ignore) {}
implAddOpens
无法为unname模块打开jdk.compile
private void implAddExportsOrOpens(String pn,
Module other,
boolean open,
boolean syncVM) {
Objects.requireNonNull(other);
Objects.requireNonNull(pn);
// all packages are open in unnamed, open, and automatic modules
if (!isNamed() || descriptor.isOpen() || descriptor.isAutomatic())
return;
这说明jdk.compile没有打开成功。但是我在我的项目中添加了module-info.java
import javax.annotation.processing.Processor;
import org.example.async.log.client.annotation.AsyncLogProcessor;
module org.example.async.log.client{
requires jdk.compiler;
requires jdk.unsupported;
exports org.example.async.log.client.annotation;
provides Processor with AsyncLogProcessor;
}
我的项目是这里
正如Mark提到的,你应该确保项目使用模块路径,我不确定你正在使用的maven版本。但鉴于您的代码存储库,我可以看到您可能仍然会回退到旧版本的编译器插件。因此更喜欢明确指定,例如:
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.13.0</version>
<configuration>
<source>21</source>
<target>21</target>
</configuration>
</plugin>
</plugins>
</build>
我可以使用
mvn verify
并在我的机器上配置 JDK-21 进一步确认成功编译代码。