diff --git a/eventbus-test-jar/src/main/java/net/minecraftforge/eventbus/testjar/benchmarks/ClassFactory.java b/eventbus-test-jar/src/main/java/net/minecraftforge/eventbus/testjar/benchmarks/ClassFactory.java index 4fb63ba0..7d8bdcd6 100644 --- a/eventbus-test-jar/src/main/java/net/minecraftforge/eventbus/testjar/benchmarks/ClassFactory.java +++ b/eventbus-test-jar/src/main/java/net/minecraftforge/eventbus/testjar/benchmarks/ClassFactory.java @@ -6,29 +6,30 @@ package net.minecraftforge.eventbus.testjar.benchmarks; import java.io.IOException; -import java.lang.reflect.Method; +import java.lang.invoke.MethodHandles; import org.objectweb.asm.ClassReader; import org.objectweb.asm.ClassWriter; import org.objectweb.asm.commons.ClassRemapper; import org.objectweb.asm.commons.Remapper; -import net.minecraftforge.unsafe.UnsafeHacks; - -public class ClassFactory { +public final class ClassFactory { private final Mapper mapper; private final String binaryName; - private final String name; private final byte[] data; - private final Method define; + private final MethodHandles.Lookup lookup; private int count; - public ClassFactory(String name, Mapper mapper) { + /** + * @param clazz The class to create new derivations of + * @param lookup {@code MethodHandles.lookup()} for defining the new classes + * @param mapper A function to apply on newly defined classes + */ + public ClassFactory(Class clazz, MethodHandles.Lookup lookup, Mapper mapper) { this.mapper = mapper; - this.name = name; - this.binaryName = name.replace('.', '/'); + this.binaryName = clazz.getName().replace('.', '/'); this.data = readData(this.binaryName); - this.define = getAccess(); + this.lookup = lookup; } private static byte[] readData(String name) { @@ -40,24 +41,13 @@ private static byte[] readData(String name) { } } - private static Method getAccess() { - try { - var define = ClassLoader.class.getDeclaredMethod("defineClass", String.class, byte[].class, int.class, int.class); - UnsafeHacks.setAccessible(define); - return define; - } catch (Exception e) { - return sneak(e); - } - } - public T create() { count++; - var newName = this.binaryName + "$New" + count; var renamer = new Remapper() { @Override public String map(String internalName) { - if (internalName.equals(binaryName)) return newName; + if (internalName.equals(binaryName)) return binaryName + "$New" + count; return BenchmarkManager.rename(internalName); } }; @@ -66,9 +56,8 @@ public String map(String internalName) { var writer = new ClassWriter(ClassWriter.COMPUTE_FRAMES | ClassWriter.COMPUTE_MAXS); reader.accept(new ClassRemapper(writer, renamer), 0); try { - var cl = Thread.currentThread().getContextClassLoader(); var newData = writer.toByteArray(); - var newCls = (Class)define.invoke(cl, this.name + "$New" + count, newData, 0, newData.length); + var newCls = (Class) lookup.defineClass(newData); return mapper.apply(newCls); } catch (Exception e) { return sneak(e); @@ -77,10 +66,11 @@ public String map(String internalName) { @SuppressWarnings("unchecked") private static R sneak(Throwable e) throws E { - throw (E)e; + throw (E) e; } - public static interface Mapper { + @FunctionalInterface + public interface Mapper { T apply(Class cls) throws Exception; } } diff --git a/eventbus-test-jar/src/main/java/net/minecraftforge/eventbus/testjar/subscribers/SubscriberDynamic.java b/eventbus-test-jar/src/main/java/net/minecraftforge/eventbus/testjar/subscribers/SubscriberDynamic.java index 2c684cf5..1d01e082 100644 --- a/eventbus-test-jar/src/main/java/net/minecraftforge/eventbus/testjar/subscribers/SubscriberDynamic.java +++ b/eventbus-test-jar/src/main/java/net/minecraftforge/eventbus/testjar/subscribers/SubscriberDynamic.java @@ -6,6 +6,7 @@ package net.minecraftforge.eventbus.testjar.subscribers; +import java.lang.invoke.MethodHandles; import java.util.function.Consumer; import net.minecraftforge.eventbus.api.IEventBus; @@ -26,9 +27,13 @@ public void onResultEvent(ResultEvent event) { } public void onSimpleEvent(EventWithData event) { } public static class Factory { - public static final ClassFactory> REGISTER = new ClassFactory<>("net.minecraftforge.eventbus.testjar.subscribers.SubscriberDynamic", cls -> { - var inst = cls.getConstructor().newInstance(); - return bus -> bus.register(inst); - }); + public static final ClassFactory> REGISTER = new ClassFactory<>( + SubscriberDynamic.class, + MethodHandles.lookup(), + cls -> { + var inst = cls.getConstructor().newInstance(); + return bus -> bus.register(inst); + } + ); } } diff --git a/eventbus-test-jar/src/main/java/net/minecraftforge/eventbus/testjar/subscribers/SubscriberLambda.java b/eventbus-test-jar/src/main/java/net/minecraftforge/eventbus/testjar/subscribers/SubscriberLambda.java index b61e5caa..8b037ea9 100644 --- a/eventbus-test-jar/src/main/java/net/minecraftforge/eventbus/testjar/subscribers/SubscriberLambda.java +++ b/eventbus-test-jar/src/main/java/net/minecraftforge/eventbus/testjar/subscribers/SubscriberLambda.java @@ -5,6 +5,7 @@ package net.minecraftforge.eventbus.testjar.subscribers; +import java.lang.invoke.MethodHandles; import java.util.function.Consumer; import net.minecraftforge.eventbus.api.IEventBus; @@ -29,6 +30,10 @@ public static void onSimpleEvent(EventWithData event) { } public static class Factory { @SuppressWarnings("unchecked") - public static final ClassFactory> REGISTER = new ClassFactory<>("net.minecraftforge.eventbus.testjar.subscribers.SubscriberLambda", cls -> (Consumer)cls.getDeclaredField("register").get(null)); + public static final ClassFactory> REGISTER = new ClassFactory<>( + SubscriberLambda.class, + MethodHandles.lookup(), + cls -> (Consumer) cls.getDeclaredField("register").get(null) + ); } } diff --git a/eventbus-test-jar/src/main/java/net/minecraftforge/eventbus/testjar/subscribers/SubscriberStatic.java b/eventbus-test-jar/src/main/java/net/minecraftforge/eventbus/testjar/subscribers/SubscriberStatic.java index 6c4536b9..02fefb76 100644 --- a/eventbus-test-jar/src/main/java/net/minecraftforge/eventbus/testjar/subscribers/SubscriberStatic.java +++ b/eventbus-test-jar/src/main/java/net/minecraftforge/eventbus/testjar/subscribers/SubscriberStatic.java @@ -6,6 +6,7 @@ package net.minecraftforge.eventbus.testjar.subscribers; +import java.lang.invoke.MethodHandles; import java.util.function.Consumer; import net.minecraftforge.eventbus.api.IEventBus; @@ -26,6 +27,10 @@ public static void onResultEvent(ResultEvent event) { } public static void onSimpleEvent(EventWithData event) { } public static class Factory { - public static final ClassFactory> REGISTER = new ClassFactory<>("net.minecraftforge.eventbus.testjar.subscribers.SubscriberStatic", cls -> bus -> bus.register(cls)); + public static final ClassFactory> REGISTER = new ClassFactory<>( + SubscriberStatic.class, + MethodHandles.lookup(), + cls -> bus -> bus.register(cls) + ); } }