有时候为了程序的灵活性,我们都会用到 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();
}
}
分享到:
相关推荐
ASM是一个开源的Java字节码操控和分析框架,它能够用来动态生成类或者增强已有类的功能。ASM可以被用来创建Java代理、实现元编程、甚至深入到Java虚拟机(JVM)层面进行性能优化。在Java开发中,ASM库允许我们直接...
CGlib库利用ASM库(一个底层的Java字节码操作和分析框架)来生成和修改字节码。通过这种方式,开发者可以在程序运行时动态地创建新的类或修改现有类的行为,而无需重新编译源代码。 **动态代理** CGlib常用于实现...
ASM字节码库是Java字节码操作的强大工具,它允许程序员在运行时动态生成类或者增强已有类的功能。在本实例中,我们将探讨如何利用ASM实现简单的面向切面编程(AOP)功能,这是一种在不修改源代码的情况下,添加额外...
ASM是一个开源的Java字节码操控和分析框架,它可以直接用来生成和修改Java类文件,是Java动态代理和字节码增强技术的重要工具。在深入学习Java字节码和ASM之前,我们需要先理解Java编译和运行的基本过程。 1. **...
在本篇中,我们将详细探讨ClassLoader的工作原理、ASM库的使用以及如何利用这些工具进行动态字节码增强。 首先,我们来看Java的类加载机制。Java中的类加载主要由ClassLoader完成,它遵循“双亲委派模型”(Parents...
ASM Java字节码操作框架PPT,结合已有AOP实现方法,对比所有对Java字节码操作方法做比较
综上所述,ASM 4.0 是一个强大且灵活的 Java 字节码操作框架,提供了丰富的功能和工具,适用于多种应用场景,如程序分析、代码生成和转换等。无论是对于开发人员还是研究人员来说,都是一款不可或缺的工具。
ObjectWeb ASM是一个轻量级且强大的Java字节码操控和分析框架,它允许程序员动态生成和修改类的字节码。本文将深入探讨如何使用ASM库来构建一个Method Monitor,以便监控和记录应用程序中方法的调用。 首先,了解...
【标题】:“cglib——Java字节码生成库”是一个强大的工具,用于在运行时动态创建和修改类的字节码。它是一个广泛应用于Java开发中的库,特别是那些需要底层控制对象实例化、方法调用等场景的项目。 【描述】:...
它可以直接生成和修改Java类的字节码,从而实现诸如动态代理、代码混淆、性能监控等功能。在这个插件中,ASM被用来在运行时动态插入代码,记录并打印指定类或注解方法的执行时间。 插件的使用流程大致如下: 1. ...
通过这个“JavaAgent: Javassist与Asm JavaAgent字节码动态编程项目”,你将有机会亲自动手实践,理解如何使用这两个库来创建JavaAgent,以及如何在运行时动态修改字节码。项目中可能包含示例代码、教程文档,以及一...
使用 ASM 从 Java 字节码生成控制流图 作者 佩纳安东尼 布朗丁·尼古拉斯 巴登·杰里米 要求 已安装 开发商 您必须位于项目文件夹(pom.xml 文件所在的位置)才能使用以下命令进行编译: mvn compile 然后运行项目...
NULL 博文链接:https://name327.iteye.com/blog/1554558
4. **动态语言实现**:一些动态语言的Java实现,如Groovy和Jython,使用ASM来生成Java字节码。 5. **框架开发**:例如Spring AOP和Hibernate ORM等框架,利用ASM进行字节码增强,实现AOP切面和对象关系映射。 **API...
在Android开发领域,字节码插桩是一种非常重要的技术,它允许开发者在程序运行时动态地插入代码,以此实现如性能监控、日志记录、权限检查等...同时,掌握ASM也能提升开发者对Java字节码的理解,进一步提升编程技能。
ASM 帮助文档(java字节码操作) 对字节码进行操作的jar包。
2. **字节码生成**:BCEL提供了一套接口和类,使得开发者可以动态地生成字节码,这对于创建动态代理、AOP(面向切面编程)等场景非常有用。 3. **代码优化**:通过修改字节码,BCEL可以实现代码的优化,例如去除...
总结来说,Java字节码实现AOP是一种高效且灵活的技术手段,通过ASM、CGLIB等字节码工具,可以在运行时动态地修改类的行为,实现面向切面编程。理解并掌握这项技术,对于提升Java开发效率和代码质量具有重要意义。
Asm字节码插桩是一种在Java字节码层面对程序进行动态修改的技术,它允许开发者在不修改源代码的情况下,向已有的类或方法中插入额外的代码。这种技术在性能监控、日志记录、行为追踪、代码优化等领域有广泛应用。在...
7. **性能优化**:虽然ASM主要用于动态生成代码,但也可以用于静态代码的优化,例如通过修改字节码减少不必要的计算或提高数据访问效率。 学习ASM需要一定的Java虚拟机(JVM)内部工作原理的知识,包括类文件结构、...