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

ASM系列六 利用TreeApi 添加和移除类成员

阅读更多

    同生成的做法一样,添加和移除类成员只要去修改fieldsmethods中的元素即可。这里我们拿一个简单的类做例子,下面这个Task类,我们来移除isNeedRemove方法,并且添加一个int 类型的addedField属性。

 

package asm.core;

/**
 * Created by yunshen.ljy on 2015/6/8.
 */
public class Task {

    private int isTask = 0;

    public void tellMe(){
        System.out.println("call tellMe");
    }

    public void isNeedRemove(){
        // do sth
    }
}

        首先我们可以构建一个Transformer用来处理ClassNode 中的fieldsmethods列表。为了方便维护和扩展,我们创建两个Transformer。一个RemoveMethodTransformer来移除方法,一个AddFieldTransformer来添加field

 

 

        读取Task的字节码,可以通过Core Api ClassReader,而且因为ClassNode继承了ClassVisitor,所以我们可以通过ClassReaderaccept方法来处理,这里依旧是将ClassReader当做一个生产者,ClassNode是消费者。而且,有趣的是,ClassNode也有一个accept方法,也就是说,可以传递本身的事件给一个ClassVisitor。这个ClassVisitor会继续“消费”所有ClassNode 属性中的事件。

 

        先来看一下RemoveMethodTransformer的实现:

package asm.tree;

import org.objectweb.asm.tree.ClassNode;
import org.objectweb.asm.tree.MethodNode;

import java.util.Iterator;

/**
 * Created by yunshen.ljy on 2015/7/12.
 */
public class RemoveMethodTransformer {
    private String fieldName;
    private String fieldDesc;

    public RemoveMethodTransformer(String fieldName, String fieldDesc) {
        this.fieldName = fieldName;
        this.fieldDesc = fieldDesc;
    }

    public void transform(ClassNode cn) {
        Iterator<MethodNode> i = cn.methods.iterator();
        while (i.hasNext()) {
            MethodNode mn = i.next();
            if (mn.name.equals(fieldName) ) {
                i.remove();
            }
        }
    }
}

    可以看到transform方法利用迭代器来直接处理ClassNode对象的methods列表。下面再看一下AddFieldTransformer的实现。

package asm.tree;

import org.objectweb.asm.tree.ClassNode;
import org.objectweb.asm.tree.FieldNode;

/**
 * Created by yunshen.ljy on 2015/7/12.
 */
public class AddFieldTransformer   {
    private int fieldAccess;
    private String fieldName;
    private String fieldDesc;

    public AddFieldTransformer(int fieldAccess, String fieldName, String fieldDesc) {
        this.fieldAccess = fieldAccess;
        this.fieldName = fieldName;
        this.fieldDesc = fieldDesc;
    }

    public void transform(ClassNode cn) {
        boolean isPresent = false;
        for (Object fn : cn.fields) {
            FieldNode ff = (FieldNode) fn;
            if (fieldName.equals(ff.name)) {
                isPresent = true;
                break;
            }
        }
        if (!isPresent) {
            cn.fields.add(new FieldNode(fieldAccess, fieldName, fieldDesc, null, null));
        }
    }

}

    最后,测试并利用ClassWriter来输出处理后的二进制字节流。我们刚好可以利用ClassNodeaccept方法来让ClassWriter 能够Visit整个class,并且输出字节数组。

 ClassReader cr = new ClassReader("asm.core.Task");
        ClassNode cn = new ClassNode();
        cr.accept(cn,0);
        RemoveMethodTransformer rt = new RemoveMethodTransformer("isNeedRemove","V");
        rt.transform(cn);
        AddFieldTransformer at= new AddFieldTransformer(Opcodes.ACC_PRIVATE,"addedField","I");
        at.transform(cn);
        ClassWriter cw = new ClassWriter(0);
        cn.accept(cw);
        byte[] toByte = cw.toByteArray();

    当然,也可以自己写一个Adapter,来封装ClassNode的处理。通过构造器来传递ClassWriter,如下,accept方法封装到visitEnd方法中,来绑定下一个消费事件:

public class MyClassAdapter extends ClassNode {

    public MyClassAdapter(ClassVisitor cv) {
        super(Opcodes.ASM4);
        this.cv = cv;
    }

    @Override
    public void visitEnd() {
        accept(cv);
    }
}

   或者再增加一层代理来传递:

package asm.tree;

import org.objectweb.asm.ClassVisitor;
import org.objectweb.asm.Opcodes;
import org.objectweb.asm.tree.ClassNode;

/**
 * Created by yunshen.ljy on 2015/7/14.
 */
public class MyClassAdapter extends ClassVisitor {

    private ClassVisitor next;
    public MyClassAdapter(ClassVisitor cv) {
        super(Opcodes.ASM4,new ClassNode());
        this.next = cv;
    }

