运行时常量池是方法区(PermGen)的一部分。

需要提前了解:
1. JVM内存模型
2. JAVA对象在JVM中内存分配

常量池的好处

常量池是为了避免频繁的创建和销毁对象而影响系统性能,其实现了对象的共享。
- Java的自动装箱中其实就使用到了运行时常量池。详见:Java 自动装箱与拆箱的实现原理
- 还有字符串常量池。

字符串进入到常量池的两种方法:

1. new String()的实例调用intern()方法。
    执行intern()方法时,若常量池中不存在等值的字符串,JVM就会在常量池中 创建一个等值的字符串,然后返回该字符串的引用。
2. “”(引号)引起来的内容(字面量)。
    引号引起来的字符串,首先从常量池中查找是否存在此字符串,如果不存在则在常量池中添加此字符串对象,然后引用此字符串对象。如果存在,则直接引用此字符串。

重要提示:虚拟机启动时常量池中就存在“java”字符串实例,下面代码中s2调用intern()方法时,只是返回常量池中“java”实例的引用,而没有添加“java”实例。

先看下,下面的代码

 public class Test {
public static void main(String[] args) {
String s1 = new StringBuilder().append("aa").append("bb").toString();
System.out.println(s1.intern() == s1);
String s2 = new StringBuilder().append("ja").append("va").toString();
System.out.println(s2.intern() == s2);
}
}

输出结果如下:

JDK6

false
false

JDK7、JDK8

true
false

为什么不同版本的JDK输出的结果还不一样呢?带着疑问我们分别分析下JDK1.6 和JDK1.7-JDK1.8的常量池内存模型。

JDK1.6 常量池内存模型

如图中,我们可以看到常量池位于方法区(PermGen),常量池中引用的字符串实例也在常量池中。
1、通过调用intern()方法,会在常量池中生成一个相同字符串的对象
2、“”内的字符串都会添加到常量池中,相当于引用的方法区中的字符串对象。

根据上图内存模型然后我们在分析下代码:

String s1 = new StringBuilder().append(“aa”).append(“bb”).toString();
System.out.println(s1.intern() == s1);
s1生成的对象在堆中,而s1.intern()的对象在常量池中,所以返回false。

String s2 = new StringBuilder().append(“ja”).append(“va”).toString();
System.out.println(s2.intern() == s2);
s2生成的对象在堆中,而s2.intern()的对象也肯定在常量池中,所以也返回false。

JDK1.7-JDK1.8常量池内存模型

如图中,我们可以看到常量池位于方法区(PermGen),但常量池引用的字符串实例在中。(区别在这)
1. 通过调用intern()方法,会在常量池添加一个此字符串实例的引用,(前提:常量池中没有相同内容的字符串)。
2. “”内的字符串实例引用会添加到常量池中(前提:常量池中没有相同内容的字符串),如果常量池中存在,则引用常量池中的对象(防止重复创建对象)。

根据上图内存模型然后我们在分析下代码:
String s1 = new StringBuilder().append(“aa”).append(“bb”).toString();
System.out.println(s1.intern() == s1);
s1生成的对象在堆中,此时常量池中没有跟s1内容相同的字符串,所以在调用intern方法时,会在常量池中添加此对象的引用,所以返回为true。

String s2 = new StringBuilder().append(“ja”).append(“va”).toString();
System.out.println(s2.intern() == s2);
s2生成的对象在堆中,而此时常量池中已经有一个跟s2内容相同的字符串常量,当s2调用intern方法时,返回常量池中已经存在的实例(相当于堆中有两个相同内容的实例:一个是new 出来的,一个是常量池中的)所以返回的结果为false。

