一、常量池的内容

一个java类中定义的很多信息都是由常量池来维护和描述的,可以将常量池看作是class文件的资源仓库,比如java类中定义的方法与变量信息。常量池中主要存储两类常量:字面量(文本字符串,final的常量)与符号引用(类和接口的全限定名,字段的名称和描述符,方法的名称和描述符

一、常量池的结构

二、常量池的分析

常量池(也称常量表):主版本号之后就是常量池的开始位置;java类所对应的常量池主要由常量池数量和常量池数组两部分组成,常量池数量是主版本号之后的两个字节;常量池数组在常量池数量之后,常量池数组中不同元素的类型,结构是不同的,所以该数组长度是不同的,但是数组中的每一种元素的第一个字节是标记位是一个u1类型,JVM在解析常量池时会根据这u1类型来获取元素的具体类型。

1、常量池元素的数量:

00 18(24):就是该class字节码文件的常量池数量; 常量池数组元素的个数=常量池数量-1;索引为0的位置暂不使用,目的是满足某些常量池索引值的数据在特定情况下需要表达,不引用任何一个常量池的含义。根本原因是索引为零也是一个常量,只是他不在常量池中,该常量对应null值,所以常量池的索引从1开始(#1)。

 

 2、常量池数组

第一个元素:根据Constant pool 中 #1的描述可知该元素是无参的构造函数

0A(10):常量池元素数量之后的第一个字节,u1=10 对应

 第一个u2(4):占两个字节即00 04;第二个u2(20):占两个字节即00 14;所以该常量池的第一个元素占五个字节即0A 00 04 00 14

第二个元素:根据 Constant pool  中#2的描述可知该元素是在类ByteCodeTest中一个int 类型 名字为num的变量,

09(9):第一个元素之后的第一个字节 ,u1=9 对应

 第一个u2(3):占两字节00 03;第二个u2(15):占两个字节00 15;所以该常量池的第二个元素占五个字节即09 00 03 00 15

 第三个元素:根据 Constant pool  中#3 可知该元素是该类的权限定名。

07(7):第二个元素之后的第一个字节07 ,u1=7 对应

 

 

 u2(16):占两个字节00 16;所以该常量池的第三个元素占三个字节即07 00 16

第四个元素:根据 Constant pool  中#4 可知该元素是该Object类的权限定名。

07(7):第三个元素之后的第一个字节07 ,u1=7 对应

 u2(17):占两个字节00 17;所以该常量池的第四个元素占三个字节即07 00 17

第五个元素:根据Constant pool  中#5的描述该元素是字符num

01(1):第四个元素之后的第一个字节01 ,u1=1 对应

 

 u2(03):占两个字节00 03,表示utf-8格式的内容对应的长度是3个字节;u1:对应三个字节 6e  75 6d, 所以该常量池的第五个元素占6个字节即01 00 03 6e 75 6d;0x6e756d转字符串=num;

Hex转字符串工具

第六个元素:根据Constant pool  中#5的描述该元素是字符I

01(1):第五个元素之后的第一个字节01 ,u1=1 对应

 u2(01):占两个字节00 01,表示utf-8格式的内容对应的长度是1个字节;u1(73):对应1个字节 49; 所以该常量池的第刘个元素占4个字节即01 00 01 49;49转十进制73;

根据ASCII字码表可知49==73=I;

二进制 十进制 十六进制 图形
0010 0000 32 20 (空格)(␠)
0010 0001 33 21 !
0010 0010 34 22
0010 0011 35 23 #
0010 0100 36 24 $
0010 0101 37 25  %
0010 0110 38 26 &
0010 0111 39 27
0010 1000 40 28 (
0010 1001 41 29 )
0010 1010 42 2A *
0010 1011 43 2B +
0010 1100 44 2C ,
0010 1101 45 2D
0010 1110 46 2E .
0010 1111 47 2F /
0011 0000 48 30 0
0011 0001 49 31 1
0011 0010 50 32 2
0011 0011 51 33 3
0011 0100 52 34 4
0011 0101 53 35 5
0011 0110 54 36 6
0011 0111 55 37 7
0011 1000 56 38 8
0011 1001 57 39 9
0011 1010 58 3A :
0011 1011 59 3B ;
0011 1100 60 3C <
0011 1101 61 3D =
0011 1110 62 3E >
0011 1111 63 3F ?
 
二进制 十进制 十六进制 图形
0100 0000 64 40 @
0100 0001 65 41 A
0100 0010 66 42 B
0100 0011 67 43 C
0100 0100 68 44 D
0100 0101 69 45 E
0100 0110 70 46 F
0100 0111 71 47 G
0100 1000 72 48 H
0100 1001 73 49 I
0100 1010 74 4A J
0100 1011 75 4B K
0100 1100 76 4C L
0100 1101 77 4D M
0100 1110 78 4E N
0100 1111 79 4F O
0101 0000 80 50 P
0101 0001 81 51 Q
0101 0010 82 52 R
0101 0011 83 53 S
0101 0100 84 54 T
0101 0101 85 55 U
0101 0110 86 56 V
0101 0111 87 57 W
0101 1000 88 58 X
0101 1001 89 59 Y
0101 1010 90 5A Z
0101 1011 91 5B [
0101 1100 92 5C \
0101 1101 93 5D ]
0101 1110 94 5E ^
0101 1111 95 5F _
 
二进制 十进制 十六进制 图形
0110 0000 96 60 `
0110 0001 97 61 a
0110 0010 98 62 b
0110 0011 99 63 c
0110 0100 100 64 d
0110 0101 101 65 e
0110 0110 102 66 f
0110 0111 103 67 g
0110 1000 104 68 h
0110 1001 105 69 i
0110 1010 106 6A j
0110 1011 107 6B k
0110 1100 108 6C l
0110 1101 109 6D m
0110 1110 110 6E n
0110 1111 111 6F o
0111 0000 112 70 p
0111 0001 113 71 q
0111 0010 114 72 r
0111 0011 115 73 s
0111 0100 116 74 t
0111 0101 117 75 u
0111 0110 118 76 v
0111 0111 119 77 w
0111 1000 120 78 x
0111 1001 121 79 y
0111 1010 122 7A z
0111 1011 123 7B {
0111 1100 124 7C |
0111 1101 125 7D }
0111 1110 126 7E ~

其他元素分析方式与此相同就不再分析

三、JVM描述符

在jvm规范中,每个变量或字段都有描述信息,描述信息主要的作用是描述字段的数据类型,方法的参数列表(包括数量,类型与顺序)与返回值。
1、为了压缩字节码文件的体积,JVM对于基本数据类型和代表无返回值的void类型都用一个大写字符来表示,而对象类型用字符L加对象的全限定类名来表示
如下表示:B–byte,C–Char,D–double,F–float,I–int,J–long,S–short,Z–boolean,V–void,L–对象类型如Ljava/lang/String。

 

2、对于数组来说,每一个维度使用一个前置的[来表示,如Int[]表示为[I,String[][]表示为[[Ljava/kang/Stirng;

 

 3、用描述符来描述方法时,用先参数列表后返回值的顺序来描述,参数列表按照参数的严格顺序放在一组()之内,如方法:String getNameById(int id,String name)的描述符为:(I,Ljava/lang/String) Ljava/lang/String;

    public String getNameById(int id,String name){
        return name;
    }

posted on
2020-01-05 17:25 
君子生非异也 
阅读(
评论(
编辑 
收藏

版权声明:本文为jalja365原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://www.cnblogs.com/jalja365/p/12152675.html