Instrumentation的所有方法
void addTransformer(ClassFileTransformer transformer, boolean canRetransform)//注册ClassFileTransformer实例,注册多个会按照注册顺序进行调用。所有的类被加载完毕之后会调用ClassFileTransformer实例,相当于它们通过了redefineClasses方法进行重定义。布尔值参数canRetransform决定这里被重定义的类是否能够通过retransformClasses方法进行回滚。
void addTransformer(ClassFileTransformer transformer)//相当于addTransformer(transformer, false),也就是通过ClassFileTransformer实例重定义的类不能进行回滚。
boolean removeTransformer(ClassFileTransformer transformer)//移除(反注册)ClassFileTransformer实例。
void retransformClasses(Class<?>... classes)//已加载类进行重新转换的方法,重新转换的类会被回调到ClassFileTransformer的列表中进行处理。
void appendToBootstrapClassLoaderSearch(JarFile jarfile)//将某个jar加入到Bootstrap Classpath里优先其他jar被加载。
void appendToSystemClassLoaderSearch(JarFile jarfile)//将某个jar加入到Classpath里供AppClassloard去加载。
Class[] getAllLoadedClasses()//获取所有已经被加载的类。
Class[] getInitiatedClasses(ClassLoader loader)//获取所有已经被初始化过了的类。
long getObjectSize(Object objectToSize)//获取某个对象的(字节)大小,注意嵌套对象或者对象中的属性引用需要另外单独计算。
boolean isModifiableClass(Class<?> theClass)//判断对应类是否被修改过。
boolean isNativeMethodPrefixSupported()//是否支持设置native方法的前缀。
boolean isRedefineClassesSupported()//返回当前JVM配置是否支持重定义类(修改类的字节码)的特性。
boolean isRetransformClassesSupported()//返回当前JVM配置是否支持类重新转换的特性。
void redefineClasses(ClassDefinition... definitions)//重定义类,也就是对已经加载的类进行重定义,ClassDefinition类型的入参包括了对应的类型Class<?>对象和字节码文件对应的字节数组。
void setNativeMethodPrefix(ClassFileTransformer transformer, String prefix)//设置某些native方法的前缀,主要在找native方法的时候做规则匹配。
对controller插入代码
package io.ct.java.agent;
import io.ct.java.agent.annotation.ClassScaner;
import javassist.ClassPool;
import javassist.CtClass;
import javassist.CtMethod;
import java.io.ByteArrayInputStream;
import java.lang.instrument.ClassFileTransformer;
import java.lang.instrument.IllegalClassFormatException;
import java.lang.instrument.Instrumentation;
import java.security.ProtectionDomain;
import java.util.HashMap;
import java.util.Map;
public class MyAgent {
public static void premain(String agentArgs, Instrumentation inst) throws Exception {
System.out.println("----------start----------");
inst.addTransformer(new ClassFileTransformer() {
@Override
public byte[] transform(ClassLoader loader, String className, Class<?> classBeingRedefined,
ProtectionDomain protectionDomain, byte[] classfileBuffer) throws IllegalClassFormatException {
/*
* 扫描所有的类
* */
if(className.contains("com/springboot/controller")){
System.out.println(className);
// 获取一个 class 池。
ClassPool classPool = ClassPool.getDefault();
try {
// 创建一个新的 class 类。classfileBuffer 就是当前class的字节码
CtClass ctClass = classPool.makeClass(new ByteArrayInputStream(classfileBuffer));
CtClass cc = classPool.get("com.springboot.controller.GoodsController");
if(cc.isFrozen()){
cc.defrost();
}
// 插入新内容
CtMethod[] personFly = cc.getDeclaredMethods();
for (CtMethod ctMethod : personFly) {
ctMethod.insertBefore("System.out.println(\"起飞之前准备降落伞\");");
ctMethod.insertBefore("System.out.println(\"执行公共的东西\");");
}
// 返回新的字节码
return ctClass.toBytecode();
} catch (Exception e) {
e.printStackTrace();
}
}
return new byte[0];
}
});
}
}
版权声明:本文为lepgon原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。