Skip to content

Commit

Permalink
Fix bug when registering the same EventHandler twice on the CrucibleE…
Browse files Browse the repository at this point in the history
…ventBus by adding a Cache for the PluginClassLoaderFactory and also add an incremental ID for uniqueNames of these wrappers.

Remove the CrucibleUnsafe.java
  • Loading branch information
EverNife committed Oct 20, 2024
1 parent fdd020e commit 965ca5e
Show file tree
Hide file tree
Showing 2 changed files with 31 additions and 72 deletions.
Original file line number Diff line number Diff line change
@@ -1,19 +1,24 @@
package io.github.crucible.eventfactory;

import com.google.common.collect.Maps;
import cpw.mods.fml.common.eventhandler.Event;
import cpw.mods.fml.common.eventhandler.IEventListener;
import io.github.crucible.unsafe.CrucibleUnsafe;
import org.objectweb.asm.ClassWriter;
import org.objectweb.asm.MethodVisitor;
import org.objectweb.asm.Type;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.security.ProtectionDomain;
import java.util.HashMap;
import java.util.concurrent.atomic.AtomicInteger;

import static org.objectweb.asm.Opcodes.*;

public class PluginClassLoaderFactory {
private static AtomicInteger IDs = new AtomicInteger();
private static final HashMap<Method, Class<?>> cache = Maps.newHashMap();
private static final String HANDLER_DESC = Type.getInternalName(IEventListener.class);
private static final String HANDLER_FUNC_DESC = Type.getMethodDescriptor(Type.VOID_TYPE, Type.getType(Event.class));

Expand All @@ -26,6 +31,9 @@ public IEventListener create(Method method, Object target) throws InstantiationE
}

public Class<?> createWrapper(Method callback) {
if (cache.containsKey(callback)) {
return cache.get(callback);
}

ClassWriter cw = new ClassWriter(0);
MethodVisitor mv;
Expand Down Expand Up @@ -74,15 +82,32 @@ public Class<?> createWrapper(Method callback) {
}
cw.visitEnd();
byte[] bytes = cw.toByteArray();
return CrucibleUnsafe.defineClass(name, bytes, 0, bytes.length, callback.getDeclaringClass().getClassLoader(), callback.getDeclaringClass().getProtectionDomain());

PluginASMClassLoader LOADER = new PluginASMClassLoader(callback.getDeclaringClass().getClassLoader(), callback.getDeclaringClass().getProtectionDomain());
Class<?> ret = LOADER.define(name, bytes);
cache.put(callback, ret);
return ret;
}

public String getUniqueName(Method callback) {
return String.format("%s.__%s_%s_%s",
callback.getDeclaringClass().getPackage().getName(),
return String.format("%s_%d_%s_%s_%s",
getClass().getName(),
IDs.incrementAndGet(),
callback.getDeclaringClass().getSimpleName(),
callback.getName(),
callback.getParameterTypes()[0].getSimpleName()
);
callback.getParameterTypes()[0].getSimpleName());
}

private static class PluginASMClassLoader extends ClassLoader {
private final ProtectionDomain protectionDomain;

private PluginASMClassLoader(ClassLoader classLoader, ProtectionDomain protectionDomain) {
super(classLoader);
this.protectionDomain = protectionDomain;
}

public Class<?> define(String name, byte[] data) {
return defineClass(name, data, 0, data.length, protectionDomain);
}
}
}
66 changes: 0 additions & 66 deletions src/main/java/io/github/crucible/unsafe/CrucibleUnsafe.java

This file was deleted.

0 comments on commit 965ca5e

Please sign in to comment.