JVM虚拟机-Class文件之常量池

简介: JVM虚拟机-Class文件之常量池

 

一、常量池的作用

在class文件中的魔数、副版本号、主版本之后,紧接着就是常量池的数据区域了,如下图用红线包括的位置:

image.gif编辑

常量池可以比喻为Class文件里的资源仓库,它是Class 文件结构中与其他项目关联最多的数据,通常也是占用Class文件空间最大的数据项目之一,另外,它还是在Class文件中第一个出现的表类型数据项目。

二、常量池的结构

常量池的结构比较简单,前面的两个字节叫做常量池计数器(constant_pool_count),它记录了常量池项(cp_info)的个数。后面紧接着就是constant_pool_count-1常量池项(cp_info)。这跟报文通信协议比较类似,首先定义报文的大小,接着就是对应大小的报文内容。

image.gif编辑

image.gif编辑

由于常量池中常量的数量是不固定的,所以在常量池的入口需要放置一项u2类型的数据,代表常量池容量计数值(constant_pool_count)。与Java中语言习惯不同,这个容量计数是从1而不是0开始的,如上图所示,常量池容量(偏移地址:0x00000008)为十六进制数0x0021,即十进制的33,这就代表常量池中有33项常量,索引值范围为1~33。在Class文件格式规范制定之时,设计者将第0项常量空出来是有特殊考虑的,这样做的目的在于,如果后面某些指向常量池的索引值的数据在特定情况下需要表达“不引用任何一个常量池项目”的含义,可以把索引值设置为0来表示。Class文件结构中只有常量池的容量计数是从1开始,对于其他集合类型,包括接口索引集合、字段表集合、方法表集合等的容量计数都与一般习惯相同,是从0开始。

三、常量池的分类

常量池中主要存放两大类常量:字面量(Literal)和符号引用(Symbolic References)。字面量比较接近于Java语言层面的常量概念,如文本字符串、被声明为final的常量值等;而符号引用则属于编译原理方面的概念。具体分类如下图:

image.gif编辑

常量池中每一项常量都是一个表,最初常量表中共有11种结构各不相同的表结构数据,后来为了更好地支持动态语言调用,额外增加了4种动态语言相关的常量,为了支持Java模块化系统 (Jigsaw),又加入了CONSTANT_M odule_info和CONSTANT_Package_info两个常量,所以截至JDK 13,常量表中分别有17种不同类型的常量。这17类表都有一个共同的特点,表结构起始的第一位是个u1类型的标志位(tag,取值见下表中标志列),代表着当前常量属于哪种常量类型。

官网最新:Specification for JEP 309: Dynamic Class-File Constants (JROSE EDITS)

image.gif编辑

image.gif编辑

我们对这个class文件进行分析,可以看到前8个字节是该class文件的魔数和版本号,紧接着的一个十六进制数0x0021,即十进制的33,这就代表z这个class文件的常量池中有32项常量,索引值为1~32。然后就是第一个常量了,上面说过,每种类型的常量开始的第一位都是一个u1类型的标志位,代表该常量的类型,这里是0x0a,十进制的10,查上面的表可知是CONSTANT_Methodref_info,说明这个常量是类中方法的符号应用。该类型常量的具体结构为:

image.gif编辑

第一个index值为0x0004,即指向常量池中的第4个常量,第二个index是0x0019,即指向常量池中的第25个常量。在JDK的bin目录中,Oracle公司已经为我们准备好一个专门用于分析Class文件字节码的工具:javap。我们可以用javap -verbose命令查看class文件的字节码内容。

image.gif编辑

可以看到和我们分析的一致,该class文件中确实有32项常量,从#1到#32。

四、17种数据类型结构总表

image.gif编辑

image.gif编辑

image.gif编辑

