? ? ? ?前些日工作中需要改一个jar包中的程序代码,想了很多方法 包括直接修改、动态代理等等,但都效果不好。最后无意中发现了ASM这个框架,感觉正是我需要的。研究几日,用到一些基础功能就实现了所要效果,所以写出来给大家共享,自己忘了也好参考参考.下面是ASM一些基本介绍,就当是抛砖引玉了~~其中参考了几篇其他iteye朋友的文章,主要是JVM、字节码和类加载方面的东西,有助于更好的理解ASM。这里我主要说说ASM的东西,其他的大家去看看吧。
?
一、什么是ASM
ASM是一个java字节码操纵框架,它能被用来动态生成类或者增强既有类的功能。ASM 可以直接产生二进制 class?文件,也可以在类被加载入 Java 虚拟机之前动态改变类行为。Java class 被存储在严格格式定义的 .class文件里,这些类文件拥有足够的元数据来解析类中的所有元素:类名称、方法、属性以及 Java 字节码(指令)。ASM从类文件中读入信息后,能够改变类行为,分析类信息,甚至能够根据用户要求生成新类。
二、ASM核心类介绍:
①ClassReader类:这个类会提供你要转变的类的字节数组,它的accept方法,接受一个具体的ClassVisitor,并调用实现中具体的visit,visitSource,?visitOuterClass,?visitAnnotation,?visitAttribute,?visitInnerClass,?visitField,visitMethod和?visitEnd方法。
public class Person { public final String sleep() { try { Thread.sleep(2);//沉睡两秒 } catch (InterruptedException e) { e.printStackTrace(); } return "123"; } }
?
?ModifyMethodClassAdapter.java代码如下:package com.asm1; import org.objectweb.asm.ClassAdapter; import org.objectweb.asm.ClassVisitor; import org.objectweb.asm.MethodVisitor; import org.objectweb.asm.Opcodes; public class ModifyMethodClassAdapter extends ClassAdapter { public ModifyMethodClassAdapter(ClassVisitor cv) { super(cv); } @Override public MethodVisitor visitMethod(int access, String name, String desc, String signature, String[] exceptions) { //(Ljava/lang/String;[BII)Ljava/lang/Class; //(Ljava/lang/String;[BIILjava/security/ProtectionDomain;)Ljava/lang/Class; int a=10; if (name.equals("sleep")&&desc.equals("()Ljava/lang/String;")) { return new ModifyMethod(super.visitMethod(access, name, desc, signature, exceptions), access, name, desc); } //System.out.println(a); return super.visitMethod(access, name, desc, signature, exceptions); } @Override public void visitEnd() { cv.visitField(Opcodes.ACC_PRIVATE + Opcodes.ACC_STATIC, "timer", "J", null, null); } }?注意name.equals("sleep")&&desc.equals("()Ljava/lang/String;")这行,ASM会根据方法名和方法描述来查找方法,下面是方法描述在类中和二进制中的对应关系
? | ? | ||||||||||||
? |
|
?
package com.asm1; import org.objectweb.asm.MethodAdapter; import org.objectweb.asm.MethodVisitor; import org.objectweb.asm.Opcodes; import org.objectweb.asm.Type; public class ModifyMethod extends MethodAdapter { public ModifyMethod(MethodVisitor mv, int access, String name, String desc) { super(mv); } @Override public void visitCode() { mv.visitFieldInsn(Opcodes.GETSTATIC, "java/lang/System", "out", "Ljava/io/PrintStream;"); mv.visitLdcInsn("我是赛亚人"); mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/io/PrintStream", "println", "(Ljava/lang/String;)V"); } }?
?
?代码中各方法public class test { public static void main(String[] args) { System.out.println("我是赛亚人"); } }?
ClassReader classReader = new ClassReader("com.asm1.Person"); //com.asm1.Person ClassWriter classWriter = new ClassWriter(ClassWriter.COMPUTE_MAXS); ClassAdapter classAdapter = new ModifyMethodClassAdapter(classWriter); classReader.accept(classAdapter, ClassReader.SKIP_DEBUG); byte[] classFile = classWriter.toByteArray(); File f = new File("F:\\abc\\aaa.class"); FileOutputStream fs = new FileOutputStream(f); fs.write(classFile); fs.close(); System.out.println("success");?运行该程序,在abc文件夹下会生成一个aaa.class文件,使用反编译软件打开该文件如下:
原文:http://kakarottoz.iteye.com/blog/2190484