2.3 常量池
2.3.1 什么是常量池?
紧接着版本号之后的就是常量池。常量池中存放两种类型的常量:
- 字面量 (Literal)
接近Java语言的常量概念,如:字符串文本、final常量值。 - 符号引用 (Symbolic Reference)
属于编译原理方面,包括下面三类常量:: - 类和接口的全限定名
- 字段的名称和描述符
- 方法的名称和描述符
2.3.2 常量池的特点
- 长度不固定
常量池的大小不固定,因此常量池开头放置一个u2类型的无符号数,代表当前常量池的容量.
该值从1开始,若为5表示池中有4项常量,索引值1~5 - 常量由二维表表示
开头有个常量池容量计数值,接下来就全是一个个常量了,只不过常量都是由一张张二维表构成,除了记录常量的值以外,还记录当前常量的相关信息 - class文件的资源仓库
- 与本class中其它部分关联最多的数据类型
- 占用Class文件空间最大的部分之一 ,也是第一个出现的表类型项目
2.3.3 常量池中常量的类型
根据常量的数据类型不同,被细分为14种常量类型,都有各自的二维表示结构
每种常量类型的头1个字节都是tag,表示当前常量属于14种类型中的哪一个.
以CONSTANT_Class_info常量为例,它的二维表示结构如下:
CONSTANT_Class_info表
- tag 表示当前常量的类型(当前常量为CONSTANT_Class_info,因此tag的值应为7,表一个类或接口的全限定名);
- name_index 表示这个类或接口全限定名的位置.它的值表示指向常量池的第几个常量.它会指向一个CONSTANT_Utf8_info类型的常量
CONSTANT_Utf8_info表字符串常量
- tag 表当前常量的类型,这里是1
- length 表该字符串的长度
- bytes为这个字符串的内容(采用缩略的UTF8编码)
Java中定义的类、变量名字必须小于64K
类、接口、变量等名字都属于符号引用,它们都存储在常量池中
而不管哪种符号引用,它们的名字都由CONSTANT_Utf8_info类型的常量表示,这种类型的常量使用u2存储字符串的长度
由于2字节最多能表示65535个数,因此这些名字的最大长度最多只能是64K
UTF-8编码 VS 缩略UTF-8编码
前者每个字符使用3个字节表示,而后者把128个ASCII码用1字节表示,某些字符用2字节表示,某些字符用3字节表示。
Demo1.txt中的常量池部分
类信息包含的静态常量,编译之后就能确认
JVM 指令
网络异常,图片无法展示
|
invokedynamic JDK1.7新加入的一个虚拟机指令,相比于之前的四条指令,他们的分派逻辑都是固化在JVM内部,而invokedynamic则用于处理新的方法分派:它允许应用级别的代码来确定执行哪一个方法调用,只有在调用要执行的时候,才会进行这种判断,从而达到动态语言的支持。(Invoke dynamic method)