JAVA字节码文件之第二篇(常量池)

Posted 君子生非异也

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了JAVA字节码文件之第二篇(常量池)相关的知识,希望对你有一定的参考价值。

一、常量池的内容

一个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;

其他元素分析方式与此相同就不再分析,最终分析可知红圈这部分区域是常量池的内容(00 18->63 74)

 

 

三、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;
    }

以上是关于JAVA字节码文件之第二篇(常量池)的主要内容,如果未能解决你的问题,请参考以下文章

java常量池和运行时常量池,附赠课程+题库

Java字节码常量池深度剖析与字节码整体结构分解

Java 虚拟机原理Class 字节码二进制文件分析 一 ( 字节码文件附加信息 | 魔数 | 次版本号 | 主版本号 | 常量池个数 )

Java字节码文件

Java 虚拟机原理Class 字节码二进制文件分析 七 ( 局部变量表分析 )

python开发(第二篇):初始python