`
ezerg
  • 浏览: 273533 次
  • 性别: Icon_minigender_1
  • 来自: 石家庄
社区版块
存档分类
最新评论

使用 ASM 动态生成字节码代替 JAVA 反射提高性能

阅读更多

    有时候为了程序的灵活性,我们都会用到 JAVA 的反射机制,但是它的代价就是性能比较差,特别是高并发的情况下。
    我们可以通过动态的修改字节码代替反射,以期获得更高的性能。当然它还可以做更多的事情,例如 Spring 的 AOP 实现就使用该技术。
    动态修改字节码的框架很多,这里使用 ASM ,因为它简洁、方便而且高效。
    假设一个处理 WEB 请求的 Action ,每个 Action 通过 execute() 方法来处理请求,为了使用方便让一个 Action 处理多个请求,一般有两种实现方式:
一、是使用反射
在 WEB 请求可以增加一个参数,告诉 Action 要执行哪个方法:
		String cmd = getActionMethodName(method);
		try {
			Method m = action.getClass().getMethod(cmd, paras);
			Object[] objs = new Object[] { form, module };
			return m.invoke(action, objs);
		} catch (NoSuchMethodException nsme) {// getMethod
			log.error("找不到可执行命令{}", method);
			throw new NoSuchMethodException("您访问的页面不存在");
		} catch (InvocationTargetException ite) {// invoke
			log.error("执行 method 命令出错", ite);
			throw new Exception(ite.getCause().getMessage());
		} catch(Exception e) {// other exception
			log.error("执行 doActionMehtod 方法出错", e);
			return null;
		}

这种方式实现比较方便,但是每次请求都会用到反射。

二、利用 ASM 动态修改字节码
基本的原理是 Action 中除 execute() 以外的每个方法都生成一个子类,子类继承该 Action 并实现 exeucte() 方法,子类只对父类特定方法的封装。
public class ParentAction implements IAction {
	public Page execute(Form f, Module m) throws Exception {
		return m.defaultPage();
	}

	public Page doChildMethod(Form f, Module m) throws Exception {
		return m.defaultPage();		
	}
}

可以动态生成子类:
public class ChildAction extends ParentAction {
	public Page execute(Form f, Module m) throws Exception {
		return doChildMethod();
	}
}

也就是说每个执行 ParentAction 中 doChildMethod() 方法的请求都会执行 ChildAction 的 exeucte() 方法,这就避免使用反射机制。
// 以下只列出核心的代码
public class MethodActionEnhancer implements Opcodes {

	public Object getMethodAction(String cls, String method) {
		// 新类的全称
		String newcls = cls + method;
		try {
			return Class.forName(newcls).newInstance();
		} catch (Exception e) {
			log.warn("未找到类[{}],自动生成", newcls);
			try {
				byte[] b = dump(cls, method, newcls);
				return lc.loadClass(newcls, b).newInstance();
			} catch (Exception ex) {
				log.error("类[" + newcls + "]加载出错", ex);
				return null;
			}
		}
	}

	private byte[] dump(String cls, String method, String newcls)
			throws Exception {
		String f = "Lcom/ezerg/jwdt/web/Form;";
		String m = "Lcom/ezerg/jwdt/web/Module;";
		String p = "Lcom/ezerg/jwdt/web/Page;";
		// 父类的名称
		cls = cls.replace(".", "/");
		// 子类的名称
		newcls = newcls.replace(".", "/");
		// 构建 ASM 工具类对象
		ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_MAXS);
		MethodVisitor mv;
		cw.visit(V1_5, ACC_PUBLIC + ACC_SUPER, newcls, null, cls, null);
		cw.visitSource(newcls + ".java", null);
		{ // 构造方法,每个类必须
			mv = cw.visitMethod(ACC_PUBLIC, "<init>", "()V", null, null);// 方法名称
			mv.visitCode();
			Label l0 = new Label();
			mv.visitLabel(l0);
			mv.visitLineNumber(7, l0);
			mv.visitVarInsn(ALOAD, 0);// 加载 this 对象
			mv.visitMethodInsn(INVOKESPECIAL, cls, "<init>", "()V");// 调用父类的 init 方法
			mv.visitInsn(RETURN);// 返回
			Label l1 = new Label();
			mv.visitLabel(l1);
			mv.visitLocalVariable("this", "L" + newcls + ";", null, l0, l1, 0);// 本地方法变量
			mv.visitMaxs(1, 1);// 设置本地堆栈
			mv.visitEnd();
		}
		{ // execute方法,实现子类的相关方法
			mv = cw.visitMethod(ACC_PUBLIC, "execute", "(" + f + m + ")" + p,	null, new String[] { "java/lang/Exception" });// 方法名称
			mv.visitCode();
			Label l0 = new Label();
			mv.visitLabel(l0);
			mv.visitLineNumber(10, l0);
			mv.visitVarInsn(ALOAD, 0);// 加载 this 对象
			mv.visitVarInsn(ALOAD, 1);// 加载 f 参数
			mv.visitVarInsn(ALOAD, 2);// 加载 m 参数 
			mv.visitMethodInsn(INVOKEVIRTUAL, cls, method, "(" + f + m + ")" + p);// 调用父类的方法
			mv.visitInsn(ARETURN); // 返回对象的引用
			Label l1 = new Label();
			mv.visitLabel(l1);
			mv.visitLocalVariable("this", "L" + newcls + ";", null, l0, l1, 0);// 本地方法变量
			mv.visitLocalVariable("f", f, null, l0, l1, 1);// 本地方法变量
			mv.visitLocalVariable("m", m, null, l0, l1, 2);// 本地方法变量
			mv.visitMaxs(3, 3);// 设置本地堆栈
			mv.visitEnd();
		}
		cw.visitEnd();
		return cw.toByteArray();
	}
}


2
0
分享到:
评论
1 楼 sjk_009 2011-08-18  
方法的参数如果是动态的怎么弄?

相关推荐

    ASM操作字节码,动态生成Java类class文件

    ASM是一个开源的Java字节码操控和分析框架,它能够用来动态生成类或者增强已有类的功能。ASM可以被用来创建Java代理、实现元编程、甚至深入到Java虚拟机(JVM)层面进行性能优化。在Java开发中,ASM库允许我们直接...

    cglib,字节码生成库是生成和转换Java字节码的高级API。它被aop、测试、数据访问框架用来生成动态代理对象和拦截字段访问。.zip

    CGlib库利用ASM库(一个底层的Java字节码操作和分析框架)来生成和修改字节码。通过这种方式,开发者可以在程序运行时动态地创建新的类或修改现有类的行为,而无需重新编译源代码。 **动态代理** CGlib常用于实现...

    ASM字节码操作简单实例

    ASM字节码库是Java字节码操作的强大工具,它允许程序员在运行时动态生成类或者增强已有类的功能。在本实例中,我们将探讨如何利用ASM实现简单的面向切面编程(AOP)功能,这是一种在不修改源代码的情况下,添加额外...

    Java字节码和asm入门资料

    ASM是一个开源的Java字节码操控和分析框架,它可以直接用来生成和修改Java类文件,是Java动态代理和字节码增强技术的重要工具。在深入学习Java字节码和ASM之前,我们需要先理解Java编译和运行的基本过程。 1. **...

    Java Classloading Mechanism : ClassLoader & ASM & 动态字节码增强

    在本篇中,我们将详细探讨ClassLoader的工作原理、ASM库的使用以及如何利用这些工具进行动态字节码增强。 首先,我们来看Java的类加载机制。Java中的类加载主要由ClassLoader完成,它遵循“双亲委派模型”(Parents...

    ASM Java字节码操作框架

    ASM Java字节码操作框架PPT,结合已有AOP实现方法,对比所有对Java字节码操作方法做比较

    ASM 字节码修改工具中文帮助手册

    综上所述,ASM 4.0 是一个强大且灵活的 Java 字节码操作框架,提供了丰富的功能和工具,适用于多种应用场景,如程序分析、代码生成和转换等。无论是对于开发人员还是研究人员来说,都是一款不可或缺的工具。

    [字节码系列]ObjectWeb ASM构建Method Monitor

    ObjectWeb ASM是一个轻量级且强大的Java字节码操控和分析框架,它允许程序员动态生成和修改类的字节码。本文将深入探讨如何使用ASM库来构建一个Method Monitor,以便监控和记录应用程序中方法的调用。 首先,了解...

    cglibJava字节码生成库

    【标题】:“cglib——Java字节码生成库”是一个强大的工具,用于在运行时动态创建和修改类的字节码。它是一个广泛应用于Java开发中的库,特别是那些需要底层控制对象实例化、方法调用等场景的项目。 【描述】:...

    Android-埋点计时Gradle插件利用ASM插入字节码

    它可以直接生成和修改Java类的字节码,从而实现诸如动态代理、代码混淆、性能监控等功能。在这个插件中,ASM被用来在运行时动态插入代码,记录并打印指定类或注解方法的执行时间。 插件的使用流程大致如下: 1. ...

    JavaAgent:Javassist 与 Asm JavaAgent 字节码动态编程项目

    通过这个“JavaAgent: Javassist与Asm JavaAgent字节码动态编程项目”,你将有机会亲自动手实践,理解如何使用这两个库来创建JavaAgent,以及如何在运行时动态修改字节码。项目中可能包含示例代码、教程文档,以及一...

    bytecode-to-cfg:使用 ASM 从 Java 字节码生成控制流图

    使用 ASM 从 Java 字节码生成控制流图 作者 佩纳安东尼 布朗丁·尼古拉斯 巴登·杰里米 要求 已安装 开发商 您必须位于项目文件夹(pom.xml 文件所在的位置)才能使用以下命令进行编译: mvn compile 然后运行项目...

    asm动态生成class,并且动态加载执行

    NULL 博文链接:https://name327.iteye.com/blog/1554558

    代码生成工具asm-3.2

    4. **动态语言实现**:一些动态语言的Java实现,如Groovy和Jython,使用ASM来生成Java字节码。 5. **框架开发**:例如Spring AOP和Hibernate ORM等框架,利用ASM进行字节码增强,实现AOP切面和对象关系映射。 **API...

    Android字节码插桩

    在Android开发领域,字节码插桩是一种非常重要的技术,它允许开发者在程序运行时动态地插入代码,以此实现如性能监控、日志记录、权限检查等...同时,掌握ASM也能提升开发者对Java字节码的理解,进一步提升编程技能。

    ASM 帮助文档(java字节码操作)

    ASM 帮助文档(java字节码操作) 对字节码进行操作的jar包。

    JAVA字节码操作库 BCEL

    2. **字节码生成**:BCEL提供了一套接口和类,使得开发者可以动态地生成字节码,这对于创建动态代理、AOP(面向切面编程)等场景非常有用。 3. **代码优化**:通过修改字节码,BCEL可以实现代码的优化,例如去除...

    Java字节码实现Aop

    总结来说,Java字节码实现AOP是一种高效且灵活的技术手段,通过ASM、CGLIB等字节码工具,可以在运行时动态地修改类的行为,实现面向切面编程。理解并掌握这项技术,对于提升Java开发效率和代码质量具有重要意义。

    演示Asm字节码插桩asmd-demo-master.zip

    Asm字节码插桩是一种在Java字节码层面对程序进行动态修改的技术,它允许开发者在不修改源代码的情况下,向已有的类或方法中插入额外的代码。这种技术在性能监控、日志记录、行为追踪、代码优化等领域有广泛应用。在...

    ASM使用指南-中文版

    7. **性能优化**:虽然ASM主要用于动态生成代码,但也可以用于静态代码的优化,例如通过修改字节码减少不必要的计算或提高数据访问效率。 学习ASM需要一定的Java虚拟机(JVM)内部工作原理的知识,包括类文件结构、...

Global site tag (gtag.js) - Google Analytics