`

使用ASM4.0实现AOP的功能,监控每个方法的执行时间

 
阅读更多

接之前的博客http://zhwj184.iteye.com/admin/blogs/1630756 关于asm使用的示例,这次使用asm来动态统计每个方法的执行时间,实现AOP功能。

AOP的更通用的做法是对原始类动态生成子类,调用子类的方法覆盖父类,来实现AOP的功能。著名的 Hibernate 和 Spring 框架,就是使用这种技术实现了 AOP 的“无损注入”。

 

下面我们就通过一个示例来对方法Foo.execute调用时动态注入方法执行前后的时间统计来统计方法的执行时间

 

 

import java.io.FileOutputStream;
import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

import org.objectweb.asm.ClassReader;
import org.objectweb.asm.ClassVisitor;
import org.objectweb.asm.ClassWriter;
import org.objectweb.asm.MethodVisitor;
import org.objectweb.asm.Opcodes;

public class AsmAopExample extends ClassLoader implements Opcodes{
    
    public static  class Foo {
        public static void execute() {
            System.out.println("test changed method name");
            try {
                Thread.sleep(10);
            } catch (InterruptedException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }
    }
    
    public static class Monitor{
        
        static long start = 0;
        
        public static void start(){
            start = System.currentTimeMillis();
        }
        public static void end(){
            long end = System.currentTimeMillis();
            System.out.println("execute method use time :" + (end - start));
        }
    }

    public static void main(String[] args) throws IOException, IllegalArgumentException, SecurityException, IllegalAccessException, InvocationTargetException {
        
        ClassReader cr = new ClassReader(Foo.class.getName());
        ClassWriter cw = new ClassWriter(cr, ClassWriter.COMPUTE_MAXS);
        ClassVisitor cv = new MethodChangeClassAdapter(cw);
        cr.accept(cv, Opcodes.ASM4);

        // gets the bytecode of the Example class, and loads it dynamically
        byte[] code = cw.toByteArray();


        AsmAopExample loader = new AsmAopExample();
        Class<?> exampleClass = loader.defineClass(Foo.class.getName(), code, 0, code.length);

        for(Method method:  exampleClass.getMethods()){
            System.out.println(method);
        }
        
        exampleClass.getMethods()[0].invoke(null, null);  //調用execute,修改方法內容
        
        
        // gets the bytecode of the Example class, and loads it dynamically

        FileOutputStream fos = new FileOutputStream("e:\\logs\\Example.class");
        fos.write(code);
        fos.close();
    }
    
    static class MethodChangeClassAdapter extends ClassVisitor implements Opcodes {

        public MethodChangeClassAdapter(final ClassVisitor cv) {
            super(Opcodes.ASM4, cv);
        }

        @Override
        public MethodVisitor visitMethod(
            int access,
            String name,
            String desc,
            String signature,
            String[] exceptions)
        {
            if("execute".equals(name))  //此处的execute即为需要修改的方法  ,修改方法內容
            {  
                MethodVisitor mv = cv.visitMethod(access, name, desc, signature, exceptions);//先得到原始的方法  
                MethodVisitor newMethod = null;  
                newMethod = new AsmMethodVisit(mv); //访问需要修改的方法  
                return newMethod;  
            }  
            
            return null;
        }


    }
    
     static  class AsmMethodVisit extends MethodVisitor {

        public AsmMethodVisit(MethodVisitor mv) {
            super(Opcodes.ASM4, mv);    
        }
        
        @Override
        public void visitCode() {       
            //此方法在访问方法的头部时被访问到,仅被访问一次
            visitMethodInsn(Opcodes.INVOKESTATIC, Monitor.class.getName(),  "start", "()V"); 
            super.visitCode();
            
        }
        
        @Override
        public void visitInsn(int opcode) {     
            //此方法可以获取方法中每一条指令的操作类型,被访问多次
            //如应在方法结尾处添加新指令,则应判断:
            if(opcode == Opcodes.RETURN)
            {
                visitMethodInsn(Opcodes.INVOKESTATIC, Monitor.class.getName(),  "end", "()V"); 
            }
            super.visitInsn(opcode);
        }  
        
    }

}

 

 

输出:

 

 

public static void AsmAopExample$Foo.execute()
public native int java.lang.Object.hashCode()
public final native java.lang.Class java.lang.Object.getClass()
public final void java.lang.Object.wait(long,int) throws java.lang.InterruptedException
public final void java.lang.Object.wait() throws java.lang.InterruptedException
public final native void java.lang.Object.wait(long) throws java.lang.InterruptedException
public boolean java.lang.Object.equals(java.lang.Object)
public java.lang.String java.lang.Object.toString()
public final native void java.lang.Object.notify()
public final native void java.lang.Object.notifyAll()
test changed method name
execute method use time :10

 

 

可以看到在execute方法中sleep 10ms,这里打印出来也是10ms,这里是在execute方法执行前先调用monitor.start()方法,方法返回是调用monitor的end方法,从而达到统计的功能,不过这里只是一个示例,如果要统计每个方法的执行时间,统计并发进行方法统计时这里当然要进行扩展,不过思路差不多就是这样。

 

 

我们查下最终生成的Foo类的class文件通过反射后的源代码:

 

import java.io.PrintStream;

public class AsmAopExample$Foo
{
  public static void execute()
  {
    AsmAopExample.Monitor.start(); System.out.println("test changed method name");
    try {
      Thread.sleep(10L);
    }
    catch (InterruptedException e) {
      e.printStackTrace();
    }
    AsmAopExample.Monitor.end();
  }
}

 

大家可以参考这里的一篇比较全的文章:http://www.ibm.com/developerworks/cn/java/j-lo-asm30/

0
1
分享到:
评论

相关推荐

    ASM4.0 中文教程与多种字节码编程实战案例

    内容包含ASM4.0中文手册,以及四种ASM常见的字节码操作应用范例,包含最新版本的ASM9.2的jar包,包含asm-9.2.jar,asm-commons-9.2.jar,asm-util-9.2.jar。 学习文章地址 ...

    asm4.0全家福

    标题中的“asm4.0全家福”指的是ASM库的一个完整版本集合,ASM是一个Java字节码操控和分析框架,主要用于动态生成类或者增强已有类的功能。这个“全家福”包括了ASM库的主要组件,分别是: 1. **asm-4.0**: 这是ASM...

    asm4.0_RC1-bin

    ASM是一个强大的Java字节码操控...总的来说,ASM4.0_RC1是一个强大的工具,为Java开发者提供了一种底层操控字节码的方式,使得在运行时生成和修改类成为可能,从而在诸如AOP、插件系统、代码生成等领域具有广泛的应用。

    asm-tree-4.0.zip_asm4.0

    标题中的"asm-tree-4.0.zip_asm4.0"提到了ASM库的特定版本,ASM是一个Java字节码操控和分析框架,主要用于动态代理、字节码转换以及代码分析等场景。ASM 4.0是这个库的一个版本,可能包含了一些针对性能和功能的改进...

    ASM4使用指南 - ASM 4 Guide 中文版

    ASM 4 使用指南中文版。ASM是Java字节码的工业级库。长期以来一直没有中文版。这下好了,中文版横空出世。感兴趣的同学可以投递简历 mars # oneapm . com 常年有效 ASM 4.0 A Java bytecode engineering library

    深入字节码 -- 使用 ASM 实现 AOP1

    3. **创建 MethodVisitor**:针对每个方法,我们需要创建一个 MethodVisitor 对象,通过重写其方法,实现在字节码级别插入新的指令。 4. **插入切面代码**:在适当的位置,比如方法调用前(Advice Before)和调用后...

    spring-asm-repack-4.0.jar

    spring 3.2.5版本源码使用的,构建的时候使用如下描述 因为英文不太好,大概意思可能是什么asm4.0版本使用的spring 在spring4中已经重新包装了asm在spring-core的核心包里,当然我这解释不标准 看下满原文构建的描述...

    asm-util-4.0_RC1.jar.zip

    标题中的"asm-util-4.0_RC1.jar.zip"是一个归档文件,它是一个ZIP格式的压缩包,其中包含了ASM工具库的一个特定版本——ASM Util 4.0 Release Candidate 1(RC1)。ASM是一个Java字节码操控和分析框架,广泛用于动态...

    asm-all-4.0.jar.zip

    ASM库广泛应用于字节码级别的编程,例如在Java代理、代码混淆、性能监控以及动态语言实现等领域。 描述中提到了“asm, all, 4.0, jar.zip包下载, 依赖包”,这进一步解释了这个压缩包的内容。"asm"是指ASM库本身,...

    AOP 的利器 ASM 3.0

    下面通过一个具体的示例来展示如何使用ASM进行AOP的实现: 1. **创建一个安全检查类**: ```java public class SecurityChecker { public static void checkSecurity() { System.out.println("SecurityChecker....

    asm-4.0.jar

    asm-4.0.jar

    asm-all-4.0.jar

    4. **框架实现**:许多框架如Hibernate、Spring等,都使用ASM来实现元编程,动态生成类和方法。 ASM-4.0作为其重要版本,引入了一些新特性和改进: - 提高了API的易用性,使得开发者更容易地进行字节码操作。 - ...

    asm操作指南(中文)

    - **定义与功能**:ASM是一个Java字节码操纵框架,主要用于动态生成类或增强现有类的功能。通过直接生成二进制`.class`文件,ASM能够在类被加载到Java虚拟机之前动态地改变类的行为。 - **应用场景**: - **程序...

    JavaEE CGLIB字节码增强方式实现AOP编程

    JavaEE CGLIB字节码增强技术是实现面向切面编程(AOP)的一种常见方法。在JavaEE应用中,AOP允许开发者定义“切面”,这些切面封装了跨越多个对象的横切关注点,如日志、事务管理等。CGLIB(Code Generation Library...

    ASM函数监听实现(三)拦截注入函数的参数值 (函数执行前)

    ASM库是一个轻量级的Java字节码操控和分析框架,常用于动态代理、代码生成以及AOP实现。本篇文章将深入探讨如何使用ASM库来实现函数监听,特别是如何在函数执行前拦截并改变其参数值。 首先,我们需要理解ASM库的...

    asm-4.0_RC1.jar.zip

    "asm-4.0_RC1.jar.zip" 是ASM库的4.0_RC1版本的压缩包,其中包含ASM的主要实现类和接口。 这个版本的ASM主要提供了以下几个方面的功能: 1. **字节码解析**:ASM能够解析Java字节码,将其转化为一棵抽象语法树...

    Java字节码实现Aop

    Java字节码实现AOP(面向切面编程)是一种在程序运行时动态插入代码的技术,它使得我们可以在不修改原有代码的情况下,增加新的功能或监控已有功能。在Java中,AOP通常通过代理模式和字节码操作来实现,如Spring AOP...

    Android-Android无痕埋点框架使用ASM插桩实现

    在这个适配器中,我们需要重写visitMethod方法,该方法会在遇到类的每个方法时被调用。 2. **检测目标方法**: 在visitMethod方法内,我们需要根据业务需求,识别出需要插入埋点代码的目标方法。这可以通过方法名、...

    asm-4.2-API文档-中文版.zip

    赠送jar包:asm-4.2.jar; 赠送原API文档:asm-4.2-javadoc.jar; 赠送源代码:asm-4.2-sources.jar; 赠送Maven依赖信息文件:asm-4.2.pom; 包含翻译后的API文档:asm-4.2-javadoc-API文档-中文(简体)版.zip; ...

Global site tag (gtag.js) - Google Analytics