Created
April 29, 2016 12:49
-
-
Save ChristianSchwarz/1b597889026ee0701ff3d8c870c5320c to your computer and use it in GitHub Desktop.
ByteBuddy+JavaAssist
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| package agh; | |
| public final class MyFinalType implements Processor<String> { | |
| @Override | |
| public final void process(String message) { | |
| }; | |
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| package agh; | |
| public interface Processor<T> { | |
| void process(T message); | |
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| package agh; | |
| import static java.lang.Thread.currentThread; | |
| import static javassist.Modifier.FINAL; | |
| import static net.bytebuddy.matcher.ElementMatchers.named; | |
| import java.io.IOException; | |
| import java.util.concurrent.Callable; | |
| import javassist.CannotCompileException; | |
| import javassist.ClassPool; | |
| import javassist.CtClass; | |
| import javassist.CtMethod; | |
| import javassist.NotFoundException; | |
| import net.bytebuddy.ByteBuddy; | |
| import net.bytebuddy.dynamic.loading.ClassLoadingStrategy; | |
| import net.bytebuddy.implementation.MethodDelegation; | |
| import com.esotericsoftware.reflectasm.FieldAccess; | |
| import com.esotericsoftware.reflectasm.MethodAccess; | |
| public class Rewrite implements Callable<Void> { | |
| public MyFinalType t; | |
| @Override | |
| public Void call() throws Exception { | |
| ClassLoader cl = currentThread().getContextClassLoader(); | |
| Class<?> myFinalType = removeFinal("agh.MyFinalType", cl); | |
| MyFinalType p; | |
| p = (MyFinalType) new ByteBuddy()// | |
| .subclass(myFinalType)// | |
| .method(named("process"))// | |
| .intercept(MethodDelegation.to(TargetImpl.class))// | |
| .make()// | |
| .load(cl, ClassLoadingStrategy.Default.WRAPPER)// | |
| .getLoaded()// | |
| .newInstance(); | |
| FieldAccess f = FieldAccess.get(Rewrite.class); | |
| int fieldIndex = f.getIndex("t"); | |
| f.set(this, fieldIndex, p); | |
| return null; | |
| } | |
| public static void main(String[] args) throws Exception { | |
| new Rewrite().call(); | |
| } | |
| private static <T> Class<T> removeFinal(String classname, ClassLoader classLoader) throws ClassNotFoundException { | |
| CtClass ctClass = getCtClass(classname, classLoader); | |
| removeFinal(ctClass); | |
| removeFinal(ctClass.getMethods()); | |
| return load(ctClass, classLoader); | |
| } | |
| private static void removeFinal(CtClass ctClass) { | |
| int modifiers = ctClass.getModifiers(); | |
| modifiers &= ~FINAL; | |
| ctClass.setModifiers(modifiers); | |
| } | |
| private static void removeFinal(CtMethod[] methods) { | |
| for (CtMethod m : methods) { | |
| int modifiers = m.getModifiers(); | |
| modifiers &= ~FINAL; | |
| m.setModifiers(modifiers); | |
| } | |
| } | |
| private static CtClass getCtClass(String classname, ClassLoader classLoader) throws ClassNotFoundException { | |
| ClassPool pool = ClassPool.getDefault(); | |
| CtClass ctClass; | |
| try { | |
| ctClass = pool.get(classname); | |
| } catch (NotFoundException e) { | |
| throw new ClassNotFoundException("Class not found '" + classname + "' using classloader " + classLoader, e); | |
| } | |
| return ctClass; | |
| } | |
| private static <T> Class<T> load(CtClass ctClass, ClassLoader classLoader) { | |
| try { | |
| return (Class<T>) ctClass.toClass(classLoader, null); | |
| } catch (CannotCompileException e) { | |
| throw new IllegalStateException(e); | |
| } | |
| } | |
| public static class TargetImpl { | |
| public static void process(Object text) { | |
| System.out.println(text); | |
| } | |
| } | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment