java虚拟机方法区内存模型

说明:
[线程共享]存储已被虚拟机加载的类信息、常量、静态变量、编译后的代码等数据。

看了《深入理解java虚拟机》后,对常量池、字符串池、运行时常量池的理解很模糊,很混乱。通过网上看其他作者的文章和自己的理解总结如下:

首先理解三个概念
常量池(Constant Pool):常量池数据编译期被确定,是Class文件中的一部分。存储了类、方法、接口等中的常量,当然也包括字符串常量。
字符串池/字符串常量池(String Pool/String Constant Pool):是常量池中的一部分,存储编译期类中产生的字符串类型数据。
运行时常量池(Runtime Constant Pool):方法区的一部分,所有线程共享。虚拟机加载Class后把常量池中的数据放入到运行时常量池。

常量池:可以理解为Class文件之中的资源仓库,它是Class文件结构中与其他项目资源关联最多的数据类型。
    常量池中主要存放两大类常量:字面量(Literal)和符号引用(Symbolic Reference)。
    字面量:文本字符串、声明为final的常量值等;
    符号引用:类和接口的完全限定名(Fully Qualified Name)、字段的名称和描述符(Descriptor)、方法的名称和描述符

java方法区内存模型图
《java虚拟机方法区内存模型》

关于String类
不可变:String使用private final char value[]来实现字符串的存储,String对象创建之后,就不能再修改此对象中存储的字符串内容。
比较:判断String值相等用”equals”,判断是否引用同一对象用“==”

1、intern()方法的作用:
    如果运行时常量池中已经包含一个等于此String对象的字符串,则返回代表池中这个字符串的对象;否则,将String对象包含的字符串添加到常量池中,并返回此String对象。
JDK6:如果常量池中没有找到String对象的字符串,会在在堆中创建String对象并复制到方法区,返回方法区上这个String对象引用。
String s = new String(“hello”);
System.out.println(s.intern()==s);  //return false
JDK7:不会复制到方法区,返回堆中String对象的引用。
String s = new String(“hello”);
System.out.println(s.intern()==s);  //return true

2、toString()方法:返回String对象
String s = “hel”;   //虚拟机编译期自动将字符串添加到常量池,然后在Class加载后添加到运行时常量池
String s1=new String(“hel”);   //s1对象在程序运行期在堆中创建
System.out.println(s==s1.toString());   //return false

3、java对String类型重载了+操作符
“aa” + “aa”创建的也是常量,编译期就能确定;
“aa” + s1创建的对象是运行期才创建的。

    原文作者:天涯海角路
    原文地址: http://www.cnblogs.com/aademeng/articles/6188090.html
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