问答文章1 问答文章501 问答文章1001 问答文章1501 问答文章2001 问答文章2501 问答文章3001 问答文章3501 问答文章4001 问答文章4501 问答文章5001 问答文章5501 问答文章6001 问答文章6501 问答文章7001 问答文章7501 问答文章8001 问答文章8501 问答文章9001 问答文章9501

ASM是怎样访问及修改编译了的class文件

发布网友 发布时间:2022-04-28 22:54

我来回答

1个回答

热心网友 时间:2022-06-24 17:18

ASM是基于ClassVisitor接口方法的调用顺序,提供了3个核心组件,用于产生和修改转换class
ClassReader解析compiled class的byte数组,其accept方法接受classVisitor的实例参数,按顺序调用它的各个visitXxx方法。将它作为事件的生产者。
ClassWriter直接构建二进制形式的class,toByteArray返回compiled class的byte数组。将它作为事件的消费者
ClassAdapter内部包装了一个ClassVisitor实例,代理所有的ClassVisitor接口方法。将它作为事件过滤器。
package org.objectweb.asm;

public abstract interface ClassVisitor
{
public abstract void visit(int paramInt1, int paramInt2, String paramString1, String paramString2, String paramString3, String[] paramArrayOfString);

public abstract void visitSource(String paramString1, String paramString2);

public abstract void visitOuterClass(String paramString1, String paramString2, String paramString3);

public abstract AnnotationVisitor visitAnnotation(String paramString, boolean paramBoolean);

public abstract void visitAttribute(Attribute paramAttribute);

public abstract void visitInnerClass(String paramString1, String paramString2, String paramString3, int paramInt);

public abstract FieldVisitor visitField(int paramInt, String paramString1, String paramString2, String paramString3, Object paramObject);

public abstract MethodVisitor visitMethod(int paramInt, String paramString1, String paramString2, String paramString3, String[] paramArrayOfString);

public abstract void visitEnd();
}

访问ClassVisitor接口方法的顺序:

visit visitSource? visitOuterClass? ( visitAnnotation | visitAttribute )*
( visitInnerClass | visitField | visitMethod )*
visitEnd

首先必须调用visit, 然后最多访问一次visitSource, 然后最多调用一次visitOuterClass, 然后选出visitAnnotation或者visitAttribute之一,对它访问若干次,
然后选出visitInnerClass或者visitField或者visitMethod 之一, 对它调用若干次
最后必须调用一下visitEnd

以下例子说明了ClassReader如何使用accept方法, 依次按照所谓的顺序,调用 ClassPrinter作为ClassVisitor的实现类的visitXxx方法,访问java.util.Map的。
查看accept方法内部,可以发现这个所谓的调用顺序。

/**
* @{#} ClassPrinter.java Created on Jun 10, 2010 9:37:57 PM
*
* this code example from asm-guide.pdf
* author.
*
*/
package example.me;

import org.objectweb.asm.AnnotationVisitor;
import org.objectweb.asm.Attribute;
import org.objectweb.asm.ClassReader;
import org.objectweb.asm.ClassVisitor;
import org.objectweb.asm.FieldVisitor;
import org.objectweb.asm.MethodVisitor;

