一、常量池的作用

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

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

二、常量池的结构

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

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

三、常量池的分类

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

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

官网最新:http://cr.openjdk.java.net/~jrose/jvm/constant-dynamic-jrose.html

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

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

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

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

参考资料:

  1. https://blog.csdn.net/wangtaomtk/article/details/52267548
  2. https://blog.csdn.net/cold___play/article/details/105325698

JVM虚拟机-Class文件之常量池相关推荐

  1. JVM虚拟机-Class文件之方法表集合

    一.概述 方法表集合与属性表集合的结构类似,是对方法的修饰符.返回类型.方法名.参数个数.参数类型.方法体的描述集合. 方法表集合的结构是一个类似于数组的结构,JVM在对java文件进行编译时,会将类 ...

  2. jvm中方法区和常量池详解_JVM——内存区域:运行时数据区域详解

    关注微信公众号:CodingTechWork,一起学习进步. 引言 我们经常会被问到一个问题是Java和C++有何区别?我们除了能回答一个是面向对象.一个是面向过程编程以外,我们还会从底层内存管理和垃 ...

  3. 欧尼酱讲JVM(11)——动态链接和常量池

    因为动态链接和运行时常量池有联系,所以先解释一下运行时常量池: 运行时常量池位于方法区(注意: JDK1.7 及之后版本的 JVM 已经将运行时常量池从方法区中移了出来,在 Java 堆(Heap)中 ...

  4. jvm中方法区和常量池详解_Java常量池(静态常量池与运行时常量池)

    1.什么是常量 用final修饰的成员变量表示常量,值一旦给定就无法改变! final修饰的变量有三种:静态变量.实例变量和局部变量,分别表示三种类型的常量. Java中的常量池,实际上分为两种形态: ...

  5. JVM虚拟机-Class文件之属性表集合

    一.概述 在class文件中,属性表集合包括Java虚拟机预先规范定义的属性以及用户自定义的属性,对于用户自定义的属性,虚拟机加载的时候会自动忽略掉.class文件.字段表.方法表都可以携带自己的属性 ...

  6. JVM虚拟机-Class文件之类索引、父类索引和接口索引集合

    一.概述 前面介绍了class文件,包括魔数.次版本号.主版本号.常量池和访问标志.接下来的就是用于确定这个类的继承关系的类索引(this_class).父类索引(super_class)与接口索引集 ...

  7. 字符串在JVM中如何存放 及常量池技术

    字符串对象在JVM中可能有两个存放的位置:字符串常量池或堆内存. 使用常量字符串初始化的字符串对象,它的值存放在字符串常量池中: 使用字符串构造方法创建的字符串对象,它的值存放在堆内存中: Strin ...

  8. JVM虚拟机-Class文件之字段表集合

    一.概述 在接口索引集合后面 的就是字段表集合了.字段表(field_info)用于描述接口或者类中声明的变量.字段包括类级变量以及实例级变量,但是不包括在方法内部声明的局部变量. 二.字段表集合的构 ...

  9. JVM虚拟机-Class文件之访问标志

    一.访问标志的概念 常量池结束之后,紧接着的两个字节代表访问标志,这个标志用于识别一些类或者接口层次的访问信息,包括:这个Class是接口还是类:是否被定义为public类型:是否定义为abstrac ...

最新文章

  1. 阿里带火的中台到底是什么?白话中台战略
  2. Illustrator+FontLab 进行字体设计教程
  3. HBase学习指南之HBase原理和Shell使用
  4. 详解SpringBoot应用跨域访问解决方案
  5. openmp官方源码_MNN推理过程源码分析笔记(一)主流程
  6. Android开发技巧--Application, ListView排列,格式化浮点数,string.xml占位符,动态引用图片...
  7. 74芯片引脚真值表汇总
  8. 【机器视觉】 dev_map_var算子
  9. 《深入理解TypeScript》读后感一篇【基础篇】
  10. 开源代码motion
  11. TeamViewer订阅版上线,正式开售!
  12. 计算机专业基础 -- Linux系统相关基础知识
  13. 防火墙、防病毒网关、IDS以及该类安全产品开发
  14. 树莓派4B静态IP与屏幕分辨率设置
  15. 谈谈我们为什么要前后端分离
  16. Day08——字符串匹配、小结
  17. 【Unity3D 灵巧小知识点】 ☀️ | UnityHub中提示 许可证过期 了怎么办?
  18. ​6. 独享锁 VS 共享锁
  19. python爬虫scrapy爬取新闻标题及链接_18Python爬虫---CrawlSpider自动爬取新浪新闻网页标题和链接...
  20. Arcgis地图服务切片

热门文章

  1. (转) lucene+paoding亲密接触
  2. 华为路由器与CISCO路由器在配置上的差别
  3. 代码自动生成工具的补充
  4. 大规模分布式系统资源管理(二)
  5. 按 字节截取分别以GBK 和 utf-8 编码的 字符串的java程序。
  6. golang 1.10 mutex互斥锁源码
  7. python随机产生10个随机数_python(random模块)取10以内的随机数
  8. Leetcode-二叉搜索树最近公共祖先
  9. Linux 64位进程地址空间分布概况
  10. 面试题:请介绍⼀下 JMM(Java 内存模型)