参考资料:

    1. Class文件中的常量池详解(上)_xinjing_wangtao的博客-CSDN博客
    2. 深入理解Java虚拟机(第三版)-- Class类文件结构_吴声子夜歌的博客-CSDN博客
    相关文章
    |
    7月前
    |
    Arthas 存储 算法
    深入理解JVM,包含字节码文件,内存结构,垃圾回收,类的声明周期,类加载器
    JVM全称是Java Virtual Machine-Java虚拟机JVM作用:本质上是一个运行在计算机上的程序,职责是运行Java字节码文件,编译为机器码交由计算机运行类的生命周期概述:类的生命周期描述了一个类加载,使用,卸载的整个过类的生命周期阶段:类的声明周期主要分为五个阶段:加载->连接->初始化->使用->卸载,其中连接中分为三个小阶段验证->准备->解析类加载器的定义:JVM提供类加载器给Java程序去获取类和接口字节码数据类加载器的作用:类加载器接受字节码文件。
    740 55
    |
    5月前
    |
    存储 Java 编译器
    深入理解Java虚拟机--类文件结构
    本内容介绍了Java虚拟机与Class文件的关系及其内部结构。Class文件是一种与语言无关的二进制格式,包含JVM指令集、符号表等信息。无论使用何种语言,只要能生成符合规范的Class文件,即可在JVM上运行。文章详细解析了Class文件的组成,包括魔数、版本号、常量池、访问标志、类索引、字段表、方法表和属性表等,并说明其在Java编译与运行过程中的作用。
    160 0
    |
    8月前
    |
    Arthas 监控 Java
    Arthas redefine(加载外部的.class文件,redefine到JVM里 )
    Arthas redefine(加载外部的.class文件,redefine到JVM里 )
    403 15
    |
    7月前
    |
    Arthas 存储 Java
    JVM深入原理(三+四):JVM组成和JVM字节码文件
    目录3. JVM组成3.1. 组成-运行时数据区3.2. 组成-类加载器3.3. 组成-执行引擎3.4. 组成-本地接口4. JVM字节码文件4.1. 字节码文件-组成4.1.1. 组成-基础信息4.1.1.1. 基础信息-魔数4.1.1.2. 基础信息-主副版本号4.1.2. 组成-常量池4.1.3. 组成-方法4.1.3.1. 方法-工作流程4.1.4. 组成-字段4.1.5. 组成-属性4.2. 字节码文件-查看工具4.2.1. javap4.2.2. jclasslib4.2.3. 阿里Arthas
    145 0
    |
    7月前
    |
    存储 安全 Java
    JVM深入原理(五):JVM组成和JVM字节码文件
    类的生命周期概述:类的生命周期描述了一个类加载,使用,卸载的整个过类的生命周期阶段:类的声明周期主要分为五个阶段:加载->连接->初始化->使用->卸载,其中连接中分为三个小阶段验证->准备->解析。
    120 0
    |
    10月前
    |
    存储 数据挖掘 虚拟化
    vsan数据恢复—vsan缓存盘故障导致虚拟机磁盘文件丢失的数据恢复案例
    VMware vsan架构采用2+1模式。每台设备只有一个磁盘组(7+1),缓存盘的大小为240GB,容量盘的大小为1.2TB。 由于其中一台主机(0号组设备)的缓存盘出现故障,导致VMware虚拟化环境中搭建的2台虚拟机的磁盘文件(vmdk)丢失。
    |
    存储 监控 算法
    深入探索Java虚拟机(JVM)的内存管理机制
    本文旨在为读者提供对Java虚拟机(JVM)内存管理机制的深入理解。通过详细解析JVM的内存结构、垃圾回收算法以及性能优化策略,本文不仅揭示了Java程序高效运行背后的原理,还为开发者提供了优化应用程序性能的实用技巧。不同于常规摘要仅概述文章大意,本文摘要将简要介绍JVM内存管理的关键点,为读者提供一个清晰的学习路线图。
    |
    存储 监控 算法
    Java虚拟机(JVM)垃圾回收机制深度解析与优化策略####
    本文旨在深入探讨Java虚拟机(JVM)的垃圾回收机制,揭示其工作原理、常见算法及参数调优方法。通过剖析垃圾回收的生命周期、内存区域划分以及GC日志分析,为开发者提供一套实用的JVM垃圾回收优化指南,助力提升Java应用的性能与稳定性。 ####
    |
    2月前
    |
    存储 缓存 Java
    我们来说一说 JVM 的内存模型
    我是小假 期待与你的下一次相遇 ~
    285 5
    |
    2月前
    |
    存储 缓存 算法
    深入理解JVM《JVM内存区域详解 - 世界的基石》
    Java代码从编译到执行需经javac编译为.class字节码,再由JVM加载运行。JVM内存分为线程私有(程序计数器、虚拟机栈、本地方法栈)和线程共享(堆、方法区)区域,其中堆是GC主战场,方法区在JDK 8+演变为使用本地内存的元空间,直接内存则用于提升NIO性能,但可能引发OOM。