https://mingshan.fun/2018/09/18/fully-qualified-name-simple-name-descriptor/
在看Class文件的結構時,我們會遇到這樣幾個概念,全限定名(Fully Qualified Name)、簡單名稱(Simple Name)和描述符(Descriptor),那么這些是什么東東呢?
首先來說全限定名,一個類的全限定名是將類全名的.全部替換為/,示例如下:
me/mingshan/cglib/SampleClass
簡單名稱是指沒有類型和參數修飾的方法或字段名稱,比如一個類的test()方法,它的簡單名稱是test。
那么描述符是什么呢?下面是JVM規范的定義:
A descriptor is a string representing the type of a field or method.
注意描述符的概念是針對Java字節碼的。描述符的作用是用來描述字段的數據類型、方法的參數列表(包括數量、類型以及順序)和返回值。在JVM規范中,定義了兩種類型的描述符,Field Descriptors 和 Method Descriptors。
Field Descriptors
A field descriptor represents the type of a class, instance, or local variable.
字段描述符包含BaseType、ObjectType、ArrayType三部分,對於基本數據類型(byte、char、double、float、int、long、short、boolean)都用一個大寫字母來表示,而對象用字符L加對象的全限定名和;來表示,具體表示如下:
FieldType term Type Interpretation
B byte signed byte
C char Unicode character code point in the Basic Multilingual Plane, encoded with UTF-16
D double double-precision floating-point value
F float single-precision floating-point value
I int integer
J long long integer
L ClassName ; reference an instance of class ClassName
S short signed short
Z boolean true or false
[ reference one array dimension
對於數組類型,每一個維度使用一個前置的[來描述,如一個定義為java.lang.String[][]類型的二維數組,將被記錄為[[Ljava/lang/String;,一個double型數組double[][][]將被記錄為[[[D。
Method Descriptors
A method descriptor contains zero or more parameter descriptors, representing the types of parameters that the method takes, and a return descriptor, representing the type of the value (if any) that the method returns.
方法描述符用來描述方法,一個方法既有參數,又有返回值,那么在用描述符描述方法時,按照先參數列表,后返回值的順序描述。參數列表按照參數的嚴格順序放在一組小括號()內,如下:
( {ParameterDescriptor} ) ReturnDescriptor
注意如果返回值為void,那么就是一個大寫字母V表示。
例如,一個方法的定義如下:
Object m(int i, double d, Thread t) {...}
那么它的描述符就是:
(IDLjava/lang/Thread;)Ljava/lang/Object;
又如方法的參數列表和返回值為空,如下:
void test()
它的描述符為:
()V
最后上代碼分析一波
我們新建Test類,包含一個成員變量和方法。
package me.mingshan.cglib; public class Test { private int a; public String inc(int b) { int c = a + b; return c + "666"; } }
利用javap -c Test來查看字節碼,如下:
public class me.mingshan.cglib.Test { public me.mingshan.cglib.Test(); Code: 0: aload_0 1: invokespecial #1 // Method java/lang/Object."<init>":()V 4: return public java.lang.String inc(int); Code: 0: aload_0 1: getfield #2 // Field a:I 4: iload_1 5: iadd 6: istore_2 7: iload_2 8: invokedynamic #3, 0 // InvokeDynamic #0:makeConcatWithConstants:(I)Ljava/lang/String; 13: areturn }
可以看到Field a:I和(I)Ljava/lang/String;, 沒什么錯^_^