上節裏有關於asm的一些基本概念,好比:visit裏的第一個類版本,方法的描述、引用描述等,下面將一一介紹。java
一個Java二進制的類文件,都有一個版本,對應於不一樣的jdk版本。所以ASM中提供了幾個常量來指定一個類的版,這些常量定義在org.objectweb.asm.Opcodes接口中,以下:web
asm中類版本標識 | 對應jdk版本 |
public static final int V1_1 = 196653; | |
public static final int V1_2 = 46; | 1.2 |
public static final int V1_3 = 47; | 1.3 |
public static final int V1_4 = 48; | 1.4 |
public static final int V1_5 = 49; | 1.5 |
public static final int V1_6 = 50; | 1.6 |
public static final int V1_7 = 51; | 1.7 |
public static final int V1_8 = 52; | 1.8 |
在Java二進制文件中使用的是JVM的內部名字,而不是咱們所熟悉的以「.」分割的全限定名,內部名字是以「/」替代「.」的全名。例如:java.lang.String在JVM中的內部名字是java/lang/String。數組
在ASM中能夠使用org.objectweb.asm.Type類中的靜態方法getInternalName(final Class c) 來得到,以下:jvm
package net.zq.test; import org.objectweb.asm.Type; public class ttt { public static void main(String[] args) { System.out.println(Type.getInternalName(String.class)); System.out.println(Type.getInternalName(Integer.class)); System.out.println(Type.getInternalName(ttt.class)); } }
運行結果:
spa
java/lang/String java/lang/Integer net/zq/test/ttt
咱們知道JAVA類型分爲基本類型和引用類型,在JVM中對每一種類型都有與之相對應的類型描述code
基本類型描述以下:接口
java基本類型 |
jvm中的描述 |
boolean | Z |
byte | B |
char | C |
short | S |
int | I |
long | J |
float | F |
double | D |
引用類型描述以下: ip
通常引用類型爲:「L該類型類描述符; 」。如:String類型的域描述符爲 Ljava/lang/String; get
對於數組,其爲:「 [其類型的域描述符;」。如: int[ ] 其描述符爲[Istring
多維數組其則爲: N個[該類型的域描述符 , N表明的是幾維數組。如:int [ ][ ] 其描述符爲[[I
java引用類型 | jvm中的描述 |
String | Ljava/lang/String; |
Object | Ljava/lang/Object; |
int[] | [I |
float[] | [F |
String[] | [Ljava/lang/String; |
Object[] | [Ljava/lang/Object; |
int[ ][ ] | [[I |
float[ ][ ] | [[F |
在ASM中要獲取類的內部描述,能夠使用org.objectweb.asm.Type類中的getDescriptor(final Class c)方法,以下:
package net.zq.test; import org.objectweb.asm.Type; public class ttt { public static void main(String[] args) { System.out.println(Type.getDescriptor(ttt.class)); System.out.println(Type.getDescriptor(String.class)); } }
運行結果:
Lnet/zq/test/ttt; Ljava/lang/String;
分兩部分:
括號中參數部分:用括號括起來裏面的參數描述
返回值類型部分:返回值值類型的描述符
綜合在一塊兒即爲:(參數的描述符-按原順序)返回類型描述符
如:void a(int i,float f) 表示爲 (IF)V
對於無返回值的,用V(表示void)表示
以下:
java層的方法描述 |
二進制文件中的方法描述 |
String test() |
Ljava/lang/String; |
void a(int i,float f) | (IF)V |
void a(Object o) | (Ljava/lang/Object;)V |
int a(int i,String s) | (ILjava/lang/String;)I |
int[] a(int[] i) | ([I)[I |
void set (byte[ ] bytes) | ([B)V |
獲取一個方法的描述,在ASM用org.objectweb.asm.Type.getMethodDescriptor來獲取,以下:
package net.zq.test; import org.objectweb.asm.Type; public class ttt { public static void main(String[] args) throws NoSuchMethodException, SecurityException { java.lang.reflect.Method m = String.class.getMethod("substring", int.class); System.out.println(Type.getMethodDescriptor(m)); } }
運行結果 以下:
(I)Ljava/lang/String;
在org.objectweb.asm.Type類中還提供了其餘不少方法讓咱們去了解一個類,有興趣的能夠能夠深看一下,對於理解類會有很大幫助。