Java中的常量池,实际上分为两种形态:静态常量池和运行时常量池。
一、静态常量池
即*.class文件中的常量池,class文件中的常量池不仅仅包含字符串(数字)字面量,还包含类、方法的信息,占用class文件绝大部分空间。
常量池(constant_pool)指的是在编译期被确定,并被保存在已编译的.class文件中的一些数据。它包括了关于类、方法、接口等中的常量,也包括字符串常量和符号引用。
常量池主要用于存放两大类常量:字面量(Literal)和符号引用量(Symbolic References)
字面量相当于Java语言层面常量的概念,如文本字符串,声明为final的常量值等
符号引用则属于编译原理方面的概念,包括了如下三种类型的常量:
1) 类和接口的全限定名
2) 字段名称和描述符
3) 方法名称和描述符
另外Byte,Short,Integer,Long,Character这5种整型的包装类也只是在对应值在-128到127时才可使用对象池。
二、而运行时常量池
则是jvm虚拟机在完成类装载操作后,将class文件中的常量池载入到内存中,并保存在方法区中,我们常说的常量池,就是指方法区中的运行时常量池。
运行时常量池是方法区的一部分。CLass文件中除了有类的版本、字段、方法、接口等描述信息外,还有一项信息是常量池,用于存放编译期生成的各种字面量和符号引用,这部分内容将在类加载后进入方法区的运行时常量池中存放。
运行时常量池相对于CLass文件常量池的另外一个重要特征是具备动态性,Java语言并不要求常量一定只有在编译期才能产生,也就是并非预置入Class文件中常量池的内容才能进入方法区运行时常量池,运行期间也可能将新的常量放入池中,这种特性被开发人员利用得比较多的便是String类的intern()方法。
三、String常量池随JDK的改变
JDK1.7中JVM把String常量区从方法区中移除了;JDK1.8中JVM把String常量池移入了堆中,同时取消了“永久代”,改用元空间代替(Metaspace)