常量池之字符串常量池String.intern()的更多相关文章

  1. JVM 常量池、运行时常量池、字符串常量池

    常量池: 即class文件常量池,是class文件的一部分,用于保存编译时确定的数据. 保存的内容如下图: D:\java\test\out\production\test>javap -ver ...

  2. Class常量池、运行时常量池、字符串常量池的一些思考

    Class常量池.运行时常量池.字符串常量池 class常量池 java代码经过编译之后都成了xxx.class文件,这是java引以为傲的可移植性的基石.class文件中,在CAFEBABE.主次版 ...

  3. 彻底搞清楚class常量池、运行时常量池、字符串常量池

    彻底搞清楚class常量池.运行时常量池.字符串常量池 常量池-静态常量池 也叫 class文件常量池,主要存放编译期生成的各种字面量(Literal)和符号引用(Symbolic Reference ...

  4. 运行时常量池中的符号引用/String.intern() /ldc指令

    运行时常量池,之前放在方法区(永久代)中,1.8之后被转移到元空间,放到了native memory中. 具体的数据结构是:(看对象的内存布局,句柄访问还是对象头中保存指向类的元数据的指针,这里以对象 ...

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

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

  6. String:字符串常量池

    String:字符串常量池 作为最基础的引用数据类型,Java 设计者为 String 提供了字符串常量池以提高其性能,那么字符串常量池的具体原理是什么,我们带着以下三个问题,去理解字符串常量池: 字 ...

  7. Java String:字符串常量池(转)

    作为最基础的引用数据类型,Java 设计者为 String 提供了字符串常量池以提高其性能,那么字符串常量池的具体原理是什么? 字符串常量池的设计思想是什么? 字符串常量池在哪里? 如何操作字符串常量 ...

  8. 从HotSpot VM源码看字符串常量池(StringTable)和intern()方法

    引言 字符串常量池(StringTable)是JVM中一个重要的结构,它有助于避免重复创建相同内容的String对象.那么StringTable是怎么实现的?"把字符串加入到字符串常量池中& ...

  9. java字符串常量池——字符串==比较的一个误区

    转自:https://blog.csdn.net/wxz980927155/article/details/81712342   起因 再一次js的json对象的比较中,发现相同内容的json对象使用 ...

随机推荐

  1. 前端基础(JavaScript)

    JavaScript概述 JavaScript的历史 1992年Nombas开发出C-minus-minus(C--)的嵌入式脚本语言(最初绑定在CEnvi软件中).后将其改名ScriptEase.( ...

  2. php时间戳函数mktime()

    在项目开发中,偶尔会遇到跨周期.跨月的的时间操作.PHP为我们提供了一个很方便的函数->mktime,可以很简单的获取制定日期的时间戳了. mktime(hour,minute,second,m ...

  3. Python3.x:生成器简介

    Python3.x:生成器简介 概念 任何使用yield的函数都称之为生成器:使用yield,可以让函数生成一个序列,该函数返回的对象类型是"generator",通过该对象连续调 ...

  4. Today's harvest !!!

    今天将Mybatis的视频看到了第60集,其之前讲解了自表的主外键查询.例如一个新闻表中,有一级栏目,二级栏目,三级栏目,其中二级栏目的pid为一级栏目的id,如此种种. 而今天做的小项目中使用了 e ...

  5. spring boot2 基于百度云apiface实现人脸检测与认证1

    原理介绍: 基于百度云的人脸资料库(用户上传),调用本地摄像头抓拍的图像,与百度云的用户图像做比对,实现人脸认证. 主要步骤如下: 1. 创建百度去账号 2. 在百度云控制台中创建人脸识别的应用,并记 ...

  6. 理解if __name__ == '__main__':

    一开始没怎么注意这个语句,这两天在模拟知乎登陆时准备刨根问底了,先看两行代码片段 第一个例子:这是在login.py文件的一部分,其他我们忽略,只关注print()函数的内容 import time ...

  7. 安装lua 环境

    lua下载地址:https://www.lua.org/download.html curl -R -O http://www.lua.org/ftp/lua-5.3.5.tar.gz tar zxf ...

  8. Linux常用命令--文件操作、权限设置

    1.编辑文件 cat aaa.txt 查看aaa.txt文件的内容 head - aaa.txt 查看aaa.txt文件前5行的内容 tail - aaa.txt 展示aaa.txt文件最后10行的内 ...

  9. ng-grid

    请查看官网:http://angular-ui.github.io/ui-grid/ 简单的使用: 总的来说我们 1.需要引入ng-grid-1.3.2.js 2.在html页面需要加入  class ...

  10. 最近公共祖先问题 LCA

    2018-03-10 18:04:55 在图论和计算机科学中,最近公共祖先,LCA(Lowest Common Ancestor)是指在一个树或者有向无环图中同时拥有v和w作为后代的最深的节点. 计算 ...