- 浏览: 755247 次
- 性别:
- 来自: 杭州
文章分类
最新评论
-
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的解决方法
asm 4.0 版本
http://forge.ow2.org/plugins/scmsvn/index.php?group_id=23
asm是java的字节码操作框架,可以动态查看类的信息,动态修改,删除,增加类的方法。
下面基于4.0版本的一个使用示例,演示了对类Foo进行修改方法名称,增加方法,修改方法内容等
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 AsmExample extends ClassLoader implements Opcodes{ public static class Foo { public static void execute() { System.out.println("test changed method name"); } public static void changeMethodContent() { System.out.println("test change method"); } } 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); //新增加一个方法 MethodVisitor mw= cw.visitMethod(ACC_PUBLIC + ACC_STATIC, "add", "([Ljava/lang/String;)V", null, null); // pushes the 'out' field (of type PrintStream) of the System class mw.visitFieldInsn(GETSTATIC, "java/lang/System", "out", "Ljava/io/PrintStream;"); // pushes the "Hello World!" String constant mw.visitLdcInsn("this is add method print!"); // invokes the 'println' method (defined in the PrintStream class) mw.visitMethodInsn(INVOKEVIRTUAL, "java/io/PrintStream", "println", "(Ljava/lang/String;)V"); mw.visitInsn(RETURN); // this code uses a maximum of two stack elements and two local // variables mw.visitMaxs(0, 0); mw.visitEnd(); // gets the bytecode of the Example class, and loads it dynamically byte[] code = cw.toByteArray(); AsmExample loader = new AsmExample(); Class<?> exampleClass = loader.defineClass(Foo.class.getName(), code, 0, code.length); for(Method method: exampleClass.getMethods()){ System.out.println(method); } System.out.println("*************"); // uses the dynamically generated class to print 'Helloworld' exampleClass.getMethods()[0].invoke(null, null); //調用changeMethodContent,修改方法內容 System.out.println("*************"); exampleClass.getMethods()[1].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 void visit( int version, int access, String name, String signature, String superName, String[] interfaces) { if (cv != null) { cv.visit(version, access, name, signature, superName, interfaces); } } @Override public MethodVisitor visitMethod( int access, String name, String desc, String signature, String[] exceptions) { if (cv != null && "execute".equals(name)) { //当方法名为execute时,修改方法名为execute1 return cv.visitMethod(access, name + "1", desc, signature, exceptions); } if("changeMethodContent".equals(name)) //此处的changeMethodContent即为需要修改的方法 ,修改方法內容 { MethodVisitor mv = cv.visitMethod(access, name, desc, signature, exceptions);//先得到原始的方法 MethodVisitor newMethod = null; newMethod = new AsmMethodVisit(mv); //访问需要修改的方法 return newMethod; } if (cv != null) { return cv.visitMethod(access, name, desc, signature, exceptions); } return null; } } static class AsmMethodVisit extends MethodVisitor { public AsmMethodVisit(MethodVisitor mv) { super(Opcodes.ASM4, mv); } @Override public void visitMethodInsn(int opcode, String owner, String name, String desc) { super.visitMethodInsn(opcode, owner, name, desc); } @Override public void visitCode() { //此方法在访问方法的头部时被访问到,仅被访问一次 //此处可插入新的指令 super.visitCode(); } @Override public void visitInsn(int opcode) { //此方法可以获取方法中每一条指令的操作类型,被访问多次 //如应在方法结尾处添加新指令,则应判断: if(opcode == Opcodes.RETURN) { // pushes the 'out' field (of type PrintStream) of the System class mv.visitFieldInsn(GETSTATIC, "java/lang/System", "out", "Ljava/io/PrintStream;"); // pushes the "Hello World!" String constant mv.visitLdcInsn("this is a modify method!"); // invokes the 'println' method (defined in the PrintStream class) mv.visitMethodInsn(INVOKEVIRTUAL, "java/io/PrintStream", "println", "(Ljava/lang/String;)V"); // mv.visitInsn(RETURN); } super.visitInsn(opcode); } } }
输出:
add方法是新增的,execute方法名改为execute1,changeMethodContent方法修改后增加了输出this is a modify method!
public static void AsmExample$Foo.changeMethodContent() public static void AsmExample$Foo.execute1() public static void AsmExample$Foo.add(java.lang.String[]) 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 change method this is a modify method! ************* test changed method name
我们把最终的字节码保存到文件中e:\\logs\\Example.class中,再用反编译工具java decompiler 查看最终的生成的源码:
最终的类如下:
import java.io.PrintStream; public class AsmExample$Foo { public static void execute1() { System.out.println("test changed method name"); } public static void changeMethodContent() { System.out.println("test change method"); System.out.println("this is a modify method!"); } public static void add(String[] paramArrayOfString) { System.out.println("this is add method print!"); } }
接下来再慢慢研究asm里面对字节码的操作,还有其他框架是如果使用asm的。
发表评论
-
对字符串进行验证之前先进行规范化
2013-09-17 23:18 13957对字符串进行验证之前先进行规范化 应用系统中经常对字 ... -
使用telnet连接到基于spring的应用上执行容器中的bean的任意方法
2013-08-08 09:17 1482使用telnet连接到基于spring的应用上执行容器中 ... -
jdk7和8的一些新特性介绍
2013-07-06 16:07 10114更多ppt内容请查看:htt ... -
java对于接口和抽象类的代理实现,不需要有具体实现类
2013-06-12 09:50 2957原文链接:http://www.javaarch.net/j ... -
Excel2007格式分析和XML解析
2013-06-07 09:56 10746在物料清单采购中,用到excel上传文件解析功能,不 ... -
Java EE 7中对WebSocket 1.0的支持
2013-06-05 09:27 3846原文链接:http://www.javaarch.n ... -
java QRCode生成示例
2013-06-05 09:26 1516原文链接:http://www.javaarch.n ... -
Java Web使用swfobject调用flex图表
2013-05-28 19:05 1128Java Web使用swfobject调用 ... -
spring使用PropertyPlaceholderConfigurer扩展来满足不同环境的参数配置
2013-05-21 15:57 3344spring使用PropertyPlaceholderCon ... -
java国际化
2013-05-20 20:57 4478java国际化 本文来自:http://www.j ... -
RSS feeds with Java
2013-05-20 20:52 1226RSS feeds with Java 原文来自:htt ... -
使用ibatis将数据库从oracle迁移到mysql的几个修改点
2013-04-29 10:40 1679我们项目在公司的大战略下需要从oracle ... -
线上机器jvm dump分析脚本
2013-04-19 10:48 2912#!/bin/sh DUMP_PIDS=`p ... -
eclipse远程部署,静态文件实时同步插件
2013-04-06 20:18 5469eclipse 远程文件实时同步,eclipse远程 ... -
java价格处理的一个问题
2013-03-26 21:21 1841我们经常会处理一些价格,比如从运营上传的文件中将某 ... -
java 服务降级开关设计思路
2013-03-23 16:35 3772java 服务屏蔽开关系统,可以手工降级服务,关闭服 ... -
poi解析excel内存溢出
2013-03-20 22:21 6406真是悲剧啊,一个破内部使用系统20多个人使用的后 ... -
简单web安全框架
2013-03-16 11:56 1551web安全框架,主要用servlet filter方 ... -
基于servlet的简单的页面缓存框架
2013-03-11 19:27 1222基于servlet的页面级缓存框架的基本用法: 代码参考: ... -
Eclipse使用过程中出现java.lang.NoClassDefFoundError的解决方案
2013-02-01 17:22 1578如果jdk,classpath设置正确,突然在eclipse ...
相关推荐
ASM字节码库是Java字节码操作的强大工具,它允许程序员在运行时动态生成类或者增强已有类的功能。在本实例中,我们将探讨如何利用ASM实现简单的面向切面编程(AOP)功能,这是一种在不修改源代码的情况下,添加额外...
ASM是一个开源的Java字节码操控和分析框架,它能够用来动态生成类或者增强已有类的功能。ASM可以被用来创建Java代理、实现元编程、甚至深入到Java虚拟机(JVM)层面进行性能优化。在Java开发中,ASM库允许我们直接...
### ASM 字节码修改工具中文帮助手册知识点概览 #### 1. ASM 4.0 简介 - **版本信息**: ASM 4.0 是一个 Java 字节码操作和分析框架,由 Eric Bruneton 开发并维护,版权归属 Eric Bruneton(2007-2011)。 - **...
它可以直接生成和修改Java类的字节码,从而实现诸如动态代理、代码混淆、性能监控等功能。在这个插件中,ASM被用来在运行时动态插入代码,记录并打印指定类或注解方法的执行时间。 插件的使用流程大致如下: 1. ...
Asm字节码插桩是一种在Java字节码层面对程序进行动态修改的技术,它允许开发者在不修改源代码的情况下,向已有的类或方法中插入额外的代码。这种技术在性能监控、日志记录、行为追踪、代码优化等领域有广泛应用。在...
ASM字节码插桩是一种在Java字节码级别进行动态代码增强的技术,广泛应用于性能监控、日志记录、安全审计等领域。ASM是一个底层的Java字节码操控和分析框架,它可以直接转换Java类和.dex文件,并能被用来动态生成类...
Java字节码框架ASM是一个强大的库,它允许程序员在运行时动态生成和修改Java类和接口的字节码。ASM提供了对JVM字节码的底层访问,这使得开发者能够实现诸如AOP(面向切面编程)或者元编程等高级功能。 首先,我们...
ObjectWeb ASM是一个轻量级且强大的Java字节码操控和分析框架,它允许程序员动态生成和修改类的字节码。本文将深入探讨如何使用ASM库来构建一个Method Monitor,以便监控和记录应用程序中方法的调用。 首先,了解...
ASM是一个开源的Java字节码操控和分析框架,它可以直接用来生成和修改Java类文件,是Java动态代理和字节码增强技术的重要工具。在深入学习Java字节码和ASM之前,我们需要先理解Java编译和运行的基本过程。 1. **...
总结起来,ASM作为强大的字节码操作工具,为Android开发者提供了字节码插桩的能力,使得我们可以在不修改源代码的情况下实现各种功能增强,这对于优化和调试Android应用具有极大的价值。同时,掌握ASM也能提升开发者...
ASM是一个低级别的库,可以直接操作Java字节码,提供了一种动态生成和修改类的方法。它通过ClassWriter、ClassReader、MethodVisitor等接口,允许开发者对字节码进行读取、修改和写入。ASM的核心在于它的事件驱动...
它为开发者提供了一种深入理解与操作Java类文件的底层机制,允许分析、创建、修改和优化字节码。在软件工程中,BCEL在诸如动态代理、代码分析、代码生成以及逆向工程等领域有广泛应用。 **一、BCEL的基本概念** 1....
CGlib库利用ASM库(一个底层的Java字节码操作和分析框架)来生成和修改字节码。通过这种方式,开发者可以在程序运行时动态地创建新的类或修改现有类的行为,而无需重新编译源代码。 **动态代理** CGlib常用于实现...
Javaagent技术允许我们在JVM启动时附加一个代理程序,这个代理可以修改类的字节码,从而在不改变原有代码的情况下,实现对方法调用的拦截和处理。 字节码编程不仅是Java开发者的必备技能之一,它也是深入理解JVM...
字节码插桩是一种动态或静态修改字节码的技术,用于在运行时或编译时插入额外的代码。在Android中,我们可以使用ASM、Dexmaker或ByteBuddy等库来实现字节码插桩。LazierTracker就是基于这些技术,它能够在运行时动态...
Java字节码实现AOP(面向切面编程)是一种在程序运行时动态插入代码的技术,它使得我们可以在不修改原有代码的情况下,增加新的功能或监控已有功能。在Java中,AOP通常通过代理模式和字节码操作来实现,如Spring AOP...
例如,CGLIB、ASM等库可以在运行时生成和修改字节码,实现动态类的创建和功能增强。 7. **JVM内存模型与字节码**: 字节码执行与JVM的内存模型密切相关,包括堆、栈、方法区、本地方法栈等。理解这些概念有助于...
通过ASM,开发者可以直接操作字节码,实现对方法的插入、删除或修改。这对于创建AOP(面向切面编程)框架、性能监控工具、代码混淆等场景非常有用。 在Android开发中,ASM插桩主要应用于以下几个方面: 1. 性能...
总结起来,Java的类加载机制保证了程序的稳定运行,而ASM库则提供了对字节码的直接操作能力,使得我们能够在运行时动态地修改类的行为。掌握这两者,开发者可以更好地理解和定制Java应用的运行过程,提升程序的灵活...
在进行字节码修改时,需要谨慎操作,因为错误的修改可能导致程序崩溃或者运行异常。通常,这种操作是在对现有代码有深入理解或需要进行特定优化时进行的。使用这些工具,开发者可以实现如方法内联、优化循环、替换...