    @Override
    public void visitEnd() {
        ClassNode cn = (ClassNode)cv;
        cn.accept(cv);
    }
}

 

 

 

 

 

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

相关推荐

    asm-tree.jar

    ASM Tree库则是ASM框架中用于构建和解析抽象语法树(Abstract Syntax Tree, AST)的模块,对于理解、修改和生成Java类的字节码有着至关重要的作用。 在Java世界里,字节码是Java类的二进制表示形式,它是由JVM执行...

    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" 指出,这些jar文件是CGlib库的一部分,它是一个强大的、高性能的代码生成库,广泛用于创建Java动态代理和增强现有类。...

    asm-tree-2.2.3.jar.zip

    这个JAR文件包含了所有的类和资源,使得我们能够在程序中直接引用ASM Tree的相关API,进行字节码操作和解析。 "asm-2.2.1.jar.license.txt"则可能是ASM库的许可协议文件,详细规定了使用ASM库的法律条款和限制。...

    asm-tree-3.3.jar.zip

    "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(3.0 /3.3)

    ASM是一个强大的库,它允许程序动态生成和分析Java类。在Java世界中,这通常用于创建元编程框架、代码生成工具以及对Java字节码进行低级操作。 在`asm-tree` 3.0和3.3这两个不同版本中,有一些关键性的变化和改进。...

    asm-tree-3.2.jar.zip

    《ASM Tree库3.2版本详解与应用》 ASM是一个Java字节码操控和分析框架,它可以直接解析和生成Java字节码...通过理解其核心概念、版本特性以及实践操作,开发者能够更好地利用ASM Tree来实现复杂的代码生成和分析任务。

    asm-tree-3.3.1.jar

    例如,可以使用ASM Tree API遍历一个类的整个字节码结构,查找并修改特定的指令或属性,或者在运行时动态生成新的类和方法。此外,由于ASM Tree API具有较高的抽象层次,因此它适用于各种类型的Java字节码操作,无论...

    asm-tree-2.1.jar.zip

    ASM是一个Java字节码操控和分析框架,它可以直接解析和生成Java类文件,而ASM Tree库则是ASM框架的一部分,它提供了将字节码转换为抽象语法树(AST)的能力,进而便于进行代码分析和修改。本文将详细介绍ASM Tree ...

    asm-tree-3.3.1.jar.zip

    动态代理可以利用ASM Tree来快速生成代理类,实现方法拦截;代码生成则可以自动生成符合特定需求的Java类或方法;字节码插桩则是在编译后的字节码层面插入额外的代码,以实现性能监控、调试或者其他高级功能。 在...

    asm-tree-3.1.jar.zip

    《ASM Tree库3.1版本解析与应用》 ASM是一个Java字节码操控和分析框架,它可以直接操作和生成中间...通过理解和利用ASM Tree库,开发者可以在Java字节码层面上实现各种高级功能,如动态代理、代码混淆、性能优化等。

    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.3.zip_asm-tree-3.3.jar_tree

    ASM Tree 模块的核心目标是将字节码转换为一棵抽象语法树(Abstract Syntax Tree, AST),这使得开发者能够更方便地理解和操作Java类的结构。 "asm-tree-3.3.zip_asm-tree-3.3.jar_tree"这个标题表明我们关注的是...

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

    它利用ASM库和Android的transform API,实现了对R类中常量整型字段的内联处理,从而达到减小APK体积的目的。 首先,我们需要理解R类的作用。在Android应用中,R类是由编译器自动生成的,用于存储资源的ID,如布局、...

    asm-tree-1.3.5.jar.zip

    "asm-tree-1.3.5.jar"是这个版本的ASM Tree API的主要组件,它包含所需的类和方法来解析类文件并构建AST。开发者可以使用这些API来分析和修改类的方法体,例如,添加、删除或改变方法的指令。 "asm-2.2.1.jar....

    asm-tree-2.2.1-sources.jar.zip

    ASM Tree库是Java字节码操作框架ASM的一个重要组成部分,其版本2.2.1提供了对Java类结构的树形表示,使得开发者能够更方便地理解和修改字节码。ASM库本身是一个强大的工具,用于动态生成和分析Java字节码,广泛应用...

    asm-tree-5.0.3.jar

    asm-tree-5.0.3.jar

    易语言asm取API地址

    在压缩包中的"易语言asm取API地址源码"文件,很可能是包含了实现这一功能的易语言源代码和相关的汇编代码片段。通过分析这个源码,我们可以深入理解如何在易语言环境中利用汇编语言获取并调用API函数,这涉及到的...

    cglib和asm

    ASM提供了底层的字节码操作能力,而CGlib则在其上构建了一个更易于使用的API,使得开发者无需直接与ASM的复杂接口打交道,就能实现类的动态扩展和代理。CGlib封装了ASM的一些细节,提供了更高级别的抽象,使得开发者...

Global site tag (gtag.js) - Google Analytics