一、静态代理Agent
1.生成Agent的jar包
(1)创建Agent项目,引入javassist.jar包
(2)编写premain方法
import java.lang.instrument.Instrumentation;
public class Agent1 {
public static void premain(String agentArgs, Instrumentation inst) {
System.out.println("agentArgs : " + agentArgs);
MyAgentTransfer trans = new MyAgentTransfer();
MyAgentTransferboot trans_boot = new MyAgentTransferboot();
inst.addTransformer(trans, true);
inst.addTransformer(trans_boot, true);
}
}
(3)创建MyAgentTransferboot类,实现ClassFileTransformer接口,重写transform方法
import java.lang.instrument.ClassFileTransformer;
import java.lang.instrument.IllegalClassFormatException;
import java.security.ProtectionDomain;
import javassist.CannotCompileException;
import javassist.ClassPool;
import javassist.CodeConverter;
import javassist.CtClass;
import javassist.CtMethod;
import javassist.NotFoundException;
import javassist.expr.ExprEditor;
import javassist.expr.MethodCall;
public class MyAgentTransferboot implements ClassFileTransformer{
/** ClassLoader loader: 类加载器,用于加载当前类的类。 String className: 正在加载的类的名称(用斜杠分隔的形式,例如 java/lang/String)。
Class<?> classBeingRedefined: 如果这个类正在被重新定义,则为其对应的 Class 对象;否则为 null。 ProtectionDomain protectionDomain: 类的保护域,提供关于类的安全权限的信息。
byte[] classfileBuffer: 原始的字节码数组。 */
@Override
public byte[] transform(ClassLoader loader, String className,
Class<?> classBeingRedefined, ProtectionDomain protectionDomain,
byte[] classfileBuffer) throws IllegalClassFormatException {
byte[] transformed = null;
// System.out.println("Transforming className::" + className);
if(!className.contains("TaxController") || !className.contains("")) {
return classfileBuffer;
}
ClassPool pool = null;
CtClass cl = null;
try {
pool = ClassPool.getDefault();
cl = pool.makeClass(new java.io.ByteArrayInputStream(classfileBuffer));
// CtMethod aop_method = pool.get("com.jdktest.instrument.AopMethods").
// getDeclaredMethod("aopMethod");
// System.out.println(aop_method.getLongName());
CodeConverter convert = new CodeConverter();
if (cl.isInterface() == false) {
CtMethod[] methods = cl.getDeclaredMethods();
for (int i = 0; i < methods.length; i++) {
if (methods[i].isEmpty() == false) {
// AOPInsertMethod(methods[i]);
if(methods[i].getName().contains("getUrl") ) {
System.out.println("methods[i].getName::" + methods[i].getName());
String name = methods[i].getName();
methods[i].insertAt(92, "System.out.println(\"---------------Url:\" + Url);");
// methods[i].insertBefore(" System.out.println(\"TTTTTTTTTTTTTTTTTT**********************************************" +name + "\");");
// methods[i].insertBefore(" return \"100\";");
}
}
}
transformed = cl.toBytecode();
}
} catch (Exception e) {
System.err.println("Could not instrument " + className
+ ", exception : " + e.getMessage());
} finally {
if (cl != null) {
cl.detach();
}
}
return transformed;
}
private void AOPInsertMethod(CtMethod method) throws NotFoundException,CannotCompileException {
method.instrument(new ExprEditor() {
@Override
public void edit(MethodCall m) throws CannotCompileException {
m.replace("{ long stime = System.currentTimeMillis(); $_ = $proceed($$);System.out.println(\""
+ m.getClassName() + "." + m.getMethodName()
+ " cost:\" + (System.currentTimeMillis() - stime) + \" ms\");}");
}
});
// method.insertBefore("System.out.println(\"enter method\");");
// method.insertAfter("System.out.println(\"leave method\");");
}
(4)将Agent项目进行打包
(5)用压缩包方式打开生成的jar包,打开\META-INF\MANIFEST.MF文件,添加如下代码:
Can-Redefine-Classes: true
Can-Retransform-Classes: true
Premain-Class: com.javaAgent.Agent1
2.在项目中使用agent
命令:-javaagent:jar包地址=参数
如:-javaagent:D:\Work_Code\javaAgent\StringLenAgent.jar=‘1’
-javaagent:D:\Work_Code\javaAgent\StringLenAgent.jar
二、动态代理Attach
1.生成Attach的jar包
(1)创建Attach项目,引入javassist.jar包、com.sun.tools.attach-1.8.0_jdk8u172-b11.jar包
(2)编写agentmain方法
import javassist.ClassPool;
import javassist.CtClass;
import javassist.CtMethod;
public class Attach1 {
public static void agentmain(String attachArgs, Instrumentation instrumentation) {
System.out.println("attach agentmain启动");
System.out.println("attachArgs : " + attachArgs);
Class<?>[] classes = instrumentation.getAllLoadedClasses();
for (Class<?> cls : classes) {
String className = cls.getName();
if(className.contains("TaxController")) {
CtClass ctClass;
try {
ClassPool classPool = ClassPool.getDefault();
ctClass = classPool.get(className);
CtMethod[] methods = ctClass.getDeclaredMethods();
for (int i = 0; i < methods.length; i++) {
if (methods[i].isEmpty() == false) {
// AOPInsertMethod(methods[i]);
if(methods[i].getName().contains("getUrl") ) {
System.out.println("methods[i].getName::" + methods[i].getName());
String name = methods[i].getName();
methods[i].insertAt(92, "System.out.println(\"---------------Url:\" + Url);");
// methods[i].insertBefore(" System.out.println(\"TTTTTTTTTTTTTTTTTT**********************************************" +name + "\");");
// methods[i].insertBefore(" return \"100\";");
}
}
}
ClassDefinition classDefinition = new ClassDefinition(cls, ctClass.toBytecode());
instrumentation.redefineClasses(classDefinition);
} catch (Throwable e) {
System.out.println(e.getMessage());
e.printStackTrace();
}
}
(3)将Attach项目进行打包
(4)用压缩包方式打开生成的jar包,打开\META-INF\MANIFEST.MF文件,添加如下代码:
Agent-Class: com.javaAttach.Attach1
Can-Redefine-Classes: true
Can-Retransform-Classes: true
(5)启动需被代理的应用程序
编写main方法,给需被代理的应用程序添加代理
import java.util.concurrent.TimeUnit;
import com.sun.tools.attach.*;
public class AttachUseMain {
public static void main(String[] args) throws Exception{
System.out.println("AttachUseMain启动");
long start = System.currentTimeMillis();
System.out.println(start);
for (VirtualMachineDescriptor vmd : VirtualMachine.list()) {
String name = vmd.displayName();
System.out.println(name + ":" + vmd.id());
if (name.contains("Application")) {
VirtualMachine vm = VirtualMachine.attach(vmd.id());
// vm.loadAgent("D:\\Work_Code\\javaAgent\\StringLenAttach.jar=hello,ok,aa,bb,cc=3");
vm.loadAgent("D:\\Work_Code\\javaAgent_1\\javaAttach\\StringLenAttach004.jar=22");
TimeUnit.MINUTES.sleep(1);
vm.detach();
System.out.println("Agent 已成功附加到目标 JVM");
}
}
long end = System.currentTimeMillis();
System.out.println(end - start);
// String targetPid = "25304"; //jps -l
// // 指定要附加的 Agent JAR 路径
// String agentPath = "D:\\Work_Code\\javaAgent\\StringLenAttach.jar";
//
// // 附加到目标 JVM
// VirtualMachine vm = VirtualMachine.attach(targetPid);
// // 加载 Agent
// vm.loadAgent(agentPath);
// // 断开连接
// vm.detach();
System.out.println("over");
}
}