目录
  1. 1. 描述符
    1. 1.1. 定义
    2. 1.2. 描述符的语法符号
    3. 1.3. 描述符分类
      1. 1.3.1. 字段描述符(Field Descriptors)
      2. 1.3.2. 方法描述符(Method Descriptors)
    4. 1.4. 代码举例
    5. 1.5. 文献引用
描述符

描述符

定义

一个描述符是一个表示一个字段或者方法类型的字符串。描述符通常是在class文件中用UTF-8的字符串来表示。

描述符的语法符号

描述符用一种语法来进行规范。描述符的这种语法是一组形成各种语法正确的描述符的字符序列。

描述符分类

字段描述符(Field Descriptors)

字段描述符用来表示一个类,实例或者局部变量。以下就是所有的字段描述符:
field_desc

  1. B C D F I J S Z 都是基本类型在class文件中的表现形式。
  2. "Ljava/lang/String;“则是String类型在class文件中的表现形式,L表示其后的字符串是一个类名,以”;"结尾。
  3. 数组在java中也是一个引用类型,数组在class文件中的表现形式为"[",一个double[][]在class文件中的表现形式为[[D,[后面可以跟其他的字段描述符。

方法描述符(Method Descriptors)

一个方法描述符包含0个或者多个参数描述符(参数都是字段描述符),它表现形式为:({ParameterDescriptor}) ReturnDescriptor。

  1. 一般情况下,一个有返回值的方法表现为:({ParameterDescriptor}) ReturnDescriptor。
1
2
3
4
5
6
java方法:String test(int i , double d , String s)
class形式:(IDLjava/lang/String;)Ljava/lang/String;
int i 对应 I
double d 对应 D
String s 对应 Ljava/lang/String;
返回值String对应 Ljava/lang/String;
  1. 如果是无返回值的方法,则表现为:({ParameterDescriptor}) V
1
2
3
4
5
6
java方法:void test(int i , double d , String s)
class形式:(IDLjava/lang/String;)V
int i 对应 I
double d 对应 D
String s 对应 Ljava/lang/String;
无返回值 对应 V
  1. 如果方法参数总长度在255之内(这个长度包括了实例的this或接口方法调用,long和double占2个长度,其他的占一个长度),则判定一个方法描述符是有效的。
  2. 无论是一个类方法还是一个实例方法,方法相同的话,塔就是同一个方法描述符。虽然一个实例方法传递了this这个本对象引用,但是这个this不会在方法描述符中反映。这个this引用是通过java虚拟机的用来调用实例方法的指令来传递的。

代码举例

  1. 下面是我们需要的代码
1
2
3
4
5
public class Test {
public static void main(String[] args){
System.out.println("Hello world") ;
}
}
  1. 代码编译后,我们通过javap命令,获取class文件的详细信息
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
javac Test.java
javap -v Test

Classfile /home/share/Public/blog/source/_posts/Java/jvm/Test.class
Last modified 2020-1-17; size 413 bytes
MD5 checksum adae6df967b28789efc582efe75101db
Compiled from "Test.java"
public class Test
minor version: 0
major version: 52
flags: ACC_PUBLIC, ACC_SUPER
Constant pool:
#1 = Methodref #6.#15 // java/lang/Object."<init>":()V
#2 = Fieldref #16.#17 // java/lang/System.out:Ljava/io/PrintStream;
#3 = String #18 // Hello world
#4 = Methodref #19.#20 // java/io/PrintStream.println:(Ljava/lang/String;)V
#5 = Class #21 // Test
#6 = Class #22 // java/lang/Object
#7 = Utf8 <init>
#8 = Utf8 ()V
#9 = Utf8 Code
#10 = Utf8 LineNumberTable
#11 = Utf8 main
#12 = Utf8 ([Ljava/lang/String;)V
#13 = Utf8 SourceFile
#14 = Utf8 Test.java
#15 = NameAndType #7:#8 // "<init>":()V
#16 = Class #23 // java/lang/System
#17 = NameAndType #24:#25 // out:Ljava/io/PrintStream;
#18 = Utf8 Hello world
#19 = Class #26 // java/io/PrintStream
#20 = NameAndType #27:#28 // println:(Ljava/lang/String;)V
#21 = Utf8 Test
#22 = Utf8 java/lang/Object
#23 = Utf8 java/lang/System
#24 = Utf8 out
#25 = Utf8 Ljava/io/PrintStream;
#26 = Utf8 java/io/PrintStream
#27 = Utf8 println
#28 = Utf8 (Ljava/lang/String;)V // 这个方法描述符表示:void func(String s)
{
public Test();
descriptor: ()V // 这个方法描述符表示:void func() 这个方法描述符描述的是Test这个类
flags: ACC_PUBLIC
Code:
stack=1, locals=1, args_size=1
0: aload_0
1: invokespecial #1 // Method java/lang/Object."<init>":()V
4: return
LineNumberTable:
line 1: 0

public static void main(java.lang.String[]);
descriptor: ([Ljava/lang/String;)V // 这个方法描述符表示:void func(String[] s) 这个方法描述符描述的是main这个主函数
flags: ACC_PUBLIC, ACC_STATIC
Code:
stack=2, locals=1, args_size=1
0: getstatic #2 // Field java/lang/System.out:Ljava/io/PrintStream;
3: ldc #3 // String Hello world
5: invokevirtual #4 // Method java/io/PrintStream.println:(Ljava/lang/String;)V
8: return
LineNumberTable:
line 3: 0
line 4: 8
}
SourceFile: "Test.java"

文献引用

  1. JNI字段描述符
文章作者: rack-leen
文章链接: http://yoursite.com/2020/01/17/Java/jvm/class%E6%96%87%E4%BB%B6%E6%A0%BC%E5%BC%8F/%E6%8F%8F%E8%BF%B0%E7%AC%A6/
版权声明: 本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来自 rack-leen's blog
打赏
  • 微信
  • 支付宝

评论