Skip to content

Instantly share code, notes, and snippets.

@raphw
Created June 2, 2018 11:07
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save raphw/00ce640762eea23ab3301a6b9c387ca4 to your computer and use it in GitHub Desktop.
Save raphw/00ce640762eea23ab3301a6b9c387ca4 to your computer and use it in GitHub Desktop.
Twist transformer order
package sun.instrument;
import net.bytebuddy.agent.ByteBuddyAgent;
import net.bytebuddy.agent.builder.AgentBuilder;
import net.bytebuddy.asm.Advice;
import net.bytebuddy.description.type.TypeDescription;
import net.bytebuddy.dynamic.DynamicType;
import net.bytebuddy.implementation.StubMethod;
import net.bytebuddy.implementation.bytecode.assign.Assigner;
import net.bytebuddy.utility.JavaModule;
import java.lang.instrument.ClassFileTransformer;
import java.lang.reflect.Array;
import java.lang.reflect.Constructor;
import java.lang.reflect.Method;
import java.security.ProtectionDomain;
import java.util.ArrayList;
import java.util.List;
import static net.bytebuddy.matcher.ElementMatchers.*;
public class Experiment {
@Advice.OnMethodExit
static void exit(@Advice.FieldValue(value = "mTransformerList", readOnly = false, typing = Assigner.Typing.DYNAMIC) Object[] mTransformerList,
@Advice.This TransformerManager manager,
@Advice.Argument(0) ClassFileTransformer transformer) throws Exception {
Class<?> info = Class.forName("sun.instrument.TransformerManager$TransformerInfo");
Method getTransformer = info.getDeclaredMethod("transformer");
getTransformer.setAccessible(true);
Object[] newList = (Object[]) Array.newInstance(info, mTransformerList.length + 1);
List<Object> delayed = new ArrayList<Object>();
int index = 0;
for (Object element : mTransformerList) {
Class<?>[] ifaces = getTransformer.invoke(element).getClass().getInterfaces();
if (ifaces.length > 0 && ifaces[0].getSimpleName().equals("PrivTransformer")) {
delayed.add(element);
} else {
newList[index++] = element;
}
}
Constructor<?> make = info.getDeclaredConstructor(TransformerManager.class, ClassFileTransformer.class);
make.setAccessible(true);
Class<?>[] ifaces = transformer.getClass().getInterfaces();
boolean priv = ifaces.length > 0 && ifaces[0].getSimpleName().equals("PrivTransformer");
if (!priv) {
newList[index++] = make.newInstance(manager, transformer);
}
for (Object element : delayed) {
newList[index++] = element;
}
if (priv) {
newList[index] = make.newInstance(manager, transformer);
}
mTransformerList = newList;
}
public static void main(String[] args) throws Exception {
new AgentBuilder.Default()
.with(AgentBuilder.RedefinitionStrategy.RETRANSFORMATION)
.disableClassFormatChanges()
.ignore(none())
.type(is(TransformerManager.class))
.transform(new AgentBuilder.Transformer() {
@Override
public DynamicType.Builder<?> transform(DynamicType.Builder<?> builder,
TypeDescription typeDescription,
ClassLoader classLoader,
JavaModule module) {
return builder.method(named("addTransformer")).intercept(Advice.to(Experiment.class).wrap(StubMethod.INSTANCE));
}
}).installOn(ByteBuddyAgent.install());
ByteBuddyAgent.install().retransformClasses(TransformerManager.class);
ByteBuddyAgent.install().addTransformer(new PrivTransformer() {
@Override
public byte[] transform(ClassLoader loader,
String className,
Class<?> classBeingRedefined,
ProtectionDomain protectionDomain,
byte[] classfileBuffer) {
System.out.println("foo");
return null;
}
}, true);
ByteBuddyAgent.install().addTransformer(new ClassFileTransformer() {
@Override
public byte[] transform(ClassLoader loader,
String className,
Class<?> classBeingRedefined,
ProtectionDomain protectionDomain,
byte[] classfileBuffer) {
System.out.println("bar");
return null;
}
}, true);
ByteBuddyAgent.install().addTransformer(new ClassFileTransformer() {
@Override
public byte[] transform(ClassLoader loader,
String className,
Class<?> classBeingRedefined,
ProtectionDomain protectionDomain,
byte[] classfileBuffer) {
System.out.println("qux");
return null;
}
}, true);
System.out.println("Loading bar...");
Class.forName("Bar");
}
interface PrivTransformer extends ClassFileTransformer { }
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment