摘抄自小涛涛~~~:小涛涛JVM系列博客
1、JAVA虚拟机方法区
JAVA虚拟机方法区在JAVA虚拟机内存模型中位置如下图所示。
方法区和堆一样,是各个线程共享的内存区域,用于存储已被虚拟机加载的类信息、常量、静态变量、和编译器编译后的代
码(也就是存储字节码文件。.class)等数据,这里可以看到常量也会在方法区中,是因为方法区中有一个运行时常量池,为什么叫
运行时常量池,因为在编译后期生成的是各种字面量(字面量的意思就是值,比如int i=3,这个3就是字面量的意思)和符号引用,
这些是存放在一个叫做常量池(这个常量池是在字节码文件中)的地方,当类加载进入方法区时,就会把该常量池中的内容放入运
行时常量池中。
这里要注意,运行时常量池和常量池,不要搞混淆了,字节码文件中也有常量池,在后面的章节会详细讲解这个东西。现在
只需要知道方法区中有一个运行时常量池,就是用来存放常量的。还有一点,运行时常量池不一定就一定要从字节码常量池中拿
取常量,可能在程序运行期间将新的常量放入池中,比如String.intern()方法,这个方法的作用就是:先从方法区的运行时常量
池中查找看是否有该值,如果有,则返回该值的引用,如果没有,那么就会将该值加入运行时常量池中。
运行时常量池Demo:
执行下方代码,得到的结果代码中注释已有
-
public
class test {
-
public static void main(String[] args) {
-
String a =
“aaa” ;
-
String b =
“aaa” ;
-
System.out.println(a == b);
-
//1、输出为true
-
-
String c =
new String(a);
-
System.out.println(a == c);
-
//2、输出为false
-
-
System.out.println(a == c.intern());
-
//3、输出为true
-
}
-
}
第一次输出:
在创建String a和b时,虚拟机会在运行时常量池中寻找”aaa”的串,如果存在,直接返回地址,如果不存在,创建后返回地址。这也就解释了为什么第一次输出位true的问题。
第二次输出:
当我们使用new String()创建c时候,c会被虚拟机创建在堆中,这就是为什么第二次输出为false。
第三次输出:
c.intern()方法是将c的值放入运行时常量池并返回地址,所以第三次比较结果为true;