Java 虚拟机原理Class 字节码二进制文件分析 二 ( 常量池位置 | 常量池结构 | tag | info[] | 完整分析字节码文件中的常量池二进制数据 )
Posted 韩曙亮
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Java 虚拟机原理Class 字节码二进制文件分析 二 ( 常量池位置 | 常量池结构 | tag | info[] | 完整分析字节码文件中的常量池二进制数据 )相关的知识,希望对你有一定的参考价值。
文章目录
前言
接上一篇博客 【Java 虚拟机原理】Class 字节码二进制文件分析 一 ( 字节码文件附加信息 | 魔数 | 次版本号 | 主版本号 | 常量池个数 ) ;
一、常量池结构分析
1、常量池位置
下图的红框内是常量池 , 在 " 常量池计数器 " 后面的若干字节 ;
第 10 10 10 字节及之后的若干字节是常量池范围 ;
不同的字节码文件 , 常量池的范围是不同的 ;
2、常量池结构
常量池的结构如下 :
3、常量池单个常量
常量池中的单个常量 : 每个常量 都是如下 cp_info 格式的数据 ;
4、常量池单个常量 tag 标签
常量池的 tag 以及代表的含义 :
二、常量池字节码文件分析
0、常量池附加信息
完整的常量池 字节码附加信息 :
Constant pool:
#1 = Methodref #4.#17 // java/lang/Object."<init>":()V
#2 = Fieldref #3.#18 // Student.name:Ljava/lang/String;
#3 = Class #19 // Student
#4 = Class #20 // java/lang/Object
#5 = Utf8 name
#6 = Utf8 Ljava/lang/String;
#7 = Utf8 <init>
#8 = Utf8 ()V
#9 = Utf8 Code
#10 = Utf8 LineNumberTable
#11 = Utf8 getName
#12 = Utf8 ()Ljava/lang/String;
#13 = Utf8 setName
#14 = Utf8 (Ljava/lang/String;)V
#15 = Utf8 SourceFile
#16 = Utf8 Student.java
#17 = NameAndType #7:#8 // "<init>":()V
#18 = NameAndType #5:#6 // name:Ljava/lang/String;
#19 = Utf8 Student
#20 = Utf8 java/lang/Object
1、常量池 #1 常量分析
#1 常量分析 : tag 值为 0A
; tag 值为 10 的时候 , 说明该常量是方法引用 ;
#1 = Methodref #4.#17 // java/lang/Object."<init>":()V
常量 tag : 0A
;
常量 info[] : 00 04 00 11
,
4
4
4 个字节 , 前
2
2
2 个字节代表类信息 , 后
2
2
2 字节代表方法和类型 ;
00 04
类信息 ; 指向常量表中的 #4 常量 ; 类型是java/lang/Object
;00 11
方法类型 ; 指向常量表中的 #17 常量 ; 类型是"<init>":()V
;
2、常量池 #2 常量分析
#1 常量分析 : tag 值为 09
; tag 值为 10 的时候 , 说明该常量是字段引用 ;
#2 = Fieldref #3.#18 // Student.name:Ljava/lang/String;
常量 tag : 09
;
常量 info[] : 00 03 00 12
,
4
4
4 个字节 , 前
2
2
2 个字节代表类信息 , 后
2
2
2 字节代表字段名称和类型 ;
00 04
类信息 ; 指向常量表中的#4
常量 ; 类型是Student
;00 11
方法类型 ; 指向常量表中的#18
常量 ; 类型是name:Ljava/lang/String
;
3、常量池 #3 常量分析
#3 常量分析 : tag 值为 07
; tag 值为 07 的时候 , 类信息 ;
#3 = Class #19 // Student
常量 tag : 07
;
常量 info[] : 00 13
,
2
2
2 个字节 , 指向类名所在常量 ;
00 13
方法类型 ; 指向常量表中的#19
常量 ; 类名是Student
;
4、常量池 #4 常量分析
#4 常量分析 : tag 值为 07
; tag 值为 07 的时候 , 类信息 ;
#4 = Class #20 // java/lang/Object
常量 tag : 07
;
常量 info[] : 00 14
,
2
2
2 个字节 , 指向类名所在常量 ;
00 14
方法类型 ; 指向常量表中的#20
常量 ; 类名是java/lang/Object
;
5、常量池 #5 常量分析
#5 常量分析 : tag 值为 01
; 说明该常量是 UTF-8 字符串 ;
#5 = Utf8 name
常量 tag : 01
;
常量 info[] : 00 04 6E 61 6D 65
;
00 04
: 表示 UTF-8 字符串 , 有 4 4 4 个字节 ;6E 61 6D 65
: 字符串内容name
;
6、常量池 #6 常量分析
#6 常量分析 : tag 值为 01
; 说明该常量是 UTF-8 字符串 ;
#6 = Utf8 Ljava/lang/String;
常量 tag : 01
;
常量 info[] : 00 12 4C 6A 61 76 61 2F 6C 61 6E 67 2F 53 74 72 69 6E 67 3B
;
00 12
: 表示 UTF-8 字符串 , 有 18 18 18 个字节 ;4C 6A 61 76 61 2F 6C 61 6E 67 2F 53 74 72 69 6E 67 3B
: 字符串内容Ljava/lang/String;
;
7、常量池 #7 常量分析
#7 常量分析 : tag 值为 01
; 说明该常量是 UTF-8 字符串 ;
#7 = Utf8 <init>
常量 tag : 01
;
常量 info[] : 00 06 3C 69 6E 69 74 3E
;
0006
: 表示 UTF-8 字符串 , 有 6 6 6 个字节 ;3C 69 6E 69 74 3E
: 字符串内容<init>
;
8、常量池 #8 常量分析
#8 常量分析 : tag 值为 01
; 说明该常量是 UTF-8 字符串 ;
#8 = Utf8 ()V
常量 tag : 01
;
常量 info[] : 00 03 28 29 56
;
00 03
: 表示 UTF-8 字符串 , 有 3 3 3 个字节 ;28 29 56
: 字符串内容()V
;
9、常量池 #9 常量分析
#9 常量分析 : tag 值为 01
; 说明该常量是 UTF-8 字符串 ;
#9 = Utf8 Code
常量 tag : 01
;
常量 info[] : 00 04 43 6F 64 65
;
00 04
: 表示 UTF-8 字符串 , 有 4 4 4 个字节 ;43 6F 64 65
: 字符串内容Code
;
10、常量池 #10 常量分析
#10 常量分析 : tag 值为 01
; 说明该常量是 UTF-8 字符串 ;
#10 = Utf8 LineNumberTable
常量 tag : 01
;
常量 info[] : 00 0F 4C 69 6E 65 4E 75 6D 62 65 72 54 61 62 6C 65
;
00 0F
: 表示 UTF-8 字符串 , 有 15 15 15 个字节 ;4C 69 6E 65 4E 75 6D 62 65 72 54 61 62 6C 65
: 字符串内容LineNumberTable
;
11、常量池 #11 常量分析
#11 常量分析 : tag 值为 01
; 说明该常量是 UTF-8 字符串 ;
#11 = Utf8 getName
常量 tag : 01
;
常量 info[] : 00 07 67 65 74 4E 61 6D 65
;
00 0F
: 表示 UTF-8 字符串 , 有 15 15 15 个字节 ;00 07 67 65 74 4E 61 6D 65
: 字符串内容getName
;
12、常量池 #12 常量分析
#12 常量分析 : tag 值为 01
; 说明该常量是 UTF-8 字符串 ;
#12 = Utf8 ()Ljava/lang/String;
常量 tag : 01
;
常量 info[] : 00 14 28 29 4C 6A 61 76 61 2F 6C 61 6E 67 2F 53 74 72 69 6E 67 3B
;
00 14
: 表示 UTF-8 字符串 , 有 20 20 20 个字节 ;28 29 4C 6A 61 76 61 2F 6C 61 6E 67 2F 53 74 72 69 6E 67 3B
: 字符串内容()Ljava/lang/String;
;
13、常量池 #13 常量分析
#13 常量分析 : tag 值为 01
; 说明该常量是 UTF-8 字符串 ;
#13 = Utf8 setName
常量 tag : 01
;
常量 info[] : 00 07 73 65 74 4E 61 6D 65
;
00 07
: 表示 UTF-8 字符串 , 有 7 7 7 个字节 ;73 65 74 4E 61 6D 65
: 字符串内容setName
;
14、常量池 #14 常量分析
#14 常量分析 : tag 值为 01
; 说明该常量是 UTF-8 字符串 ;
#14 = Utf8 (Ljava/lang/String;)V
常量 tag : 01
;
常量 info[] : 00 15 28 4C 6A 61 76 61 2F 6C 61 6E 67 2F 53 74 72 69 6E 67 3B 29 56
;
00 15
: 表示 UTF-8 字符串 , 有 21 21 21 个字节 ;28 4C 6A 61 76 61 2F 6C 61 6E 67 2F 53 74 72 69 6E 67 3B 29 56
: 字符串内容(Ljava/lang/String;)V
;
15、常量池 #15 常量分析
#15 常量分析 : tag 值为 01
; 说明该常量是 UTF-8 字符串 ;
#15 = Utf8 SourceFile
常量 tag : 01
;
常量 info[] : 00 0A 53 6F 75 72 63 65 46 69 6C 65
;
00 0A
: 表示 UTF-8 字符串 , 有 10 10 10 个字节 ;53 6F 75 72 63 65 46 69 6C 65
: 字符串内容SourceFile
;
16、常量池 #16 常量分析
#16 常量分析 : tag 值为 01
; 说明该常量是 UTF-8 字符串 ;
#16 = Utf8 Student.java
常量 tag : 01
;
常量 info[] : 00 0C 53 74 75 64 65 6E 74 2E 6A 61 76 61
;
00 0C
: 表示 UTF-8 字符串 , 有 12 12 12 个字节 ;53 74 75 64 65 6E 74 2E 6A 61 76 61
: 字符串内容Student.java
;
17、常量池 #17 常量分析
#17 常量分析 : tag 值为 0C
; 说明该常量是 名称和类型信息 ;
#17 = NameAndType #7:#8 // "<init>":()V
常量 tag : 0C
;
常量 info[] : 00 07 00 08
;
00 07
:#7
,"<init>"
;00 08
:#8
,()V
;
18、常量池 #18 常量分析
#18 常量分析 : tag 值为 0C
; 说明该常量是 名称和类型信息 ;
#18 = NameAndType #5:#6 // name:Ljava/lang/String;
常量 tag : 0C
;
常量 info[] : 00 05 00 06
;
00 05
:#5
,name
;00 06
:#6
,Ljava/lang/String;
;
19、常量池 #19 常量分析
#19 常量分析 : tag 值为 01
; 说明该常量是 UTF-8 字符串 ;
#19 = Utf8 Student
常量 tag : 01
;
常量 info[] : 00 07 53 74 75 64 65 6E 74
;
00 07
: 表示 UTF-8 字符串 , 有 7 7 7 个字节 ;00 07 53 74 75 64 65 6E 74
: 字符串内容Student
;
20、常量池 #20 常量分析
#20 常量分析 : tag 值为 01
; 说明该常量是 UTF-8 字符串 ;
#20 = Utf8 java/lang/Object
常量 tag : 01
;
常量 info[] : 00 10 6A 61 76 61 2F 6C 61 6E 67 2F 4F 62 6A 65 63 74
;
00 10
: 表示 UTF-8 字符串 , 有 16 16 16 个字节 ;6A 61 76 61 2F 6C 61 6E 67 2F 4F 62 6A 65 63 74
: 字符串内容java/lang/Object
;
总结
下图的选中区域 , 是整个常量池的范围 ;
本博客部分图片转载自 https://blog.csdn.net/luanlouis/category_9263262.html 博客
以上是关于Java 虚拟机原理Class 字节码二进制文件分析 二 ( 常量池位置 | 常量池结构 | tag | info[] | 完整分析字节码文件中的常量池二进制数据 )的主要内容,如果未能解决你的问题,请参考以下文章
Java 虚拟机原理Class 字节码二进制文件分析 四 ( 字段表数据结构 | 字段表详细分析 | 访问标志 | 字段名称 | 字段描述符 | 属性项目 )
Java 虚拟机原理Class 字节码二进制文件分析 三 ( 访问和修饰标志 | 类索引 | 父类索引 | 接口计数器 | 接口表 | 字段计数器 | 字段表 )
Java 虚拟机原理Class 字节码二进制文件分析 六 ( 属性类型 | Code 属性 | 属性名称索引 | 属性长度 | 操作数栈最大深度 | 局部变量存储空间 | 字节码长度 )
Java 虚拟机原理动态字节码技术 | Dalvik & ART 虚拟机 | Android 字节码打包过程
Java 虚拟机原理Class 字节码二进制文件分析 五 ( 方法计数器 | 方法表 | 访问标志 | 方法名称索引 | 方法返回值类型 | 方法属性数量 | 方法属性表 )
Java 虚拟机原理Class 字节码二进制文件分析 二 ( 常量池位置 | 常量池结构 | tag | info[] | 完整分析字节码文件中的常量池二进制数据 )