- 浏览: 739888 次
- 性别:
- 来自: 杭州
文章分类
最新评论
-
lgh1992314:
a offset: 26b offset: 24c offse ...
java jvm字节占用空间分析 -
ls0609:
语音实现在线听书http://blog.csdn.net/ls ...
Android 语音输入API使用 -
wangli61289:
http://viralpatel-net-tutorials ...
Android 语音输入API使用 -
zxjlwt:
学习了素人派http://surenpi.com
velocity宏加载顺序 -
tt5753:
谢啦........
Lucene的IndexWriter初始化时的LockObtainFailedException的解决方法
接之前的博客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/
发表评论
-
对字符串进行验证之前先进行规范化
2013-09-17 23:18 13882对字符串进行验证之前先进行规范化 应用系统中经常对字 ... -
使用telnet连接到基于spring的应用上执行容器中的bean的任意方法
2013-08-08 09:17 1427使用telnet连接到基于spring的应用上执行容器中 ... -
jdk7和8的一些新特性介绍
2013-07-06 16:07 10067更多ppt内容请查看:htt ... -
java对于接口和抽象类的代理实现,不需要有具体实现类
2013-06-12 09:50 2905原文链接:http://www.javaarch.net/j ... -
Excel2007格式分析和XML解析
2013-06-07 09:56 10608在物料清单采购中,用到excel上传文件解析功能,不 ... -
Java EE 7中对WebSocket 1.0的支持
2013-06-05 09:27 3796原文链接:http://www.javaarch.n ... -
java QRCode生成示例
2013-06-05 09:26 1464原文链接:http://www.javaarch.n ... -
Java Web使用swfobject调用flex图表
2013-05-28 19:05 1078Java Web使用swfobject调用 ... -
spring使用PropertyPlaceholderConfigurer扩展来满足不同环境的参数配置
2013-05-21 15:57 3287spring使用PropertyPlaceholderCon ... -
java国际化
2013-05-20 20:57 4437java国际化 本文来自:http://www.j ... -
RSS feeds with Java
2013-05-20 20:52 1183RSS feeds with Java 原文来自:htt ... -
使用ibatis将数据库从oracle迁移到mysql的几个修改点
2013-04-29 10:40 1632我们项目在公司的大战略下需要从oracle ... -
线上机器jvm dump分析脚本
2013-04-19 10:48 2860#!/bin/sh DUMP_PIDS=`p ... -
eclipse远程部署,静态文件实时同步插件
2013-04-06 20:18 5417eclipse 远程文件实时同步,eclipse远程 ... -
java价格处理的一个问题
2013-03-26 21:21 1791我们经常会处理一些价格,比如从运营上传的文件中将某 ... -
java 服务降级开关设计思路
2013-03-23 16:35 3718java 服务屏蔽开关系统,可以手工降级服务,关闭服 ... -
poi解析excel内存溢出
2013-03-20 22:21 6344真是悲剧啊,一个破内部使用系统20多个人使用的后 ... -
简单web安全框架
2013-03-16 11:56 1498web安全框架,主要用servlet filter方 ... -
基于servlet的简单的页面缓存框架
2013-03-11 19:27 1177基于servlet的页面级缓存框架的基本用法: 代码参考: ... -
Eclipse使用过程中出现java.lang.NoClassDefFoundError的解决方案
2013-02-01 17:22 1471如果jdk,classpath设置正确,突然在eclipse ...
相关推荐
内容包含ASM4.0中文手册,以及四种ASM常见的字节码操作应用范例,包含最新版本的ASM9.2的jar包,包含asm-9.2.jar,asm-commons-9.2.jar,asm-util-9.2.jar。 学习文章地址 ...
asm-4.0,asm-analysis-4.0,asm-tree-4.0,asm-util-4.0,asm-xml-4.0
asm4.0字节码操纵框架 asm4.0字节码操纵框架
spring 3.2.5版本源码使用的,构建的时候使用如下描述 因为英文不太好,大概意思可能是什么asm4.0版本使用的spring 在spring4中已经重新包装了asm在spring-core的核心包里,当然我这解释不标准 看下满原文构建的描述...
深入字节码 -- 使用 ASM 实现 AOP1
asm-4.0.jar
ssh搭建 asm-all-4.0.jar 解决ssh包冲突问题
介绍ASM的简单使用和基本原理,并对AOP的原理进行了详细的描述和总结。
标签:asm-all-4.0.jar.zip,asm,all,4.0,jar.zip包下载,依赖包
标签:asm-util-4.0_RC1.jar.zip,asm,util,4.0_RC1,jar.zip包下载,依赖包
AOP 的利器:ASM 3_0 介绍,很好的书
标签:asm-4.0_RC1.jar.zip,asm,4.0_RC1,jar.zip包下载,依赖包
asm-all-4.0.jar
我学习spring程序,测试程序时.老出bug, 后来从网上找原因说asm.jar版本太低 现把好不容易找来的jar包共享给大家
ASM算法实现对齐功能代码 经典算法asm,内部对齐部分代码,就是求解那个矩阵代码
详细介绍了AOP的核心功能(拦截功能)在底层是如何实现的;介绍了两种实现AOP的动态代理:jdk动态代理和cglib动态代理,并详细描述了它们在代码层面的实现。附有必须的cglib.jar和asm.jar
sourceInsight4.0完美支持汇编,识别equ定义常量,ds定义变量,“:”结束的函数,可以跳转,还有各种汇编指令高亮。注意只支持4.0,3.0版本不支持.xclf...使用方法网上很多,csdn博客搜一大堆,给上一个别人写的参考:...
Android 无痕埋点框架 使用ASM插桩实现
oracle不使用oracleasm的包配置ASM磁盘配置方法
实现JPA基本数据库操作功能封装 实现基于ASM9,动态生成entity、repository、service、serviceImpl、controller相关.class 可根据库表,一键生成新增、修改删除、查询等接口 实现部分基于mybatis-plus,动态代码生成...