Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -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<T> {
public final class ClassFactory<T> {
private final Mapper<T> 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<T> 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<T> 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) {
Expand All @@ -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);
}
};
Expand All @@ -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);
Expand All @@ -77,10 +66,11 @@ public String map(String internalName) {

@SuppressWarnings("unchecked")
private static <E extends Throwable, R> R sneak(Throwable e) throws E {
throw (E)e;
throw (E) e;
}

public static interface Mapper<T> {
@FunctionalInterface
public interface Mapper<T> {
T apply(Class<?> cls) throws Exception;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -26,9 +27,13 @@ public void onResultEvent(ResultEvent event) { }
public void onSimpleEvent(EventWithData event) { }

public static class Factory {
public static final ClassFactory<Consumer<IEventBus>> REGISTER = new ClassFactory<>("net.minecraftforge.eventbus.testjar.subscribers.SubscriberDynamic", cls -> {
var inst = cls.getConstructor().newInstance();
return bus -> bus.register(inst);
});
public static final ClassFactory<Consumer<IEventBus>> REGISTER = new ClassFactory<>(
SubscriberDynamic.class,
MethodHandles.lookup(),
cls -> {
var inst = cls.getConstructor().newInstance();
return bus -> bus.register(inst);
}
);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -29,6 +30,10 @@ public static void onSimpleEvent(EventWithData event) { }

public static class Factory {
@SuppressWarnings("unchecked")
public static final ClassFactory<Consumer<IEventBus>> REGISTER = new ClassFactory<>("net.minecraftforge.eventbus.testjar.subscribers.SubscriberLambda", cls -> (Consumer<IEventBus>)cls.getDeclaredField("register").get(null));
public static final ClassFactory<Consumer<IEventBus>> REGISTER = new ClassFactory<>(
SubscriberLambda.class,
MethodHandles.lookup(),
cls -> (Consumer<IEventBus>) cls.getDeclaredField("register").get(null)
);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -26,6 +27,10 @@ public static void onResultEvent(ResultEvent event) { }
public static void onSimpleEvent(EventWithData event) { }

public static class Factory {
public static final ClassFactory<Consumer<IEventBus>> REGISTER = new ClassFactory<>("net.minecraftforge.eventbus.testjar.subscribers.SubscriberStatic", cls -> bus -> bus.register(cls));
public static final ClassFactory<Consumer<IEventBus>> REGISTER = new ClassFactory<>(
SubscriberStatic.class,
MethodHandles.lookup(),
cls -> bus -> bus.register(cls)
);
}
}