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方法中添加这个变量。

时间: 2024-10-05 10:44:14

ASM学习笔记--ASM 4 user guide 第二章要点翻译总结的相关文章

ASM学习笔记--ASM 4 user guide 第一章翻译

第一章 介绍 1.1动机 程序分析.生成和转换是非常有用的技术,它具有以下的应用场景: l  程序分析(包括从简单的综合性分析到一个全面的语义分析)可以被用来寻找潜在的bug,发现未使用的代码,进行工程代码的逆向. l  程序生成被用在编译器当中.这包括传统的编译器,也包括为分布式编程使用的stub或skeleton 编译器,即时编译器等 l  程序转换可以被用来优化或者混淆程序,为程序插入debugging或者性能检测代码,方便面向对象编程等. 所有这些技术可以被用到任意的编程语言,但是难易程

《python基础教程(第二版)》学习笔记 基础部分(第1章)

<python基础教程(第二版)>学习笔记基础部分(第1章)IDEWindows: IDLE(gui), Eclipse+PyDev; Python(command line);Linux/Unix: python >>> 1/2=0 注意整除得0>>> from __future__ import division 执行普通的除法python -Qnew 执行普通的除法 //整除,  1//2=0:%取余数:**乘幂长整型数: 末尾带L十六进制,以0x开头

课本学习笔记1:第一、二章 20135115臧文君

第一章 Linux内核简介 注:作者:臧文君,原创作品转载请注明出处. 一.Unix的历史 1.1969年,Dennis Ritchie和Ken Thompson,Unix. 2.Unix产生于贝尔试验室的一个失败的多用户操作系统Multics. 第一个被广泛使用的Unix版本是第6版,称为V6. 3.进一步开发: 加州大学伯克利分校:BSD(Berkeley Software Distributions). 4.Unix系统强大的根本原因:策略和机制分离的设计理念,确保了Unix系统具备清晰的

JavaScript高级程序设计(第三版)学习笔记20、21、23章

第20章,JSON JSON(JavaScript Object Notation,JavaScript对象表示法),是JavaScript的一个严格的子集. JSON可表示一下三种类型值: 简单值:字符串,数值,布尔值,null,不支持js特殊值:undefined 对象:一组无序的键值对 数组:一组有序的值的列表 不支持变量,函数或对象实例 注:JSON的字符串必须使用双引号,这是与JavaScript字符串最大的区别 对象 { "name":"Nicholas"

JavaScript高级程序设计(第三版)学习笔记22、24、25章

第22章,高级技巧 高级函数 安全的类型检测 typeof会出现无法预知的行为 instanceof在多个全局作用域中并不能正确工作 调用Object原生的toString方法,会返回[Object NativeConstructorName]格式字符串.每个类内部都有一个[[Class]]属性,这个属性中就指定了上述字符串中的构造函数名. 原生数组的构造函数名与全局作用域无关,因此使用toString方法能保证返回一致的值,为此可以创建如下函数: function isArray(value)

Yii学习笔记之六(HTML生成帮助类api 翻译)

html帮助类 (Html helper) 参考地址:http://www.yiiframework.com/doc-2.0/guide-helper-html.html 每一个web应用都会生成许多的HTML 标签,如果标签是静态的,他就能有效的避免PHP代码和HTML之间的混淆:但是当它是动态生成,它就开始变得棘手处理,不过它无需额外的帮助下完成.Yii 提供了这样的辅助 在一个form 提供了一系列静态的方法来处理生成 HTML标签组件, 以及他们的选项和内容. 提示: 入过你的标签是静态

JavaScript高级程序设计(第三版)学习笔记11、12、17章

第11章, DOM扩展 选择符 API Selector API Level1核心方法querySelector .querySelectorAll,兼容的浏览器可以使用 Document,Element 实例调用它们,支持浏览器:IE8+,Firefox3.5+,Safari3.1+,chrome,Opera10+ querySelector方法 接收一个 CSS选择符,返回与该模式匹配的第一个元素 通过 Document类型调用该函数,会在文档范围查找匹配元素,通过 Element类型调用该

读书笔记_java设计模式深入研究 第二章 反射

1,JDK中反射类包含的内容: -1,Class类,代表一个类. -2,Constructor,代表类的构造方法. -3,Field,代表类成员 -4,Method,代表方法. 2,统一调用形式: 一个基本的使用反射的例子如下: package com.use; import java.lang.reflect.Constructor; import java.lang.reflect.Field; import java.lang.reflect.Method; public class A 

笔记之Cyclone IV 第一卷第二章Cyclone IV器件的逻辑单元和逻辑阵

逻辑单元 (LE) 在 Cyclone IV 器件结构中是最小的逻辑单位.LE 紧密且有效的提供了高级功能的逻辑使用.每个 LE 有以下特性 ■ 一个四口输入的查找表 (LUT),以实现四种变量的任何功能■ 一个可编程的寄存器■ 一个进位链连接■ 一个寄存器链连接■ 可驱动以下的相互连接:■ 本地■ 行■ 列■ 寄存器链■ 直联■ 寄存器套包支持■ 寄存器反馈支持 您可以对每个 LE 配置可编程的寄存器为 D. T. JK, 或 SR 触发器操作.每个寄存器上有数据,时钟,时钟使能和清零输入.全