Skip to content

Commit

Permalink
Made IS_OPEN_J9 public + made a workaround for OpenJ9 9-15 issues
Browse files Browse the repository at this point in the history
  • Loading branch information
Rongmario committed Feb 15, 2024
1 parent daea66c commit ce5e030
Show file tree
Hide file tree
Showing 2 changed files with 60 additions and 18 deletions.
61 changes: 49 additions & 12 deletions src/main/java/zone/rong/imaginebreaker/ImagineBreaker.java
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,9 @@
import jdk.internal.reflect.Reflection;
import sun.misc.Unsafe;

import java.lang.invoke.MethodHandles;
import java.lang.invoke.MethodHandle;
import java.lang.invoke.MethodHandles.Lookup;
import java.lang.invoke.MethodType;
import java.lang.invoke.VarHandle;
import java.lang.ref.SoftReference;
import java.lang.reflect.Field;
Expand All @@ -22,9 +24,10 @@
*/
public final class ImagineBreaker {

private static final boolean IS_OPEN_J9 = isOpenJ9();
public static final boolean IS_OPEN_J9 = isOpenJ9();

private static final Unsafe UNSAFE = retrieveUnsafe();
private static final MethodHandles.Lookup LOOKUP = retrieveLookup();
private static final Lookup LOOKUP = retrieveLookup();
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 All @@ -46,7 +49,7 @@ public static Unsafe unsafe() {
*
* @return instance of the trusted lookup.
*/
public static MethodHandles.Lookup lookup() {
public static Lookup lookup() {
return LOOKUP;
}

Expand Down Expand Up @@ -182,15 +185,15 @@ private static Unsafe retrieveUnsafe() {
}
}

private static MethodHandles.Lookup retrieveLookup() {
private static Lookup retrieveLookup() {
Field methodHandles$lookup$implLookup = retrieveImplLookup();
long offset = UNSAFE.staticFieldOffset(methodHandles$lookup$implLookup);
return (MethodHandles.Lookup) UNSAFE.getObject(MethodHandles.Lookup.class, offset);
return (Lookup) UNSAFE.getObject(Lookup.class, offset);
}

private static Field retrieveImplLookup() {
try {
return MethodHandles.Lookup.class.getDeclaredField("IMPL_LOOKUP");
return Lookup.class.getDeclaredField("IMPL_LOOKUP");
} catch (NoSuchFieldException e) {
throw new RuntimeException(e);
}
Expand All @@ -199,7 +202,16 @@ private static Field retrieveImplLookup() {
private static Set<Module> retrieveEveryoneSet() {
try {
return (Set<Module>) LOOKUP.findStaticVarHandle(Module.class, "EVERYONE_SET", Set.class).get();
} catch (NoSuchFieldException | IllegalAccessException e) {
} catch (IllegalAccessException e1) {
if (e1.getMessage().endsWith("Expected static field.")) {
try {
return (Set<Module>) mockLookup(Module.class).findStaticVarHandle(Module.class, "EVERYONE_SET", Set.class).get();
} catch (Throwable e) {
throw new RuntimeException(e);
}
}
throw new RuntimeException(e1);
} catch (NoSuchFieldException e) {
throw new RuntimeException(e);
}
}
Expand All @@ -223,16 +235,34 @@ private static VarHandle retrieveModuleHandle() {
private static VarHandle retrieveFieldFilterMap() {
try {
return LOOKUP.findStaticVarHandle(Reflection.class, "fieldFilterMap", Map.class);
} catch (NoSuchFieldException | IllegalAccessException e) {
throw new RuntimeException(e);
} catch (IllegalAccessException e1) {
if (e1.getMessage().endsWith("Expected static field.")) {
try {
return mockLookup(Reflection.class).findStaticVarHandle(Reflection.class, "fieldFilterMap", Map.class);
} catch (Throwable e) {
throw new RuntimeException(e);
}
}
throw new RuntimeException(e1);
} catch (NoSuchFieldException e2) {
throw new RuntimeException(e2);
}
}

private static VarHandle retrieveMethodFilterMap() {
try {
return LOOKUP.findStaticVarHandle(Reflection.class, "methodFilterMap", Map.class);
} catch (NoSuchFieldException | IllegalAccessException e) {
throw new RuntimeException(e);
} catch (IllegalAccessException e1) {
if (e1.getMessage().endsWith("Expected static field.")) {
try {
return mockLookup(Reflection.class).findStaticVarHandle(Reflection.class, "methodFilterMap", Map.class);
} catch (Throwable e) {
throw new RuntimeException(e);
}
}
throw new RuntimeException(e1);
} catch (NoSuchFieldException e2) {
throw new RuntimeException(e2);
}
}

Expand All @@ -247,6 +277,13 @@ private static VarHandle retrieveReflectionData() {
}
}

// Extremely crude hack, used for OpenJ9 9 - 15, where nothing ever made sense
private static Lookup mockLookup(Class<?> mockClass) throws Throwable {
MethodHandle lookup$ctor = LOOKUP.findConstructor(Lookup.class,
MethodType.methodType(void.class, Class.class, Class.class, int.class, boolean.class));
return (Lookup) lookup$ctor.invokeExact(mockClass, (Class) null, 31, false); // Magic number
}

private ImagineBreaker() { }

private static class WorldRejector extends AbstractMap<String, Set<Module>> {
Expand Down
17 changes: 11 additions & 6 deletions src/test/java/zone/rong/imaginebreaker/LookupTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@

import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;
import org.junit.platform.commons.function.Try;
import org.junit.platform.commons.util.ReflectionUtils;
import org.junit.jupiter.api.condition.EnabledForJreRange;
import org.junit.jupiter.api.condition.JRE;

import java.lang.invoke.MethodHandle;
import java.lang.invoke.MethodHandles;
Expand All @@ -13,13 +13,18 @@

public class LookupTest {

// Can be 63 or 127
private static final Try<Object> EXPECTED_MODES = ReflectionUtils.tryToReadFieldValue(MethodHandles.Lookup.class, "ALL_MODES", null);
@Test
@EnabledForJreRange(min = JRE.JAVA_9, max = JRE.JAVA_16)
public void lookupOld() {
MethodHandles.Lookup lookup = ImagineBreaker.lookup();
Assertions.assertEquals(lookup.lookupModes(), ImagineBreaker.IS_OPEN_J9 ? 128 : 63);
}

@Test
public void lookup() throws Exception {
@EnabledForJreRange(min = JRE.JAVA_17)
public void lookupNew() {
MethodHandles.Lookup lookup = ImagineBreaker.lookup();
Assertions.assertTrue(lookup.lookupModes() == 63 || lookup.lookupModes() == 127);
Assertions.assertEquals(lookup.lookupModes(), 127);
}

@Test
Expand Down

0 comments on commit ce5e030

Please sign in to comment.