又拿出这道String str1 = new String("abc");创建几个对象的面试题梳理了一下常量池与方法区的关系,希望能把这两者的关系通过这道面试题说明白

方法区是什么

简单说方法区用于存储jvm加载的类的信息、常量、静态变量、编译后的代码

方法区、永久代与元空间的关系

下文都以HotSpot来说明

首先方法区是JVM规范的说法,永久代、元空间是HotSpot用来实现方法区的两个具体的实现

JDK1.8以前使用永久代Perm实现了JVM规范中的方法区

JDK1.8废弃永久代,变更为元空间,不是废弃了方法区

永久代与元空间的区别是元空间不在虚拟机内存中,而使用本地内存,目的是为了融合HotSpot与JRockit VM而做出的努力并且减少,并且由于这部分空间的GC效果难以令人满意

上面我们就说清楚了方法区、永久代与元空间这几个名词之间的关系和区别,下面我们在来看三个常量池的关系和不同

常量池

字符串常量池

是一个哈希表(StringTable),里面存的是驻留字符串的引用

字符串驻留:JVM 为了提高性能会将能在编译时期确定的字符串放在字符串驻留池的内存块中,String a = "abc"; String b = new String("def");都在编译时期能确定主流字符串"abc""def"

在堆中的字符串实例被这个哈希表引用之后就等同被赋予了”驻留字符串”的身份
在JVM中字符串常量池被所有类共享
字符串常量池在JDK1.7的版本从永久代移动到了堆

class文件常量池

class文件中除了包含类的版本、字段、方法、接口等描述信息外,还有一项信息就是常量池,用于存放编译器生成的各种字面量(Literal)和符号引用(Symbolic References)。注意这是class文件中的内容
字面量就是我们所说的常量概念,如文本字符串、被声明为final的常量值等
符号引用是一组符号来描述所引用的目标,符号可以是任何形式的字面量,只要使用时能无歧义地定位到目标即可,通常包含:类的全限定名、字段的名称和描述符、方法的名称和描述符
总之这些内容能表示这个类的代码内容

运行时常量池

JDK1.7仅仅把字符串常量池移动到了堆,JDK1.8虽然废弃了永久代变更为元空间,但是运行时常量池仍然跟随元空间被移出JVM内存
当类加载到内存中后,jvm就会将class常量池中的内容存放到运行时常量池中,由此可知,运行时常量池也是每个类都有一个
并且在类加载的解析阶段会把运行时常量池的符号引用替换成直接引用,这个过程需要查找字符串常量池

由上面的内容我们可知new String对象创建问题只和堆以及堆内的字符串常量池有关系(字符串常量池在不在堆对new String没什么影响)

      //在堆中会有一个”abc”实例,全局StringTable中存放着”abc”的一个引用值
String str1 = "abc";
//生成两个实例,一个是”def”的实例对象,并且StringTable中存储一个”def”的引用值,还有一个是new出来的一个”def”的实例对象(指向str2)
String str2 = new String("def");
//查找StringTable,里面有”abc”的全局驻留字符串引用,所以str3的引用地址与之前的那个已存在的相同
String str3 = "abc";
//调用intern()函数,返回StringTable中”def”的引用值,如果没有就将str2的引用值添加进去
String str4 = str2.intern();
//最后str5在解析的时候就也是指向存在于StringTable中的”def”的引用值
String str5 = "def";
//生成一个实例,new出来的一个”def”的实例对象(指向str6),(def母本与StringTable放入”def”引用值已经创建)
String str6 = new String("def"); System.out.println(str1 == str3);//true System.out.println(str2 == str4);//false
System.out.println(str4 == str5);//true System.out.println(str5 == str2);//false
System.out.println(str6 == str2);//false System.out.println(str6 == str2.intern());//false
System.out.println(str6.intern() == str2.intern());//true

