ASM函数监听实现-之简单静态方法注入
来源:互联网 发布:matlab 如何遍历数组 编辑:程序博客网 时间:2024/05/16 17:37
1.目的:实现对函数执行监听,在函数调用前,后得到通知。考虑用asm来实现。
2.资料:在网上看到关于asm的技术资料,写了一个简单的实现。参考链接如下:
http://www.cnblogs.com/eafy/archive/2008/06/18/1224633.html
http://alvinqq.iteye.com/blog/940965
http://www.ibm.com/developerworks/cn/java/j-lo-asm30/
http://ayufox.iteye.com/blog/668917
3.代码:asmAopClassAdapter 该类对目标类进行操作。
asmAopMethodAdapter 对目标类的方法做操作。
ChangeToChildConstructorMethodAdapter该类生成目标类的子类。
asmAopGenerator 一个工具类,生成代理目标类的对象。
asmAopInvoker 函数注入类
测试类
输出结果
4.目的基本达成。
5.待改进,在监听函数执行后,是用的try和catch抛异常的方式来实现。
2.资料:在网上看到关于asm的技术资料,写了一个简单的实现。参考链接如下:
http://www.cnblogs.com/eafy/archive/2008/06/18/1224633.html
http://alvinqq.iteye.com/blog/940965
http://www.ibm.com/developerworks/cn/java/j-lo-asm30/
http://ayufox.iteye.com/blog/668917
3.代码:asmAopClassAdapter 该类对目标类进行操作。
- public class asmAopClassAdapter extends ClassAdapter{
- private String enhancedSuperName,enhancedName;
- private String method;
- private String startInfo,endInfo;
- public asmAopClassAdapter(ClassVisitor cv,String methodName,String start,String end) {
- //Responsechain 的下一个 ClassVisitor,这里我们将传入 ClassWriter,
- // 负责改写后代码的输出
- super(cv);
- method = methodName;
- startInfo = start;
- endInfo = end;
- }
- // 重写 visitMethod,访问到 "method" 方法时,
- // 给出自定义 MethodVisitor,实际改写方法内容
- public MethodVisitor visitMethod(final int access, final String name,
- final String desc, final String signature, final String[] exceptions) {
- MethodVisitor mv = cv.visitMethod(access, name, desc, signature, exceptions);
- MethodVisitor wrappedMv = mv;
- if (mv != null) {
- if (name.equals(method)) {
- wrappedMv = new asmAopMethodAdapter(mv,startInfo,endInfo);
- } else if (name.equals("<init>")) {
- wrappedMv = new ChangeToChildConstructorMethodAdapter(mv,
- enhancedSuperName);
- }
- }
- return wrappedMv;
- }
- public void visit(final int version, final int access, final String name,
- final String signature, final String superName,
- final String[] interfaces) {
- enhancedName = name.replace("/", "$")+"$EnhancedByASM"; // 改变类命名
- enhancedSuperName = name; // 改变父类
- super.visit(version, access, enhancedName, signature,
- enhancedSuperName, interfaces);
- }
- public String getEnhancedName() {
- return enhancedName;
- }
- }
asmAopMethodAdapter 对目标类的方法做操作。
- public class asmAopMethodAdapter extends MethodAdapter implements Opcodes{
- private final static int EXCEPTION_STACK = 2 + 1;//max_stack至少需要能够容纳2个常量地址(监控方法使用)和1个exception地址
- private Label try_catch_start,try_catch_end;
- private String startInfo,endInfo;
- public asmAopMethodAdapter(MethodVisitor mv,String start,String end) {
- super(mv);
- try_catch_start = new Label();
- try_catch_end = new Label();
- startInfo = start;
- endInfo = end;
- }
- public void visitCode() {
- mv.visitCode();
- mv.visitLabel(try_catch_start);
- mv.visitLdcInsn(startInfo);
- //asmAopInvoker 这里写类的路径例如:com.asm.asmAopInvoker 应写成 com/asm/asmAopInvoker
- mv.visitMethodInsn(INVOKESTATIC, "asmAopInvoker",
- "methodStart", "(Ljava/lang/String;)V");
- }
- public void visitInsn(int opcode){
- if(opcode >= IRETURN && opcode <= RETURN){
- mv.visitLdcInsn(endInfo);
- //asmAopInvoker 这里写类的路径例如:com.asm.asmAopInvoker 应写成 com/asm/asmAopInvoker
- mv.visitMethodInsn(INVOKESTATIC, "asmAopInvoker",
- "methodEnd", "(Ljava/lang/String;)V");
- }
- mv.visitInsn(opcode);
- }
- public void visitEnd() {
- mv.visitLabel(try_catch_end);
- mv.visitTryCatchBlock(try_catch_start, try_catch_end, try_catch_end, null);
- mv.visitLdcInsn(endInfo);
- //asmAopInvoker 这里写类的路径例如:com.asm.asmAopInvoker 应写成 com/asm/asmAopInvoker
- mv.visitMethodInsn(INVOKESTATIC, "asmAopInvoker",
- "methodEnd", "(Ljava/lang/String;)V");
- mv.visitInsn(Opcodes.ATHROW);
- mv.visitEnd();
- }
- public void visitMaxs(int maxStack,int maxLocals){
- //保证max stack足够大
- mv.visitMaxs(Math.max(EXCEPTION_STACK,maxStack), maxLocals);
- }
- }
ChangeToChildConstructorMethodAdapter该类生成目标类的子类。
- public class ChangeToChildConstructorMethodAdapter extends MethodAdapter {
- private String superClassName;
- public ChangeToChildConstructorMethodAdapter(MethodVisitor mv,
- String superClassName) {
- super(mv);
- this.superClassName = superClassName;
- }
- public void visitMethodInsn(int opcode, String owner, String name,
- String desc) {
- // 调用父类的构造函数时
- if (opcode == Opcodes.INVOKESPECIAL && name.equals("<init>")) {
- owner = superClassName;
- }
- super.visitMethodInsn(opcode, owner, name, desc);// 改写父类为 superClassName
- }
- }
asmAopGenerator 一个工具类,生成代理目标类的对象。
- public class asmAopGenerator {
- private AOPGeneratorClassLoader classLoader ;
- public asmAopGenerator(){
- classLoader = new AOPGeneratorClassLoader();
- }
- public Object proxy(Class c,String methodName,String startInfo,String endInfo) {
- try{
- if( c != null){
- String classPach = c.toString().replace("/", ".");
- ClassReader cr = new ClassReader(classPach.substring(6,classPach.length()));
- ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_MAXS);
- asmAopClassAdapter classAdapter = new asmAopClassAdapter(cw,methodName,startInfo,endInfo);
- cr.accept(classAdapter, ClassReader.SKIP_DEBUG);
- byte[] data = cw.toByteArray();
- Class obj = classLoader.defineClassFromClassFile(classAdapter.getEnhancedName(), data);
- //TODO:隐藏BUG
- return obj.newInstance();
- }}catch(Exception e){
- e.printStackTrace();
- }
- return null;
- }
- class AOPGeneratorClassLoader extends ClassLoader {
- public Class defineClassFromClassFile(String className,
- byte[] classFile) throws ClassFormatError {
- return defineClass(className, classFile, 0,
- classFile.length);
- }
- }
- }
asmAopInvoker 函数注入类
- public class asmAopInvoker {
- public static void methodEnd(String evtID){
- System.out.println(evtID);
- }
- public static void methodStart(String evtID){
- System.out.println(evtID);
- }
- }
测试类
- public class helloWorld {
- public void sayHello(){
- System.out.println("helloWorld....");
- }
- public static void main(String[]args){
- asmAopGenerator aag = new asmAopGenerator();
- helloWorld hw = (helloWorld) aag.proxy(helloWorld.class, "sayHello", "it's begin", "it's end");
- hw.sayHello();
- }
- }
输出结果
- it's begin
- helloWorld....
- it's end
4.目的基本达成。
5.待改进,在监听函数执行后,是用的try和catch抛异常的方式来实现。
6.环境 asm 3.3.1 jdk 1.6.
转载:http://xkorey.iteye.com/blog/1551897
- ASM函数监听实现-之简单静态方法注入
- Asm实现静态AOP的两种方式-在进入方法和限出方法时注入代码实现aop代码增强
- PHP中实现生成静态文件之简单方法一
- 简单实现防止sql注入的方法
- c++之静态函数和静态方法
- 静态方法注入bean
- 用ASM实现GetProcAddress()函数
- spring注入的方式实现静态方法中使用非静态变量
- 多线程之静态同步函数/方法
- ORACLE监听之动态监听与静态监听特点
- ASM(四) 利用Method 组件动态注入方法逻辑
- 控制反转(IOC)、依赖注入(DI)之通过构造函数注入简单属性
- Python使用函数默认值实现函数静态变量的方法
- 事件监听简单通用方法
- Spring 之方法注入
- spring之构造函数注入属性值与set方法注入属性值
- 实现静态页面的一种非常简单的方法
- 【unity3d小技巧之三】添加自定义拓展,动态向某个类注入静态函数
- python property函数
- 饭卡 hdu 2546
- hdu 1049(1.2.3)
- Linux安装系统调用表更改模块时系统崩溃(unable to handle kernel paging request at XX)
- 进程间的通信-消息队列
- ASM函数监听实现-之简单静态方法注入
- 最大值最小化
- 实验4 [bx]和loop的使用——第二小题
- 常用的字符串加密和解密
- malloc与calloc
- JVM字节码初探--字节码
- adb介绍
- PythonChallenge 挑战之路 Level-29
- 三种基础的博弈知识和自己的小总结