diff --git a/cacio-tta/pom.xml b/cacio-tta/pom.xml index ed3134b..6b5eb40 100644 --- a/cacio-tta/pom.xml +++ b/cacio-tta/pom.xml @@ -58,6 +58,7 @@ 17 -XDignore.symbol.file=true + --add-exports=java.base/jdk.internal.misc=ALL-UNNAMED --add-exports=java.desktop/java.awt.peer=ALL-UNNAMED --add-exports=java.desktop/sun.awt.image=ALL-UNNAMED --add-exports=java.desktop/sun.java2d=ALL-UNNAMED diff --git a/cacio-tta/src/main/java/com/github/caciocavallosilano/cacio/ctc/CTCPreloadClassLoader.java b/cacio-tta/src/main/java/com/github/caciocavallosilano/cacio/ctc/CTCPreloadClassLoader.java index 39165da..082380b 100644 --- a/cacio-tta/src/main/java/com/github/caciocavallosilano/cacio/ctc/CTCPreloadClassLoader.java +++ b/cacio-tta/src/main/java/com/github/caciocavallosilano/cacio/ctc/CTCPreloadClassLoader.java @@ -30,24 +30,10 @@ import java.io.File; import java.io.IOException; import java.lang.reflect.Field; -import java.lang.reflect.Modifier; -import java.lang.invoke.MethodHandles; -import java.lang.invoke.VarHandle; import java.net.*; +import jdk.internal.misc.Unsafe; public class CTCPreloadClassLoader extends URLClassLoader { - // https://stackoverflow.com/a/56043252/1050369 - private static final VarHandle MODIFIERS; - - static { - try { - var lookup = MethodHandles.privateLookupIn(Field.class, MethodHandles.lookup()); - MODIFIERS = lookup.findVarHandle(Field.class, "modifiers", int.class); - } catch (IllegalAccessException | NoSuchFieldException ex) { - throw new RuntimeException(ex); - } - } - static { try { Field toolkit = Toolkit.class.getDeclaredField("toolkit"); @@ -67,12 +53,12 @@ public class CTCPreloadClassLoader extends URLClassLoader { defaultHeadlessField.set(null, Boolean.FALSE); headlessField.set(null,Boolean.FALSE); - makeNonFinal(ge); - Class smfCls = Class.forName("sun.java2d.SurfaceManagerFactory"); Field smf = smfCls.getDeclaredField("instance"); smf.setAccessible(true); smf.set(null, null); + + setWithUnsafe(ge, new CTCGraphicsEnvironment()); ge.set(null, new CTCGraphicsEnvironment()); @@ -107,7 +93,7 @@ static URL getFileURL(File file) { } catch (IOException e) {} try { - return file.toURL(); + return file.toURI().toURL(); } catch (MalformedURLException e) { // Should never happen since we specify the protocol... throw new InternalError(e); @@ -119,10 +105,16 @@ private void appendToClassPathForInstrumentation(String path) { super.addURL(getFileURL(new File(path))); } - public static void makeNonFinal(Field field) { - int mods = field.getModifiers(); - if (Modifier.isFinal(mods)) { - MODIFIERS.set(field, mods & ~Modifier.FINAL); - } + public static void setWithUnsafe(Field field, Object value) { + /* + * We can do this because we are running under *very* specific conditions: + * - This class is initialized way before anything AWT-related gets JIT-ed + * - The field is an object reference. + * Otherwise this won't work at all. + */ + Unsafe unsafe = Unsafe.getUnsafe(); + Object base = unsafe.staticFieldBase(field); + long offset = unsafe.staticFieldOffset(field); + unsafe.putReference(base, offset, value); } } diff --git a/cacio-tta/src/main/java/com/github/caciocavallosilano/cacio/ctc/junit/CacioTestRunner.java b/cacio-tta/src/main/java/com/github/caciocavallosilano/cacio/ctc/junit/CacioTestRunner.java index 65613c7..a908c4e 100644 --- a/cacio-tta/src/main/java/com/github/caciocavallosilano/cacio/ctc/junit/CacioTestRunner.java +++ b/cacio-tta/src/main/java/com/github/caciocavallosilano/cacio/ctc/junit/CacioTestRunner.java @@ -27,6 +27,7 @@ import javax.swing.plaf.metal.MetalLookAndFeel; import com.github.caciocavallosilano.cacio.ctc.CTCGraphicsEnvironment; +import com.github.caciocavallosilano.cacio.ctc.CTCPreloadClassLoader; import com.github.caciocavallosilano.cacio.ctc.CTCToolkit; import org.junit.runners.BlockJUnit4ClassRunner; @@ -34,23 +35,8 @@ import java.awt.*; import java.lang.reflect.Field; -import java.lang.reflect.Modifier; -import java.lang.invoke.MethodHandles; -import java.lang.invoke.VarHandle; public class CacioTestRunner extends BlockJUnit4ClassRunner { - // https://stackoverflow.com/a/56043252/1050369 - private static final VarHandle MODIFIERS; - - static { - try { - var lookup = MethodHandles.privateLookupIn(Field.class, MethodHandles.lookup()); - MODIFIERS = lookup.findVarHandle(Field.class, "modifiers", int.class); - } catch (IllegalAccessException | NoSuchFieldException ex) { - throw new RuntimeException(ex); - } - } - static { try { Field toolkit = Toolkit.class.getDeclaredField("toolkit"); @@ -59,7 +45,7 @@ public class CacioTestRunner extends BlockJUnit4ClassRunner { Field defaultHeadlessField = java.awt.GraphicsEnvironment.class.getDeclaredField("defaultHeadless"); defaultHeadlessField.setAccessible(true); - defaultHeadlessField.set(null,Boolean.TRUE); + defaultHeadlessField.set(null,Boolean.TRUE); Field headlessField = java.awt.GraphicsEnvironment.class.getDeclaredField("headless"); headlessField.setAccessible(true); headlessField.set(null,Boolean.TRUE); @@ -70,14 +56,13 @@ public class CacioTestRunner extends BlockJUnit4ClassRunner { defaultHeadlessField.set(null, Boolean.FALSE); headlessField.set(null,Boolean.FALSE); - makeNonFinal(ge); Class smfCls = Class.forName("sun.java2d.SurfaceManagerFactory"); Field smf = smfCls.getDeclaredField("instance"); smf.setAccessible(true); smf.set(null, null); - ge.set(null, new CTCGraphicsEnvironment()); + CTCPreloadClassLoader.setWithUnsafe(ge, new CTCGraphicsEnvironment()); } catch (Exception e) { e.printStackTrace(); } @@ -88,11 +73,4 @@ public class CacioTestRunner extends BlockJUnit4ClassRunner { public CacioTestRunner(Class klass) throws InitializationError { super(klass); } - - public static void makeNonFinal(Field field) { - int mods = field.getModifiers(); - if (Modifier.isFinal(mods)) { - MODIFIERS.set(field, mods & ~Modifier.FINAL); - } - } } diff --git a/pom.xml b/pom.xml index f7c49ba..2703bc5 100644 --- a/pom.xml +++ b/pom.xml @@ -59,6 +59,7 @@ -XDignore.symbol.file=true + --add-exports=java.base/jdk.internal.misc=ALL-UNNAMED --add-exports=java.desktop/java.awt.peer=ALL-UNNAMED --add-exports=java.desktop/sun.awt=ALL-UNNAMED --add-exports=java.desktop/sun.awt.event=ALL-UNNAMED @@ -130,6 +131,7 @@ false + --add-exports=java.base/jdk.internal.misc=ALL-UNNAMED --add-exports=java.desktop/java.awt=ALL-UNNAMED --add-exports=java.desktop/java.awt.peer=ALL-UNNAMED --add-exports=java.desktop/sun.awt.image=ALL-UNNAMED