常量池与方法区以及又读new String对象创建问题的更多相关文章

  1. JDK方法区、元空间区别 & String.intern相关面试题

    一.方法区.永久代.元空间 1.方法区.永久代 方法区也是各个线程共享的内存区域,它用于存储已经被虚拟机加载的类信息.常量.静态变量.即时编译器编译后的代码等数据.方法区域又被称为"永久代& ...

  2. jvm之java类加载机制和类加载器(ClassLoader),方法区结构,堆中实例对象结构的详解

    一.类加载或类初始化:当程序主动使用某个类时,如果该类还未被加载到内存中,则JVM会通过加载.连接.初始化3个步骤来对该类进行初始化.如果没有意外,JVM将会连续完成3个步骤. 二.类加载时机:  1 ...

  3. 类的加载,链接和初始化——1运行时常量池(来自于java虚拟机规范英文版本+本人的翻译和理解)

    加载(loading):通过一个特定的名字,找到类或接口的二进制表示,并通过这个二进制表示创建一个类或接口的过程. 链接:是获取类或接口并把它结合到JVM的运行时状态中,以让类或接口可以被执行 初始化 ...

  4. Java方法区和运行时常量池溢出问题分析

    运行时常量池是方法区的一部分,方法区用于存放Class的相关信息,如类名.访问修饰符.常量池.字段描述.方法描述等. String.intern()是一个native方法,它的作用是:如果字符串常量池 ...

  5. Java方法区和运行时常量池溢出问题分析(转)

    运行时常量池是方法区的一部分,方法区用于存放Class的相关信息,如类名.访问修饰符.常量池.字段描述.方法描述等. String.intern()是一个native方法,它的作用是:如果字符串常量池 ...

  6. 对于JVM中方法区,永久代,元空间以及字符串常量池的迁移和string.intern方法

    在Java虚拟机(以下简称JVM)中,类包含其对应的元数据,比如类的层级信息,方法数据和方法信息(如字节码,栈和变量大小),运行时常量池,已确定的符号引用和虚方法表. 在过去(当自定义类加载器使用不普 ...

  7. Java中的栈,堆,方法区和常量池

    要说Java中的栈,堆,方法区和常量池就要提到HotSpot,HotSpot是Sun JDK 和 Open JDK中所带的虚拟机. (Sun JDK 和 Open JDK除了注释不同,代码实现基本上是 ...

  8. String放入运行时常量池的时机与String.intern()方法解惑

    运行时常量池概述 Java运行时常量池中主要存放两大类常量:字面量和符号引用.字面量比较接近于Java语言层面的常量概念,如文本字符串.声明为final的常量值等. 而符号引用则属于编译原理方面的概念 ...

  9. JVM体系结构之七:持久代、元空间(Metaspace) 常量池==了解String类的intern()方法、常量池介绍、常量池从Perm-->Heap

    一.intern()定义及使用 相信绝大多数的人不会去用String类的intern方法,打开String类的源码发现这是一个本地方法,定义如下: public native String inter ...

随机推荐

  1. Openjudge jubeeeeeat

    jubeeeeeat 题目链接 总时间限制:  1000ms 内存限制:  256000kB 描述 众所周知,LZF很喜欢打一个叫Jubeat的游戏.这是个音乐游戏,游戏界面是4×4的方阵,会根据音乐 ...

  2. HTML基本标签问题总结

    一.常见的内联元素和块元素 块级元素: div, form, (列表相关ul,dl,ol,li,) h1-6,p,table 内联元素: a, br, u,(b , em, strong, i,) i ...

  3. 怎么在Vue中使用Base64格式的背景

    问题发生于一次mock数据,生成了base64格式的东西,因为编码包在一个变量中,不知道怎么直接在 :style 中引入. 解答1:格式background-image: url(此处是我们mock生 ...

  4. linux下生成随机密码

    常见的简单的两种方法 1.openssl rand -base64 32 2.date | md5sum

  5. maven 引入本地项目jar报红线错误解决方法

    问题:本地创建了2个项目,A和B,A引入B,A的pom如下: <dependency> <groupId>com.ebc</groupId> <artifac ...

  6. python_魔法方法(四):属性访问

    通常可以通过点(.)操作符的形式去访问对象的属性,也可以通过BIF适当地去访问属性,看个例子吧 >>> class A(): def __init__(self): self.x = ...

  7. xmanger图形化登陆远程服务器

    由于网上的资料比较杂,经过本人整理实际操作验证,保证ok  本人的服务器系统为centos5.8 下面的都是centos服务器上的操作,需要简单的配置下: win客户端使用xmanger软件:首先是服 ...

  8. js 独立命名空间,私有成员和静态成员

    独立的命名空间   1可以避免全局变量污染. 全局变量污染不是 说 被全局变量污染,而是说不会污染全局变量.   2实现私有成员. 在js中函数 就可以满足独立的命名空间的两点需求.   如:     ...

  9. CAD Import .NET支持AutoCAD DWG 2013

    CADSoftTools发布了CAD Import .NET 9一个新版本.NET开发库,可以提供给开发人员导入AutoCAD DWG.DXF.HPGL.PLT.CGM等格式的功能. 在新版本中,CA ...

  10. 常用的CSS属性列表汇总

    常用的CSS属性列表汇总 近期教学给学员总结常用的CSS属性,方便学习查询,正好发上来也给大家分享一下. 表格最右列的数字标识支持的CSS最低版本. 01. CSS背景属性(Background) 属 ...