Skip to content

Commit

Permalink
Sync with JVM when opening modules & removed add opens + redo tests
Browse files Browse the repository at this point in the history
  • Loading branch information
Rongmario committed Feb 15, 2024
1 parent ea5d23d commit b198048
Show file tree
Hide file tree
Showing 10 changed files with 196 additions and 76 deletions.
5 changes: 0 additions & 5 deletions build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -12,10 +12,6 @@ java {
withJavadocJar()
}

tasks.withType(JavaExec).configureEach {
jvmArgs '--add-opens=java.base/jdk.internal.reflect=ALL-UNNAMED'
}

tasks.withType(Javadoc).configureEach {
options {
quiet()
Expand Down Expand Up @@ -71,7 +67,6 @@ targetVendors.each { spec, info ->
toolchain.vendor = spec
}
test.useJUnitPlatform()
test.jvmArgs '--add-opens=java.base/jdk.internal.reflect=ALL-UNNAMED'
if (javaVersion < 17) {
test.jvmArgs '--illegal-access=deny'
}
Expand Down
23 changes: 23 additions & 0 deletions src/main/java/zone/rong/imaginebreaker/ImagineBreaker.java
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,8 @@ public final class ImagineBreaker {

private static final Unsafe UNSAFE = retrieveUnsafe();
private static final Lookup LOOKUP = retrieveLookup();
private static final MethodHandle MODULE$ADD_EXPORTS_TO_ALL_0 = retrieveAddExportsToAll0();

private static final Set<Module> EVERYONE_MODULE_SET = retrieveEveryoneSet();
private static final VarHandle MODULE$OPEN_PACKAGES = retrieveOpenPackagesHandle();
private static final VarHandle CLASS$MODULE = retrieveModuleHandle();
Expand Down Expand Up @@ -60,6 +62,10 @@ public static void openBootModules() {
openModuleLayer(ModuleLayer.boot());
}

public static void openBootModule(String bootModule) {
openModule(ModuleLayer.boot().findModule(bootModule).orElseThrow());
}

/**
* Opens all modules within the specified ModuleLayer
*
Expand All @@ -76,6 +82,13 @@ public static void openModuleLayer(ModuleLayer layer) {
*/
public static void openModule(Module module) {
MODULE$OPEN_PACKAGES.set(module, WorldRejector.INSTANCE);
for (String pkg : module.getPackages()) {
try {
MODULE$ADD_EXPORTS_TO_ALL_0.invokeExact(module, pkg);
} catch (Throwable e) {
throw new RuntimeException(e);
}
}
}

/**
Expand Down Expand Up @@ -199,6 +212,14 @@ private static Field retrieveImplLookup() {
}
}

private static MethodHandle retrieveAddExportsToAll0() {
try {
return LOOKUP.findStatic(Module.class, "addExportsToAll0", MethodType.methodType(void.class, Module.class, String.class));
} catch (NoSuchMethodException | IllegalAccessException e) {
throw new RuntimeException(e);
}
}

private static Set<Module> retrieveEveryoneSet() {
try {
return (Set<Module>) LOOKUP.findStaticVarHandle(Module.class, "EVERYONE_SET", Set.class).get();
Expand Down Expand Up @@ -234,6 +255,7 @@ private static VarHandle retrieveModuleHandle() {

private static VarHandle retrieveFieldFilterMap() {
try {
openBootModule("java.base");
return LOOKUP.findStaticVarHandle(Reflection.class, "fieldFilterMap", Map.class);
} catch (IllegalAccessException e1) {
if (e1.getMessage().endsWith("Expected static field.")) {
Expand All @@ -251,6 +273,7 @@ private static VarHandle retrieveFieldFilterMap() {

private static VarHandle retrieveMethodFilterMap() {
try {
openBootModule("java.base");
return LOOKUP.findStaticVarHandle(Reflection.class, "methodFilterMap", Map.class);
} catch (IllegalAccessException e1) {
if (e1.getMessage().endsWith("Expected static field.")) {
Expand Down
67 changes: 0 additions & 67 deletions src/test/java/zone/rong/imaginebreaker/FilterTest.java

This file was deleted.

Original file line number Diff line number Diff line change
@@ -1,16 +1,19 @@
package zone.rong.imaginebreaker;
package zone.rong.imaginebreaker.lookup;

import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.condition.EnabledForJreRange;
import org.junit.jupiter.api.condition.JRE;
import org.junit.jupiter.api.parallel.Isolated;
import zone.rong.imaginebreaker.ImagineBreaker;

import java.lang.invoke.MethodHandle;
import java.lang.invoke.MethodHandles;
import java.lang.reflect.AccessibleObject;
import java.lang.reflect.Field;
import java.lang.reflect.Method;

@Isolated
public class LookupTest {

@Test
Expand Down
Original file line number Diff line number Diff line change
@@ -1,15 +1,17 @@
package zone.rong.imaginebreaker;
package zone.rong.imaginebreaker.module;

import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.parallel.Isolated;
import zone.rong.imaginebreaker.ImagineBreaker;

import java.lang.reflect.Field;
import java.lang.reflect.InaccessibleObjectException;

@Isolated
public class ModuleTest {

@Test
public void openBootModules() throws ReflectiveOperationException {
public void openBootModules() {
Assertions.assertThrows(RuntimeException.class, this::retrieveStringBackingArray);
ImagineBreaker.openBootModules();
Assertions.assertDoesNotThrow(this::retrieveStringBackingArray);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
package zone.rong.imaginebreaker.reflectionfilter;

import jdk.internal.reflect.Reflection;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.condition.EnabledForJreRange;
import org.junit.jupiter.api.condition.JRE;
import org.junit.jupiter.api.parallel.Isolated;
import zone.rong.imaginebreaker.ImagineBreaker;

import java.lang.reflect.Method;
import java.util.Set;

@Isolated
@EnabledForJreRange(min = JRE.JAVA_12)
public class NewFieldReflectionFilterTest {

@Test
public void removeFieldFilters() {
ImagineBreaker.openBootModule("java.base");
registerFieldFilter();
Assertions.assertThrows(NoSuchFieldException.class, Subject::retrieveSubjectField);
ImagineBreaker.wipeFieldFilters();
Assertions.assertDoesNotThrow(Subject::retrieveSubjectField);
}

private void registerFieldFilter() {
try {
Method method = Reflection.class.getDeclaredMethod("registerFieldsToFilter", Class.class, Set.class);
method.invoke(null, Subject.class, Set.of("subjectField"));
} catch (Exception e) {
throw new RuntimeException(e);
}
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
package zone.rong.imaginebreaker.reflectionfilter;

import jdk.internal.reflect.Reflection;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.condition.EnabledForJreRange;
import org.junit.jupiter.api.condition.JRE;
import org.junit.jupiter.api.parallel.Isolated;
import zone.rong.imaginebreaker.ImagineBreaker;

import java.lang.reflect.Method;
import java.util.Set;

@Isolated
@EnabledForJreRange(min = JRE.JAVA_12)
public class NewMethodReflectionFilterTest {

@Test
public void removeMethodFilters() {
ImagineBreaker.openBootModule("java.base");
registerMethodFilter();
Assertions.assertThrows(NoSuchMethodException.class, Subject::retrieveSubjectMethod);
ImagineBreaker.wipeMethodFilters();
Assertions.assertDoesNotThrow(Subject::retrieveSubjectMethod);
}

private void registerMethodFilter() {
try {
Method method = Reflection.class.getDeclaredMethod("registerMethodsToFilter", Class.class, Set.class);
method.invoke(null, Subject.class, Set.of("subjectMethod"));
} catch (Exception e) {
throw new RuntimeException(e);
}
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
package zone.rong.imaginebreaker.reflectionfilter;

import jdk.internal.reflect.Reflection;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.condition.EnabledForJreRange;
import org.junit.jupiter.api.condition.JRE;
import org.junit.jupiter.api.parallel.Isolated;
import zone.rong.imaginebreaker.ImagineBreaker;

import java.lang.reflect.Method;

@Isolated
@EnabledForJreRange(min = JRE.JAVA_9, max = JRE.JAVA_11)
public class OldFieldReflectionFilterTest {

@Test
public void removeFieldFilters() {
ImagineBreaker.openBootModule("java.base");
registerFieldFilter();
Assertions.assertThrows(NoSuchFieldException.class, Subject::retrieveSubjectField);
ImagineBreaker.wipeFieldFilters();
Assertions.assertDoesNotThrow(Subject::retrieveSubjectField);
}

private void registerFieldFilter() {
try {
Method method = Reflection.class.getDeclaredMethod("registerFieldsToFilter", Class.class, String[].class);
method.invoke(null, Subject.class, new String[] { "subjectField" });
} catch (Exception e) {
throw new RuntimeException(e);
}
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
package zone.rong.imaginebreaker.reflectionfilter;

import jdk.internal.reflect.Reflection;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.condition.EnabledForJreRange;
import org.junit.jupiter.api.condition.JRE;
import org.junit.jupiter.api.parallel.Isolated;
import zone.rong.imaginebreaker.ImagineBreaker;

import java.lang.reflect.Method;

@Isolated
@EnabledForJreRange(min = JRE.JAVA_9, max = JRE.JAVA_11)
public class OldMethodReflectionFilterTest {

@Test
public void removeMethodFilters() {
ImagineBreaker.openBootModule("java.base");
registerMethodFilter();
Assertions.assertThrows(NoSuchMethodException.class, Subject::retrieveSubjectMethod);
ImagineBreaker.wipeMethodFilters();
Assertions.assertDoesNotThrow(Subject::retrieveSubjectMethod);
}

private void registerMethodFilter() {
try {
Method method = Reflection.class.getDeclaredMethod("registerMethodsToFilter", Class.class, String[].class);
method.invoke(null, Subject.class, new String[] { "subjectMethod" });
} catch (Exception e) {
throw new RuntimeException(e);
}
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
package zone.rong.imaginebreaker.reflectionfilter;

import java.lang.reflect.Field;
import java.lang.reflect.Method;

class Subject {

private static int subjectField = -1;

private static int subjectMethod() {
return -1;
}

static Field retrieveSubjectField() throws NoSuchFieldException {
return Subject.class.getDeclaredField("subjectField");
}

static Method retrieveSubjectMethod() throws NoSuchMethodException {
return Subject.class.getDeclaredMethod("subjectMethod");
}

}

0 comments on commit b198048

Please sign in to comment.