`
lijingyao8206
  • 浏览: 217101 次
  • 性别: Icon_minigender_2
  • 来自: 杭州
社区版块
存档分类
最新评论

ASM系列七 TreeApi Method组件和接口介绍

阅读更多

一、MethodNode概述  

 

      ASMTreeApi 对于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。这样就可以像CoreApiMethodVisitor提供的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这样一个链表结构中。当然,这个链表结构也维系了整个字节码指令的结构。

1
1
分享到:
评论
1 楼 haohaokan123 2015-08-10  
膜拜中!!新手值得收藏的中文API帮助,新手且英文不好的福音,全是中文翻译的,一个很不错的中文API帮助
需要的朋友自己去看看。www.apicx.com

相关推荐

    asm-tree-3.3.1.jar

    asm-tree-3.3.1.jar是ASM项目的一个组件,它为Java字节码提供了树状API。这个库主要用于处理由无符号数和表两种数据结构组成的Class字节码。 ASM Tree API可以视为对上述两种数据结构的抽象表达方式,它以树形结构...

    asm-6.0-API文档-中英对照版.zip

    赠送原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.jar

    asm-tree 跟大家分享一下,赶快下载吧

    asm-tree-5.0.3.jar

    asm-tree-5.0.3.jar

    asm-tree-3.3.1.jar.zip

    标签:asm-tree-3.3.1.jar.zip,asm,tree,3.3.1,jar.zip包下载,依赖包

    shrinker,用asm和transform api实现android r类的内联常量字段.zip

    收缩器将删除所有r.class和r\$**.class,所有常量整型字段将由asm和transform api内联。

    asm-9.1-API文档-中文版.zip

    包含翻译后的API文档:asm-9.1-javadoc-API文档-中文(简体)版.zip; Maven坐标:org.ow2.asm:asm:9.1; 标签:ow2、jar包、java、中文文档; 使用方法:解压翻译后的API文档,用浏览器打开“index.html”文件,即可...

    asm-tree(3.0 /3.3)

    asm-tree(3.0 /3.3) 不同版本, 资源共享,有需要其他jar包的可以在评论留言,看到后我会陆续上传。

    cglib-2.2.jar asm-tree.jar asm-commons.jar asm.jar

    cglib动态代理模式jar包 cglib-2.2.jar asm-tree.jar asm-commons.jar asm.jar

    asm-9.1-API文档-中英对照版.zip

    包含翻译后的API文档:asm-9.1-javadoc-API文档-中文(简体)-英语-对照版.zip; Maven坐标:org.ow2.asm:asm:9.1; 标签:ow2、jar包、java、中英对照文档; 使用方法:解压翻译后的API文档,用浏览器打开“index....

    易语言asm取API地址

    易语言asm取API地址源码,asm取API地址,asm_取api地址_调用api,Ox16,取变量地址_文本型_

    asm-tree-2.2.3.jar.zip

    标签:asm-tree-2.2.3.jar.zip,asm,tree,2.2.3,jar.zip包下载,依赖包

    asm-tree-3.2.jar.zip

    标签:asm-tree-3.2.jar.zip,asm,tree,3.2,jar.zip包下载,依赖包

    asm-5.0.4-API文档-中文版.zip

    包含翻译后的API文档:asm-5.0.4-javadoc-API文档-中文(简体)版.zip; Maven坐标:org.ow2.asm:asm:5.0.4; 标签:ow2、jar包、java、API文档、中文版; 使用方法:解压翻译后的API文档,用浏览器打开“index.html”...

    asm-tree-3.3.jar.zip

    标签:asm-tree-3.3.jar.zip,asm,tree,3.3,jar.zip包下载,依赖包

    asm-tree-3.3.jar

    this is a lib for java named : asm-tree-3.3.jar

    asm-4.2-API文档-中文版.zip

    包含翻译后的API文档:asm-4.2-javadoc-API文档-中文(简体)版.zip; Maven坐标:org.ow2.asm:asm:4.2; 标签:ow2、中文文档、jar包、java; 使用方法:解压翻译后的API文档,用浏览器打开“index.html”文件,即可...

    asm-7.1-API文档-中文版.zip

    包含翻译后的API文档:asm-7.1-javadoc-API文档-中文(简体)版.zip; Maven坐标:org.ow2.asm:asm:7.1; 标签:ow2、jar包、java、中文文档; 使用方法:解压翻译后的API文档,用浏览器打开“index.html”文件,即可...

    asm-6.2.1-API文档-中英对照版.zip

    包含翻译后的API文档:asm-6.2.1-javadoc-API文档-中文(简体)-英语-对照版.zip; Maven坐标:org.ow2.asm:asm:6.2.1; 标签:ow2、asm、中英对照文档、jar包、java; 使用方法:解压翻译后的API文档,用浏览器打开...

Global site tag (gtag.js) - Google Analytics