一、MethodNode概述
ASM的TreeApi 对于Method的转换、生成也提供了一系列的组件和接口。其功能主要基于前一章提到的MethodNode类。MethodNode中大多数属性和方法都和ClassNode类似,其中最主要的属性就是InsnList了。InsnList是一个双向链表对象,包含了存储方法的字节指令序。先来看下InsnList中的主要是属性和方法。
public class InsnList { // public accessors omitted private int size; private AbstractInsnNode first; private AbstractInsnNode last; AbstractInsnNode[] cache; int size(); AbstractInsnNode getFirst(); AbstractInsnNode getLast(); AbstractInsnNode get(int index); boolean contains(AbstractInsnNode insn); int indexOf(AbstractInsnNode insn); void accept(MethodVisitor mv); ListIterator iterator(); ListIterator iterator(int index); AbstractInsnNode[] toArray(); void set(AbstractInsnNode location, AbstractInsnNode insn); void add(AbstractInsnNode insn); void add(InsnList insns); void insert(AbstractInsnNode insn); void insert(InsnList insns); void insert(AbstractInsnNode location, AbstractInsnNode insn); void insert(AbstractInsnNode location, InsnList insns); void insertBefore(AbstractInsnNode location, AbstractInsnNode insn); void insertBefore(AbstractInsnNode location, InsnList insns); void remove(AbstractInsnNode insn); void clear(); }
可以看到InsnList 中主要是对AbstractInsnNode对象的操作方法,AbstractInsnNode也就是链表中的元素。其中,AbstractInsnNode数组存储了字节码指令对象的链表连接关系。AbstractInsnNode是一个抽象父类,代表了字节指令的一个抽象类。AbstractInsnNode的主要方法如下。
public abstract class AbstractInsnNode { public int getOpcode(); public int getType(); public AbstractInsnNode getPrevious(); public AbstractInsnNode getNext(); public void accept(MethodVisitor cv); public AbstractInsnNode clone(Map labels); }
他的子类如VarInsnNode(代表局部变量表的操作指令对象,如xstore,xload)是和MethodVisitor中的visitVarInsn(int opcode, int var)关联的指令访问方法。LabelNode, FrameNode 以及 LineNumberNode也继承了AbstractInsnNode。这样就可以像CoreApi中MethodVisitor提供的visitXX 方法一样,插入在关联的指令前。在TreeApi中可以通过对象的getNext()方法方便找到跳转到的指令,并且移除指令的时候,只要label不变,也不会影响原有的跳转指令的跳转地址。同Core 不同的就是,从调用MethodVisitor各个指令对应的visitXX方法,改成对MethodNode 中InsnList对象的链表节点操作。
二、生成Method
通过下面这个例子就会更加一目了然。当然,MethodNode生成class的效率要比MethodVisitor低,内存消耗也会大,但是我们可以更轻松得实现一段注入逻辑。
方法内部的字节码结构样例,我们依然沿用一下在CoreApi 的Method介绍中使用的http://yunshen0909.iteye.com/blog/2221144的例子。然后可以对比一下两种实现方式的不同。
package asm.tree.method; import org.objectweb.asm.ClassWriter; import org.objectweb.asm.Opcodes; import org.objectweb.asm.tree.*; import java.io.File; import java.io.FileOutputStream; import java.io.IOException; /** * tree api method 生成字节码 Created by yunshen.ljy on 2015/7/20. */ public class GenerateClasses { public static void main(String[] args) throws IOException { ClassNode classNode = new ClassNode(); classNode.version = Opcodes.V1_8; classNode.access = Opcodes.ACC_PUBLIC; classNode.name = "bytecode/TreeMethodGenClass"; classNode.superName = "java/lang/Object"; classNode.fields.add(new FieldNode(Opcodes.ACC_PRIVATE, "espresso", "I", null, null)); // public void addEspresso(int espresso) 方法生命 MethodNode mn = new MethodNode(Opcodes.ACC_PUBLIC, "addEspresso", "(I)V", null, null); classNode.methods.add(mn); InsnList il = mn.instructions; il.add(new VarInsnNode(Opcodes.ILOAD, 1)); il.add(new InsnNode(Opcodes.ICONST_1)); LabelNode label = new LabelNode(); // if (espresso > 0) 跳转通过LabelNode标记跳转地址 il.add(new JumpInsnNode(Opcodes.IF_ICMPLE, label)); il.add(new VarInsnNode(Opcodes.ALOAD, 0)); il.add(new VarInsnNode(Opcodes.ILOAD, 1)); // this.espresso = var1; il.add(new FieldInsnNode(Opcodes.PUTFIELD, "bytecode/TreeMethodGenClass", "espresso", "I")); LabelNode end = new LabelNode(); il.add(new JumpInsnNode(Opcodes.GOTO, end)); // label 后紧跟着下一个指令地址 il.add(label); // java7之后对stack map frame 的处理 il.add(new FrameNode(Opcodes.F_SAME, 0, null, 0, null)); // throw new IllegalArgumentException(); il.add(new TypeInsnNode(Opcodes.NEW, "java/lang/IllegalArgumentException")); il.add(new InsnNode(Opcodes.DUP)); il.add(new MethodInsnNode(Opcodes.INVOKESPECIAL, "java/lang/IllegalArgumentException", "<init>", "()V", false)); il.add(new InsnNode(Opcodes.ATHROW)); il.add(end); // stack map 的第二次偏移记录 il.add(new FrameNode(Opcodes.F_SAME, 0, null, 0, null)); il.add(new InsnNode(Opcodes.RETURN)); // 局部变量表和操作数栈大小的处理 mn.maxStack = 2; mn.maxLocals = 2; mn.visitEnd(); // 打印查看class的生成结果 ClassWriter cw = new ClassWriter(Opcodes.ASM5); classNode.accept(cw); File file = new File("TreeMethodGenClass.class"); FileOutputStream fout = new FileOutputStream(file); try { fout.write(cw.toByteArray()); fout.close(); } catch (IOException e) { e.printStackTrace(); } } }
InsnList il = mn.instructions;所有的方法指令都放在InsnList这样一个链表结构中。当然,这个链表结构也维系了整个字节码指令的结构。
相关推荐
"asm-tree-3.3.jar"是ASM Tree模块的主文件,包含了实现ASM Tree API的所有类和方法。而"asm-2.2.1.jar.license.txt"很可能包含的是ASM框架2.2.1版本的许可协议文本,用户在使用ASM库时需要遵循这些条款。 关于ASM ...
在实际应用中,ASM Tree库通常与ASM的其他组件,如`ClassReader`和`ClassWriter`一起使用。`ClassReader`可以读取字节码并创建一个`ClassNode`实例,而`ClassWriter`则能根据修改后的`ClassNode`生成新的字节码。...
**ASM** 是一个轻量级的字节码处理库,它允许用户在运行时动态生成类和接口,或者修改已有的类。ASM.jar包含了ASM库的所有核心类,这些类可以解析和生成Java字节码,从而实现对Java类的低级别操作。 **ASM-Commons*...
`asm-tree`是Java字节码处理框架ASM的一个组件,主要负责将字节码解析成抽象语法树(Abstract Syntax Tree, AST)。ASM是一个强大的库,它允许程序动态生成和分析Java类。在Java世界中,这通常用于创建元编程框架、...
总结,ASM Tree 3.2是ASM框架中用于处理字节码为树形结构的重要组件,它的稳定性和高效性使其在许多Java开发场景中得到广泛应用。通过理解其核心概念、版本特性以及实践操作,开发者能够更好地利用ASM Tree来实现...
asm-tree-3.3.1.jar是ASM项目的一个组件,它为Java字节码提供了树状API。这个库主要用于处理由无符号数和表两种数据结构组成的Class字节码。 ASM Tree API可以视为对上述两种数据结构的抽象表达方式,它以树形结构...
这个JAR文件包含了所有的类和资源,使得我们能够在程序中直接引用ASM Tree的相关API,进行字节码操作和解析。 "asm-2.2.1.jar.license.txt"则可能是ASM库的许可协议文件,详细规定了使用ASM库的法律条款和限制。...
包含翻译后的API文档:asm-9.1-javadoc-API文档-中文(简体)版.zip; Maven坐标:org.ow2.asm:asm:9.1; 标签:ow2、jar包、java、中文文档; 使用方法:解压翻译后的API文档,用浏览器打开“index.html”文件,即可...
【字节码系列】ObjectWeb ASM构建Method Monitor 在Java世界中,字节码是运行在JVM(Java虚拟机)上的程序表示形式。它是一种中间语言,允许开发者对Java代码进行低级别的操作,比如性能优化、动态代理、代码混淆等...
ASM Tree 2.1是该库的一个稳定版本,相比早期版本,它可能包含了一些性能优化和bug修复,提高了API的稳定性和兼容性。 二、ASM Tree的核心概念 1. `ClassNode`:ASM Tree的核心类,代表一个Java类。它包含了类的...
"asm"指的是ASM框架,"tree"对应ASM Tree模块,"3.1"表示版本号,"jar.zip包下载"意味着用户可以下载这个包含ASM Tree库的JAR压缩包,"依赖包"则暗示在使用ASM Tree时可能需要其他的依赖库,比如ASM的其他组件。...
"asm-tree-1.3.5.jar"是这个版本的ASM Tree API的主要组件,它包含所需的类和方法来解析类文件并构建AST。开发者可以使用这些API来分析和修改类的方法体,例如,添加、删除或改变方法的指令。 "asm-2.2.1.jar....
赠送原API文档:asm-6.0-javadoc.jar 赠送源代码:asm-6.0-sources.jar 包含翻译后的API文档:asm-6.0-javadoc-API文档-中文(简体)-英语-对照版.zip 对应Maven信息:groupId:org.ow2.asm,artifactId:asm,...
asm-tree-5.0.3.jar
包含翻译后的API文档:asm-7.1-javadoc-API文档-中文(简体)版.zip; Maven坐标:org.ow2.asm:asm:7.1; 标签:ow2、jar包、java、中文文档; 使用方法:解压翻译后的API文档,用浏览器打开“index.html”文件,即可...
ASM Tree 是一个针对Java字节码操作的库,它是ASM框架的一部分,ASM是一个流行的、高性能的Java字节码操控和分析框架。这个框架被广泛用于动态代理、代码分析、混淆和优化等多种场景。ASM Tree 模块的核心目标是将...
ASM Tree库则是ASM框架中的一个模块,它的主要作用是将ASM低级别的字节码操作转化为直观的树形结构,便于开发者理解和处理。在ASM Tree 3.3.1版本中,开发者可以更方便地对Java类的结构进行解析和修改,提供了更高...
包含翻译后的API文档:asm-4.2-javadoc-API文档-中文(简体)版.zip; Maven坐标:org.ow2.asm:asm:4.2; 标签:ow2、中文文档、jar包、java; 使用方法:解压翻译后的API文档,用浏览器打开“index.html”文件,即可...
在这一框架下,ASM (Authenticator Specific Module) 是一个关键组件,它为UAF认证器提供了向上层应用的统一接口,从而使得上层应用能够通过标准的接口来访问和管理不同类型的认证器,如带有SPI、USB或蓝牙等物理...
包含翻译后的API文档:asm-5.0.4-javadoc-API文档-中文(简体)版.zip; Maven坐标:org.ow2.asm:asm:5.0.4; 标签:ow2、jar包、java、API文档、中文版; 使用方法:解压翻译后的API文档,用浏览器打开“index.html”...