Javaagent使用介绍 Java动态代理

2021-12-25 23:33:00
admin
原创 1938
摘要:Javaagent使用介绍 Java动态代理

一、Javaagent使用介绍

1、javaagent通过premain或angentmain方法注入java应用,从而影响应用执行,用于热部署或监控;

2、java应用可以加载多个代理,premain代理必须位于命令行参数的主类或-jar参数前面;

3、premain(String,Instrumentation)优先级高于premain(String),两个方法同时存在时执行前者;

4、agentmain(String,Instrumentation)优先级高agentmain(String),两个方法同时存在时执行前者;

5、代理包的MANIFEST文件必须包含Premain-Class或Agent-Class;


程序启动前注入:

程序启动前代理类:AgentStatic.java

程序启动前代理清单:agent-static.mf

测试程序:AgentTest.java


打包以及执行:

jar cvfm myagent1.jar agent-static.mf -C target\classes javaagent\AgentStatic.class

java -javaagent:myagent1.jar=myagent -classpath target\classes javaagent.AgentTest


执行输出:

AgentStatic::premain(String,Instrumentation)
myagent
main


程序启动后注入:

程序启动后代理类:AgentDynamic.java

程序启动后代理清单:agent-dynamic.mf

注入程序AttachApp.java


打包以及执行:

jar cvfm myagent2.jar agent-dynamic.mf -C target\classes javaagent\AgentDynamic.class

java -classpath "target\classes;%JAVA_HOME%\lib\tools.jar" javaagent.AttachApp pid myagent2.jar myagent


执行输出:

AgentDynamic::agentmain(String,Instrumentation)

myagent


二、Java动态代理

1、如果需要对接口进行代理,则使用JDK动态代理;

2、如果需要对类进行代理,则使用CGLib动态代理;

3、如果希望直接修改字节码,则使用Javassist动态代理;


JDK动态代理:

1、Proxy.newProxyInstance(loader,interfaces,h)生成代理对象,实现了被代理对象的接口;

2、代理对象所有方法实际调用InvocationHandler.invoke(proxy,method,args)

3、proxy是虚拟机生成的代理对象,method是被代理的方法,args是方法的参数;

4、InvocationHandler.invoke实际调用method.invoke(obj,args),obj是被代理对象;

5、sun.misc.ProxyGenerator.saveGeneratedFiles=true,代理类写入文件系统;

6、动态代理代码示例:ProxyDemo.java


CGLib动态代理:

1、Enhancer.setSuperclass(cls)设置需要代理的类;

2、Enhancer.setCallback(callback)设置代理处理逻辑;

3、Enhancer.create()生成代理对象,继承了被代理的类;

4、代理对象所有非static非final方法被重载,实际调用MethodInterceptor.intercept(proxy,method,args,methodProxy);

5、代理对象所有非static非final方法会新增方法methodname$0(),实际调用super.methodname();

6、CGLib同时会生成两个FastClass,一个调用methodname$0(),另外一个调用methodname();

7、MethodProxy.invokeSuper调用第一个FastClass,MethodProxy.invoke调用第二个FastClass;

8、动态代理代码示例:CGLibDemo.java


Javassist动态代理:

1、Javassist可以直接使用源代码来修改字节码,使用起来非常方便;

2、帮助指南:https://www.javassist.org/tutorial/tutorial.html

3、修改字节码示例:JavassistDemo.java

发表评论
评论通过审核之后才会显示。