方法区是一个抽象定义,可以想象成接口;元空间或永久代是具体的实现技术Java8版本以后,是用元空间来实现的方法区;在Java8之前的版本,则是。用永久代实现的方法区。
Class类常量池
class类常量池中包含的是字面量和符号引用,如下图
运行时常量池
相较于Class文件常量池,运行时常量池更具动态性,和class文件的常量池是一一对应的,它就是class文件的constant_pool来构建的。运行时常量池中有两种类型,分别是符号引用和静态常量,
其中静态常量不需要后续解析,而符号引用需要进一步进行解析处理。
什么是静态常量,什么是符号引用呢? 我们举个直观的例子。
String site="hello"
上面的字符串”hello”可以看做是一个静态常量,因为它是不会变化的。
而上面的字符串的名字“site”就是符号引用,需要在运行期间进行解析,为什么呢?
因为site引用的值是可以变化的,不能在第一时间确定其真正的值,需要在动态运行中进行解析。
- 在运行期间也可以将新的变量放入常量池中,而不是一定要在编译时确定的常量才能放入。最主要的运用便是String类的intern()方法
-
String.intern()
检查字符串常量池中是否存在String并返回池里的字符串引用;若池中不存在,则将其加入池中,并返回其引用。
这样做主要是为了避免在堆中不断地创建新的字符串对象
字符串常量池
JDK1.7中JVM把String常量区从方法区中移除了;JDK1.8中JVM把String常量池移入了堆中,同时取消了“永久代”,改用元空间代替(Metaspace)。
字符串常量池保存的是“字符”的实例,供运行时常量池引用