ASM学习笔记--ASM 4 user guide 第二章要点翻译总结
参考:ASM 4 user guide
第一部分 core API
第二章 类
2.1.1概观
编译后的类包括:
l 一个描述部分:包括修饰语(比如public或private)、名字、父类、接口或者注释区域。
l 类中每个域声明的部分。
l 类中每个方法以及构造函数声明的部分。也包含了方法编译后的代码,它是一系列Java字节码指令的形式。
编译后的类结构如下:
2.1.2内部名(internal name)
类或者接口使用内部名,内部名就是类的全限定名,即带斜杠的全称。
例如,String的internal name为 java/lang/String.
2.1.3类型描述符
内部名只被用在类或者接口名字。其他的使用类型描述符。
String is Ljava/lang/String;
类的描述符以L开头,以分号结尾。
数组类型以方括号开头。
2.1.4方法描述
方法描述符以圆括号开始,圆括号中是每个参数的类型(每个参数类型连着写,之间没有空格或者逗号之类),圆括号后面是方法的返回值类型。 方法描述符不包括方法的名字和参数名字。
2.2 接口和组件
2.2.1 描述
ASM API对于产生和转换编译后的类是基于ClassVistor抽象类的。visitField返回一个FieldVistor,这个规则在FieldVistor中也是递归的。
ClassVistor中方法调用的顺序:
visit visitSource? visitOuterClass? ( visitAnnotation | visitAttribute )*
( visitInnerClass | visitField | visitMethod )*
visitEnd
visit必须首先调用,接着最多一个visitSource,接着最多一个visitOuterClass, 接着任意数量个visitAnnotation和visitAttribute,接着任意数量个visitInnerClass、visitField和visitMethod,最后调用visitEnd。
ASM提供了三种基于ClassVisitor API的核心组件来产生和转换类,
l ClassReader类解析一个给定的编译好的类的字节数组,调用ClassVisitor实例中的visitXXX方法,这个ClassVistor实例是作为accept的参数传入的。它可以被看做是事件的生产者。
l ClassWriter类是ClassVistor的子类,它将编译后的类直接以二进制的形式构建。它输出一个包括编译好的类的字节数组(可以通过toByteArray方法获得)。它被看做是事件的消费者。
l ClassVistor类代理了所有的来自其他ClassVistor实例的方法调用。它被看做是事件的过滤者。
2.2.2 解析类
解析一个现有的类需要的组件只是ClassReader。例子,我们需要打印一个类的内容,首先我们写一个ClassVistor的子类来打印它所访问的类的信息。
ClassPrinter cp = new ClassPrinter();
ClassReader cr = new ClassReader("java.lang.Runnable");
cr.accept(cp, 0);
由于ClassPrinter是ClassVistor的子类,前面提到了,ClassReader的accept方法需要传入一个ClassVistor,所以讲将cp作为accept的参数。
运行结果是:
java/lang/Runnable extends java/lang/Object {
run()V
}
注意,有许多方法构建ClassReader实例。可以被访问的类可以是用名字标注的(如上例),或者通过字节数组值或者作为一个InputStream。可以通过ClassLoader的getResourceAsStream方法来获得一个input stream。如:
cl.getResourceAsStream(classname.replace(’.’,
’/’) + ".class");
2.2.3 产生类
为了产生一个类,唯一需要的组件就是ClassWriter组件。
可以借助ClassLoader(说明中有两种方法)动态加载一个产生的类。
2.2.4 转换类
这里讲述将ClassReader和ClassWriter组件一起用,结果就是被Class reader解析的类会被class writer重建。
byte[] b1 = ...;
ClassWriter cw = new ClassWriter(0);
// cv forwards all events to cw
ClassVisitor cv = new ClassVisitor(ASM4, cw) { };
ClassReader cr = new ClassReader(b1);
cr.accept(cv, 0);
byte[] b2 = cw.toByteArray(); // b2 represents the same class as b1
优化:
使用上面的方法,仅仅修改了jdk版本,绝大多数没有改变。b2是通过抓取b1的方式的方式构建的。更高效的做法是直接拷贝不需要改变的部分,这样,这一部分就不需进行解析和产生响应的事件了。ASM可以自动进行这样的优化。
2.2.5 删除类成员
不将函数调用进行转发,相当于相应的类元素被移除了。
但是这样的策略对fields和methods是无法奏效的,因为visitField和visitMethod方法必须有一个返回值,所以此时返回一个null即可。
注意:想要指明一个方法需要同时支出函数名和描述符。因为可能会有很多方法具有相同的名字但是具有不同的参数。
2.2.6添加类成员
和不转发方法调用不同的是,转发的更多就相当于添加了一些类元素。
Note: in fact the
only truly correct solution is to add new members by making additional calls in
the visitEnd method. Indeed a class must not contain duplicate members, and the
only way to be sure that a new member is unique is to compare it with all the existing
members, which can only be done once they have all been visited, i.e. in the
visitEnd method. This is rather constraining. Using generated names that are
unlikely to be used by a programmer, such as _counter$ or _4B7F_ is sufficient in
practice to avoid duplicate members without having to add them in visitEnd.
Note that, as discussed in the first chapter, the tree API does not have this
limitation: it is possible to add new members at any time inside a
transformation with this API.
示例:添加一个变量的做法,在visitField中判断要添加的变量是否已经存在,若不存在,则在visitEnd方法中添加这个变量。
ASM学习笔记--ASM 4 user guide 第二章要点翻译总结的更多相关文章
- 《Thinking in C++》学习笔记(一)【第二章】
第二章 对象的创建与使用 2.1语言的翻译过程 翻译器分为两类:解释器(interpreter)和编译器(compiler). 2.1.1解释器 解释器将源代码转化成一些动作(它可由许多机器指令组成) ...
- ASM学习笔记--ASM 4 user guide 第一章翻译
ASM是什么? 借用别人的话 :ASM 是一个 Java 字节码操控框架.它能被用来动态生成类或者增强既有类的功能. ASM 可以直接产生二进制 class 文件,也可以在类被加载入 Java 虚拟机 ...
- 《python基础教程(第二版)》学习笔记 列表/元组(第2章)
<python基础教程(第二版)>学习笔记 列表/元组(第2章)序列中的下标从0开始x='ABC' ==> x[0]='A', x[1]='B', x[2]='C'负数索引从右边开始 ...
- 《python基础教程(第二版)》学习笔记 基础部分(第1章)
<python基础教程(第二版)>学习笔记 基础部分(第1章)python常用的IDE:Windows: IDLE(gui), Eclipse+PyDev; Python(command ...
- 《Django By Example》第二章 中文 翻译 (个人学习,渣翻)
书籍出处:https://www.packtpub.com/web-development/django-example 原作者:Antonio Melé (译者注:翻译完第一章后,发现翻译第二章的速 ...
- 统计学习导论:基于R应用——第二章习题
目前在看统计学习导论:基于R应用,觉得这本书非常适合入门,打算把课后习题全部做一遍,记录在此博客中. 第二章习题 1. (a) 当样本量n非常大,预测变量数p很小时,这样容易欠拟合,所以一个光滑度更高 ...
- 「学习记录」《数值分析》第二章计算实习题(Python语言)
在假期利用Python完成了<数值分析>第二章的计算实习题,主要实现了牛顿插值法和三次样条插值,给出了自己的实现与调用Python包的实现--现在能搜到的基本上都是MATLAB版,或者是各 ...
- python学习笔记之基础二(第二天)
1.编码转换介绍 unicode是最底层.最纯的,会根据终端的编码进行转化展示 一般硬盘存储或传输为utf-8(因为省空间.省带宽),读入内存中为unicode,二者如何转换 a = ' ...
- MySQL实战45讲学习笔记:日志系统(第二讲)
一.重要的日志模块:redo log 1.通过酒店掌柜记账思路刨析redo log工作原理 2.InnoDB 的 redo log 是固定大小的 只要赊账记录在了粉板上或写了账本上,之后即使掌柜忘记了 ...
随机推荐
- 参考分享《Python深度学习》高清中文版pdf+高清英文版pdf+源代码
学习深度学习时,我想<Python深度学习>应该是大多数机器学习爱好者必读的书.书最大的优点是框架性,能提供一个"整体视角",在脑中建立一个完整的地图,知道哪些常用哪些 ...
- CSUOJ 1549 Navigition Problem
1549: Navigition Problem Time Limit: 1 Sec Memory Limit: 256 MBSubmit: 65 Solved: 12 Description N ...
- Python3爬虫之爬取某一路径的所有html文件
要离线下载易百教程网站中的所有关于Python的教程,需要将Python教程的首页作为种子url:http://www.yiibai.com/python/,然后按照广度优先(广度优先,使用队列:深度 ...
- sigprocmask, sigpending, sigsuspend的用法
sigset_t set sigemptyset(&set) :清空阻塞信号集合变量 sigfillset(&set) :添加所有的信号到阻塞集合变量里 sigaddset(& ...
- C#接口,类,集成
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.T ...
- 深入浅出微服务框架dubbo(一):基础篇
一.基础篇 1.1 开篇说明 dubbo是一个分布式服务框架,致力于提供高性能透明化RPC远程调用方案,提供SOA服务治理解决方案.本文旨在将对dubbo的使用和学习总结起来,深入源码探究原理,以备今 ...
- #学习笔记#——JavaScript 数组部分编程(七)
24.柯里化 首先想解释一下,“柯里化”的意思, [在计算机科学中,柯里化(Currying)是把接受多个参数的函数变换成接受一个单一参数(最初函数的第一个参数)的函数,并且返回接受余下的参数且返回结 ...
- npm更新方法
今天npm的版本更新发现小于3.0 尝试了npm install npm -g 安装么有成功换成了 cnpm install npm -g安装之后就可以
- RPC简易学习
0.RPC简介 RPC, 英文全称:Remote Process Call. 中文全称:远程过程调用. 客户端通过网络请求调用远程服务端对外暴露服务.常用的两种RPC协议:TCP.HTTP. ...
- chfn---改变finger命令显示的信息
chfn命令 chfn命令用来改变finger命令显示的信息.这些信息都存放在/etc目录里的passwd文件里.若不指定任何选项,则chfn命令会进入问答式界面. 语法 chfn(选项)(参数) ...