[fixes #2681] [jdk16] support jdk16

This commit is contained in:
Reinier Zwitserloot committed 2021-03-16 17:39:56 +01:00
1 parent 476a43b970
commit 9806e5cca4
5 files changed
+137 -2

No files matched your search

+89 -2
View File
@@ -1,5 +1,5 @@
/*
* Copyright (C) 2009-2019 The Project Lombok Authors.
* Copyright (C) 2009-2020 The Project Lombok Authors.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -63,6 +63,8 @@ import lombok.core.CleanupRegistry;
import lombok.core.DiagnosticsReceiver;
import lombok.javac.JavacTransformer;
import lombok.permit.Permit;
import lombok.permit.dummy.Parent;
import sun.misc.Unsafe;
/**
* This Annotation Processor is the standard injection mechanism for lombok-enabling the javac compiler.
@@ -430,6 +432,7 @@ public class LombokProcessor extends AbstractProcessor {
* gradle incremental compilation, the delegate ProcessingEnvironment of the gradle wrapper is returned.
*/
public JavacProcessingEnvironment getJavacProcessingEnvironment(Object procEnv) {
addOpensForLombok();
if (procEnv instanceof JavacProcessingEnvironment) return (JavacProcessingEnvironment) procEnv;
// try to find a "delegate" field in the object, and use this to try to obtain a JavacProcessingEnvironment
@@ -446,7 +449,91 @@ public class LombokProcessor extends AbstractProcessor {
"Can't get the delegate of the gradle IncrementalProcessingEnvironment. Lombok won't work.");
return null;
}
private static Object getOwnModule() {
try {
Method m = Permit.getMethod(Class.class, "getModule");
return m.invoke(LombokProcessor.class);
} catch (Exception e) {
return null;
}
}
private static Object getJdkCompilerModule() {
/* call public api: ModuleLayer.boot().findModule("jdk.compiler").get();
but use reflection because we don't want this code to crash on jdk1.7 and below.
In that case, none of this stuff was needed in the first place, so we just exit via
the catch block and do nothing.
*/
try {
Class<?> cModuleLayer = Class.forName("java.lang.ModuleLayer");
Method mBoot = cModuleLayer.getDeclaredMethod("boot");
Object bootLayer = mBoot.invoke(null);
Class<?> cOptional = Class.forName("java.util.Optional");
Method mFindModule = cModuleLayer.getDeclaredMethod("findModule", String.class);
Object oCompilerO = mFindModule.invoke(bootLayer, "jdk.compiler");
return cOptional.getDeclaredMethod("get").invoke(oCompilerO);
} catch (Exception e) {
return null;
}
}
/** Useful from jdk9 and up; required from jdk16 and up. This code is supposed to gracefully do nothing on jdk8 and below, as this operation isn't needed there. */
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) {}
}
private static long getFirstFieldOffset(Unsafe unsafe) {
try {
return unsafe.objectFieldOffset(Parent.class.getDeclaredField("first"));
} catch (NoSuchFieldException e) {
// can't happen.
throw new RuntimeException(e);
} catch (SecurityException e) {
// can't happen
throw new RuntimeException(e);
}
}
private static Unsafe getUnsafe() {
try {
Field theUnsafe = Unsafe.class.getDeclaredField("theUnsafe");
theUnsafe.setAccessible(true);
return (Unsafe) theUnsafe.get(null);
} catch (Exception e) {
return null;
}
}
/**
* This class returns the given filer as a JavacFiler. In case the filer is no
* JavacFiler (e.g. the Gradle IncrementalFiler), its "delegate" field is used to get the JavacFiler
+9
View File
@@ -0,0 +1,9 @@
package lombok.permit.dummy;
@SuppressWarnings("all")
public abstract class Child extends Parent {
private transient volatile boolean foo;
private transient volatile Object[] bar;
private transient volatile Object baz;
}
@@ -0,0 +1,19 @@
package lombok.permit.dummy;
@SuppressWarnings("all")
public final class GrandChild extends Child {
private Class<?> a;
private int b;
private String c;
private Class<?> d;
private Class<?>[] e;
private Class<?>[] f;
private int g;
private transient String h;
private transient Object i;
private byte[] j;
private byte[] k;
private byte[] l;
private volatile Object m;
private Object n;
}
+12
View File
@@ -0,0 +1,12 @@
package lombok.permit.dummy;
import java.io.OutputStream;
@SuppressWarnings("all")
public class Parent {
boolean first;
static final Object staticObj = OutputStream.class;
volatile Object second;
private static volatile boolean staticSecond;
private static volatile boolean staticThird;
}
@@ -0,0 +1,8 @@
/**
* This package recreates the type hierarchy of {@code java.lang.reflect.AccessibleObject} and friends (such as {@code java.lang.reflect.Method});
* its purpose is to allow us to ask {@code sun.misc.internal.Unsafe} about the exact offset of the {@code override} field of {@code AccessibleObject};
* asking about that field directly doesn't work after jdk14, presumably because the fields of AO are expressly hidden somehow.
*
* NB: It's usually 12, on the vast majority of OS, VM, and architecture combos.
*/
package lombok.permit.dummy;