Constant pool://常量池
序号 类型 引用
#1 = Methodref #4.#20 // java/lang/Object."<init>":()V
#2 = Fieldref #3.#21 // com/compass/spring_lecture/binarycode/MyTest1.a:I
#3 = Class #22 // com/compass/spring_lecture/binarycode/MyTest1
#4 = Class #23 // java/lang/Object
#5 = Utf8 a
#6 = Utf8 I
#7 = Utf8 <init>
#8 = Utf8 ()V
#9 = Utf8 Code
#10 = Utf8 LineNumberTable
#11 = Utf8 LocalVariableTable
#12 = Utf8 this
#13 = Utf8 Lcom/compass/spring_lecture/binarycode/MyTest1;
#14 = Utf8 getA
#15 = Utf8 ()I
#16 = Utf8 setA
#17 = Utf8 (I)V
#18 = Utf8 SourceFile
#19 = Utf8 MyTest1.java
#20 = NameAndType #7:#8 // "<init>":()V
#21 = NameAndType #5:#6 // a:I
#22 = Utf8 com/compass/spring_lecture/binarycode/MyTest1
#23 = Utf8 java/lang/Object
-
使用javap -verbose 命令分析一个字节码文件时,将会分析该字节码文件的魔数、版本号、常量池、类信息、类的构造方法、类的方法信息、类变量和成员变量等信息。
-
魔数:magic number 所有的.class字节码文件的前4个字节都是魔数,魔数值是固定值:0xCAFEBABE.咖啡宝贝
-
魔数之后的4个字节为版本信息,前2个字节表示minor version(次版本号),后2个字节表示major version(主版本号) 这里的版本号为 00 00 00 34,换算成十进制表示次版本号为0,而主版本号为52 (jdk8) 所以该文件的版本号为1.8.0,可以通过 java -version命令来验证这一点。
安装的jdk可以通过这个版本号来确定这个class文件是否能够加载,JDK是向下兼容的,1.8的版本可以加载version<1.8的jdk编译的class文件。 -
常量池(constant pool):紧接着主版本号之后的就是常量池入口,常量池的长度是不确定的,一个java类中定义的很多信息都是由常量池来维护和描述的,可以将常量池看作是class文件的资源仓库,比如说java类中定义的方法与变量信息,都是存储在常量池中的,常量池中主要存储两类常量:字面量和符号引用[符号引用转换成直接引用]。字面量比如说文本字符串,java中声明为final的常量值等。而符号引用如类和接口的全局限定名,字段的名称和描述符,方法的名称和描述符等。
-
常量池的总体结构:
java类对应的常量池主要由常量池数量和常量池数组(表结构)这2部分共同组成,可以最大限度地压缩字节码的体积,常量池数量紧跟在主版本后面,占据2个字节,常量池数组紧跟在常量池数量之后。常量池数组与一般的数组不同的是,常量池数组中不同的元素的类型、结构都是不同的。长度当然也就不同,但是每一种元素的第一个数据都是一个u1类型,该字节是一个标志位,占据一个1个字节,JVM在解析常量池的时候,会根据这个u1类型来获取对应元素的具体类型。分析字节码:00 18 共有24个常量,反编译字节码中只有23个。为什么呢? 值得注意的是:常量池中元素的个数=常量池数-1(其中0暂时不使用)。目的是满足某些常量池索引值的数据在特定的情况下需要表达[不引用任何的常量池]的含义,根本原因在于,索引为0也是一个常量(保留常量),只不过它不位于常量表中。这个常量就对应null值,索引常量池的索引从1而非0开始。 -
在JVM规范中,每个变量/字段都有描述信息,描述信息主要的作用是描述字段的数据类型、方法的参数列表(包括数量、类型与顺序)与返回值,根据描述符的规则,基本数据类型和代表无返回值的void类型都用一个大写字符表示,对象类型则使用字符L加上对象的全局限定名称来表示。为了压缩字节码文件的体积,对于基本的数据类型,JVM都只是用一个大写字母来表示,如下所示:B-byte,C-char,D-double,I-int,F-float,J-long,S-short,Z-boolean,V-void ,L-对象类型,如Ljava/lang/String;
-
对于数组类型来说,每一个维度使用一个前置的[表示,如int[]被记录成[I,String[][]被记录成[[Ljava/lang/String;
-
用描述符来描述方法的时候,按先参数列表后返回值的顺序进行描述,参数列表按照参数的严格顺序放在一组()之内,如方法 String getNameByAndIdcNo(int id,String idcNo)的描述符为:(I,Ljava/lang/String;)getNameByAndIdcNo Ljava/lang/String;
Utf8类型是01
Methodref是10
Fieldref是9
Class是7
NameAndType是12
分析过程:
07 7 根据类型表找到对应的类型是CONSTANT_Class_info :
index(U2) 00 16(22 指向全限定名常量项的索引)
#3 = Class #22 // com/compass/spring_lecture/binarycode/MyTest1
#22 = Utf8 com/compass/spring_lecture/binarycode/MyTest1
---
07 表示7 根据类型表找到对应的类型是CONSTANT_Class_info :
index(U2) 00 17(23 指向全限定名常量项的索引)
#4 = Class #23 // java/lang/Object
##23 = Utf8 java/lang/Object
---
01 表示1 根据类型表找到对应的类型是CONSTANT_utf8_info:
length(U2) 00 01 (1 表示utf8编码的字符串长度)长度是1
byte(U1) 61 (97 表示长度为length的utf8编码的字符串)表示a
#5 = Utf8 a
---
01 表示1 根据类型表找到对应的类型是CONSTANT_utf8_info:
length(U2) 00 01 (1 表示utf8编码的字符串长度)长度是1
byte(U1) 49 (73 表示长度为length的utf8编码的字符串)表示I(A:65 B:66...I:73)
#6 = Utf8 I
---
#7 = Utf8 <init>
查看对应的ASCII表
http://ascii.911cha.com/
....
ca fe ba be 00 00 00 34 00 18
-----------------------------------------------常量池开始
0a 00 04 00 14 09
00 03 00 15 07 00 16 07 00 17 01 00 01 61 01 00
01 49 01 00 06 3c 69 6e 69 74 3e 01 00 03 28 29
56 01 00 04 43 6f 64 65 01 00 0f 4c 69 6e 65 4e
75 6d 62 65 72 54 61 62 6c 65 01 00 12 4c 6f 63
61 6c 56 61 72 69 61 62 6c 65 54 61 62 6c 65 01
00 04 74 68 69 73 01 00 2f 4c 63 6f 6d 2f 63 6f
6d 70 61 73 73 2f 73 70 72 69 6e 67 5f 6c 65 63
74 75 72 65 2f 62 69 6e 61 72 79 63 6f 64 65 2f
4d 79 54 65 73 74 31 3b 01 00 04 67 65 74 41 01
00 03 28 29 49 01 00 04 73 65 74 41 01 00 04 28
49 29 56 01 00 0a 53 6f 75 72 63 65 46 69 6c 65
01 00 0c 4d 79 54 65 73 74 31 2e 6a 61 76 61 0c
00 07 00 08 0c 00 05 00 06 01 00 2d 63 6f 6d 2f
63 6f 6d 70 61 73 73 2f 73 70 72 69 6e 67 5f 6c
65 63 74 75 72 65 2f 62 69 6e 61 72 79 63 6f 64
65 2f 4d 79 54 65 73 74 31 01 00 10 6a 61 76 61
2f 6c 61 6e 67 2f 4f 62 6a 65 63 74
-----------------------------------------------常量池结束
00 21 00 03
00 04 00 00 00 01 00 02 00 05 00 06 00 00 00 03
00 01 00 07 00 08 00 01 00 09 00 00 00 38 00 02
00 01 00 00 00 0a 2a b7 00 01 2a 04 b5 00 02 b1
00 00 00 02 00 0a 00 00 00 0a 00 02 00 00 00 04
00 04 00 06 00 0b 00 00 00 0c 00 01 00 00 00 0a
00 0c 00 0d 00 00 00 01 00 0e 00 0f 00 01 00 09
00 00 00 2f 00 01 00 01 00 00 00 05 2a b4 00 02
ac 00 00 00 02 00 0a 00 00 00 06 00 01 00 00 00
0a 00 0b 00 00 00 0c 00 01 00 00 00 05 00 0c 00
0d 00 00 00 01 00 10 00 11 00 01 00 09 00 00 00
3e 00 02 00 02 00 00 00 06 2a 1b b5 00 02 b1 00
00 00 02 00 0a 00 00 00 0a 00 02 00 00 00 0e 00
05 00 0f 00 0b 00 00 00 16 00 02 00 00 00 06 00
0c 00 0d 00 00 00 00 00 06 00 05 00 06 00 01 00
01 00 12 00 00 00 02 00 13
网友评论