目录
Java中主要有三种常量池,分别是class常量池、字符串常量池和运行时常量池。我们对这三个常量池进行对比。
class常量池
我们写的每一个Java类被编译之后都会生成一个对应的Class文件。Class文件中除了有类的版本、字段、方法、接口等描述信息外,还有一项信息是常量池,用于存放编译期生成的各种字面量和符号引用。每个类都有一个Class常量池。
什么是字面量和符号引用
字面量比较接近于Java语言层面的常量概念,如文本字符串、声明为final的常量值和八种基本类型的变量等。而符号引用则属于编译原理方面的概念,包括了下面三类变量:
- 类和接口的全限定名
- 字段的名称和描述符
- 方法的名称和描述符
Java代码在进行Javac编译的时候是在虚拟机加载Class文件的时候进行动态连接。也就是说,在Class文件中不会保存各个方法、字段的最终内存布局信息,因此这些字段、方法的符号引用不经过运行期转换的话无法得到真正的内存入口地址,也就无法直接被虚拟机使用。当虚拟机运行时,需要从常量池获得对应的符号引用,再在类创建时或者运行时解析、翻译到具体的内存地址中。
常量池中每一项常量都是一个表,在JDK1.7之前共有11种结构各不相同的表结构数据,在JDK1.7中为了更好地支持动态语言调用,又额外增加了3种。
字符串常量池
字符串常量池的设计思想
和其他对象分配一样,字符串的分配耗费高昂的时间和空间代价,作为最基础的数据类型大量频繁创建字符串会极大的影响性能。
JVM为了提高性能和减少内存开销,在实例化字符串常量的时候进行了一些优化
-
为字符串开辟一个字符串常量池,类似于缓存区
-
创建字符串常量时,首先检查字符串常量池是否存在该字符串
-
若存在该字符串,返回引用实例;若不存在,实