diff --git a/src/com/tofvesson/hacks/ClassHacks.java b/src/com/tofvesson/hacks/ClassHacks.java deleted file mode 100644 index 3d5d486..0000000 --- a/src/com/tofvesson/hacks/ClassHacks.java +++ /dev/null @@ -1,59 +0,0 @@ -package com.tofvesson.hacks; - -import jdk.internal.org.objectweb.asm.ClassReader; -import jdk.internal.org.objectweb.asm.ClassWriter; -import jdk.internal.org.objectweb.asm.MethodVisitor; -import sun.misc.Unsafe; -import java.io.IOException; -import java.lang.reflect.Field; -import java.lang.reflect.InvocationTargetException; -import java.lang.reflect.Method; - -import static org.objectweb.asm.Opcodes.*; - -public class ClassHacks { - public static <T> Class<T> injectField(Class<T> target, Object toInject, String name) throws IOException, NoSuchMethodException, InvocationTargetException, IllegalAccessException { - try{ // Get unsafe - Field f = target.getDeclaredField(name); - f.setAccessible(true); - - Field f1 = Unsafe.class.getDeclaredField("theUnsafe"); - f1.setAccessible(true); - - f.set(((Unsafe)f1.get(null)).allocateInstance(target), toInject); // Check if field exists - }catch(Exception e){} // Will never happen - - // Read from class - ClassReader cr = new ClassReader(target.getClassLoader().getResourceAsStream(target.getName().replace(".", "/")+".class")); - ClassWriter cw = new ClassWriter(cr, ClassWriter.COMPUTE_MAXS); // Prepare to write - - // Get all fully defined interface class names - String[] itf = new String[target.getInterfaces().length]; - for(int i = 0; i<itf.length; ++i) itf[i] = target.getInterfaces()[i].getName().replace(".", "/"); - - // Create class definition - cw.visit(V1_8, ACC_PUBLIC, target.getSimpleName(), "L"+target.getName().replace(".", "/")+";", - target.getSuperclass().getName().replace(".", "/"), itf); - - // Define blank constructor - MethodVisitor mv = cw.visitMethod(ACC_PUBLIC, "<init>", "()V", "L"+target.getName().replace(".", "/")+";", null); - mv.visitVarInsn(ALOAD, 0); // Load "this" reference - mv.visitMethodInsn(INVOKESPECIAL, target.getSuperclass().getName().replace(".", "/"), "<init>", "()V", false); - mv.visitInsn(RETURN); - mv.visitMaxs(1, 1); - mv.visitEnd(); - // Define field - cw.visitField(ACC_PUBLIC, name, "L"+toInject.getClass().getName().replace(".", "/")+";", null, toInject).visitEnd(); - - // Finish modifications - cw.visitEnd(); - - try{ - Method m = ClassLoader.class.getDeclaredMethod("defineClass", String.class, byte[].class, int.class, int.class); - m.setAccessible(true); - byte[] b; - return (Class<T>) m.invoke(target.getClassLoader(), target.getSimpleName(), b=cw.toByteArray(), 0, b.length); // Redefine class - }catch(Exception e){ e.printStackTrace(); } - throw new RuntimeException("Something went very wrong"); - } -} diff --git a/src/com/tofvesson/hacks/Reloader.java b/src/com/tofvesson/hacks/Reloader.java deleted file mode 100644 index d0408ca..0000000 --- a/src/com/tofvesson/hacks/Reloader.java +++ /dev/null @@ -1,49 +0,0 @@ -package com.tofvesson.hacks; - -import sun.misc.Unsafe; -import java.lang.reflect.Field; -import java.util.ArrayList; -import java.util.List; -import static java.lang.reflect.Modifier.STATIC; - -public class Reloader { - private static final List<Object> reload = new ArrayList<>(); - public void reloadAll(){} - public void reloadClasses(Class<?>... c) throws ClassNotFoundException { - final boolean[] b = {false}; - reload.stream().filter(o->{ - for(Class<?> c1 : c) b[0] = b[0] || (b[0]= o!=null && c1.isAssignableFrom(o.getClass())); - return b[0]; - }); // Check if class needs reloading - if(!b[0]) return; - Unsafe u = null; - try { - Field f = Unsafe.class.getDeclaredField("theUnsafe"); - f.setAccessible(true); - u = (Unsafe) f.get(null); - } catch (Exception ignored) {} - if(u==null) throw new RuntimeException("Something went very wrong! Unsafe reference is null."); - List<Object> reloaded = new ArrayList<>(); - reload.stream().filter(o->{ - for(Class<?> c1 : c) if(c1.isAssignableFrom(o.getClass())) return true; - return false; - }).forEach(reloaded::add); // Move all objects to be reloaded to a holder - reload.removeAll(reloaded); - for(Class<?> c1 : c) c1.getClassLoader().loadClass(c1.getName()); // Re load class in classloader - for(Object o : reloaded){ - try{ - Class<?> reloadedClass = Class.forName(o.getClass().getName()); - Object o1 = u.allocateInstance(reloadedClass); - for(Field f : o.getClass().getDeclaredFields()){ - f.setAccessible(true); - try{ - Field f1 = reloadedClass.getDeclaredField(f.getName()); - f1.setAccessible(true); - f1.set((f1.getModifiers()&STATIC)==STATIC?null:o1, f.get((f.getModifiers()&STATIC)==STATIC?null:o)); - }catch(Exception ignored){} - } - - }catch(Exception ignored){} - } - } -}