国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 學院 > 開發設計 > 正文

ASM學習筆記--ASM 4 user guide 第二章要點翻譯總結

2019-11-14 23:23:15
字體:
來源:轉載
供稿:網友
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的子類來打印它所訪問的類的信息。

ClassPrintercp=newClassPrinter();ClassReadercr=newClassReader("java.lang.Runnable");cr.accept(cp,0);

由于ClassPrinter是ClassVistor的子類,前面提到了,ClassReader的accept方法需要傳入一個ClassVistor,所以講將cp作為accept的參數。

運行結果是:

java/lang/Runnableextendsjava/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 cwClassVisitor 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 theonly truly correct solution is to add new members by making additional calls inthe visitEnd method. Indeed a class must not contain duplicate members, and theonly way to be sure that a new member is unique is to compare it with all the existingmembers, which can only be done once they have all been visited, i.e. in thevisitEnd method. This is rather constraining. Using generated names that areunlikely to be used by a programmer, such as _counter$ or _4B7F_ is sufficient inpractice 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 thislimitation: it is possible to add new members at any time inside atransformation with this API.

示例:添加一個變量的做法,在visitField中判斷要添加的變量是否已經存在,若不存在,則在visitEnd方法中添加這個變量。


發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
主站蜘蛛池模板: 华坪县| 永靖县| 辽阳市| 陇西县| 宁德市| 长丰县| 突泉县| 财经| 合山市| 五大连池市| 桦甸市| 全椒县| 濮阳市| 汤原县| 翁牛特旗| 长春市| 滨州市| 车致| 三穗县| 霞浦县| 偃师市| 斗六市| 鸡西市| 海伦市| 鹤壁市| 临沂市| 东平县| 武陟县| 安图县| 隆尧县| 静海县| 石泉县| 长沙市| 凌海市| 大同县| 林甸县| 东乡| 游戏| 兴义市| 涪陵区| 谷城县|