public class ClassPrinter implements ClassVisitor {

public void visit(int version, int access, String name, String signature,
String superName, String[] interfaces) {
System.out.println(name + " extends " + superName + " {");
}

public AnnotationVisitor visitAnnotation(String desc, boolean visible) {
return null;
}

public void visitAttribute(Attribute attr) {}

public void visitEnd() {

System.out.println("}");
}

public FieldVisitor visitField(int access, String name, String desc,
String signature, Object value) {
System.out.println(" " + desc + " " + name);
return null;
}

public void visitInnerClass(String name, String outerName,
String innerName, int access) {}

public MethodVisitor visitMethod(int access, String name, String desc,
String signature, String[] exceptions) {
System.out.println(" " + name + desc);
return null;
}

public void visitOuterClass(String owner, String name, String desc) {}

public void visitSource(String source, String debug) {}
public static void main(String[] args) throws Exception {
ClassPrinter cp = new ClassPrinter();
ClassReader cr = new ClassReader("java.util.Map");
/*
* InputStream input = Thread.currentThread().getContextClassLoader()
* .getResourceAsStream( "java.lang.Runnable".replace('.', '/') +
* ".class"); ClassReader cr = new ClassReader(input);
*/
cr.accept(cp, 0); //cp是ClassVisitor的实现类,在accept方法的内部,以既定的顺序调用cp.visitXxx(...)方法,最终输出java.util.Map的编译后class结构
}

}
输出结果:java/util/Map extends java/lang/Object {
size()I
isEmpty()Z
containsKey(Ljava/lang/Object;)Z
containsValue(Ljava/lang/Object;)Z
get(Ljava/lang/Object;)Ljava/lang/Object;
put(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;
remove(Ljava/lang/Object;)Ljava/lang/Object;
putAll(Ljava/util/Map;)V
clear()V
keySet()Ljava/util/Set;
values()Ljava/util/Collection;
entrySet()Ljava/util/Set;
equals(Ljava/lang/Object;)Z
hashCode()I
}
声明声明:本网页内容为用户发布,旨在传播知识,不代表本网认同其观点,若有侵权等问题请及时与本网联系,我们将在第一时间删除处理。E-MAIL:11247931@qq.com
怎么把word 标题第几章和后面的标题中间的位置弄小点?有图片 钢化膜是抗蓝光的好 还是普通的好 都是在官网上买的 价钱都一样 但是抗... 我朋友借我5000块钱,说好5天还的,到现在3个月了人都不见。电话也不借... 有谁知道明年晋城富士康多会招工呢?是不是现在进富士康不好进去了? ...深圳 找工作 几月份去好呢?是年底去,还是二三月去??我是明年... 你们借出去的钱,要回来了吗?你如何看待那些借钱不还的人 别人借我6万元钱,7年了,现在他不认了,借条也丢了怎么办 ...跟他要的时候说还,可就不见还,一直托着还钱时间,当时没写借条... 我在网上认识一个人把钱借给了他没给借条怎么办?他现在也不想还? ...欠我5000块钱,打了借条,请问我有必要起诉他吗,起诉他的费用下来要... 国内比较好的高端女装品牌有哪些? asmcdllection是什么牌子女装 去眼袋按哪个穴位 经络调理:祛除眼袋的有效方法? 按摩眼睛周围的穴位能祛除眼袋吗? 去除眼袋的穴位怎么按 按摩的方法可以去除眼袋吗 怎样去眼袋快? 按摩哪个穴位可以快速消除眼袋 白斗篷先祖是哪个 《光遇》白斗篷要多少心? 光遇如何获得白斗 光遇白斗篷是哪个星座 龙宫里面有什么? 荣耀30怎么样值得购买吗 如果海底真有龙王,或者说是龙这种生物,那这龙算是海鲜吗?? 中国哪里有龙王庙请问中国哪里有拜祭龙王的龙王庙 荣耀30屏幕有30p好吗 龙蛙喜怒文言文翻译 昔有龙王······而休 急`~xx谢谢你的大恩大德啦~ 华为荣耀30系出鸿蒙了吗 checker-qualjar包用途 如何:用反射发出定义泛型方法 JAVA 导入R包还有相应的包 怎么R.id.add_item显示错误 can not be re 红岩第六章读书笔记 解封为什么要填银行卡和预留手机号还有身份证? 葵末时辰是几点钟 逢癸未是什么意思 帮好友解封为什么要提供银行卡号? 癸未日是那一天,举个例子 癸亥年,赓申月,癸未日,己未时 朋友微信封了,微信解封,她说要银行卡后八位,和手机号,是不是骗人的? 中国的60个时辰都是什么? 微信好友辅助验证解封,就一定要身份证很银行卡号吗? 癸未是什么意思鬼 一普通朋友微信说是被封了,让我帮他解封,还说要填银行卡号和身份证号码,这对我有什么影响吗? 青岛优派普环保科技有限公司怎么样? 时辰八字 丁亥年壬子月癸未日10点什么时辰? 八字中的时辰如何区分(每个时辰都分有四个) 唐朝时辰制