运行时常量池和字符串常量池的区别及说明
作者:岛田悠米
运行时常量池和字符串常量池的区别
常量池
每个class一份,存在于字节码文件中。
常量池中有字面量(数量值、字符串值)和符号引用(类符号引用、字段符号引用、方法符号引用),虚拟机指令根据这张常量表找到要执行的类名、方法名、参数类型、字面量等类型
运行时常量池
每个class一份,存在于方法区中(元空间)。
当类加载到内存中后,jvm就会将class常量池中的内容存放到运行时常量池中,经过解析(resolve)之后,也就是把符号引用替换为直接引用,解析的过程会去查询全局字符串池,也就是下面的StringTable,以保证运行时常量池所引用的字符串与全局字符串池中所引用的是一致的。
字符串常量池
每个JVM中只有一份,存在于方法区中(堆)。
全局字符串池里的内容是在类加载完成,经过验证,准备阶段之后在堆中生成字符串对象实例,然后将该字符串对象实例的引用值存到string pool中(string pool中存的是引用值而不是具体的实例对象,具体的实例对象是在堆中开辟的一块空间存放的)。
在HotSpot VM里实现的string pool功能的是一个StringTable类,它是一个哈希表,里面存的是驻留字符串(用双引号括起来的引用而不是驻留字符串实例本身),也就是说在堆中的某些字符串实例被这个StringTable引用之后就等同被赋予了”驻留字符串”的身份。
运行时常量池和字符串常量池的关系
运行时常量池是一个统称 也包括字符串常量池,但是字符串常量池放的只是字符串,而运行时常量池中,还包括类信息,属性信息,方法信息,以及其他基础类型的的常量池比如int,long等
jdk1.7之前,运行时常量池(包含着字符串常量池)都在方法区,具体的hotspot虚拟机实现为永久代
jdk1.7阶段,字符串常量池从方法区移到堆中,运行池常量池剩下的部分依旧在方法区(剩下类信息、属性信息、方法信息等),同样是hotspot中的永久代
jdk1.8, 方法区的实现从永久代变成了元空间,因此 字符串常量池依然在堆中,运行时常量池在方法区,hotspot中的元空间(metaspace)
总结
以上为个人经验,希望能给大家一个参考,也希望大家多多支持脚本之家。