常量池之字符串常量池String.intern()
运行时常量池是方法区(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()的更多相关文章
- JVM 常量池、运行时常量池、字符串常量池
常量池: 即class文件常量池,是class文件的一部分,用于保存编译时确定的数据. 保存的内容如下图: D:\java\test\out\production\test>javap -ver ...
- Class常量池、运行时常量池、字符串常量池的一些思考
Class常量池.运行时常量池.字符串常量池 class常量池 java代码经过编译之后都成了xxx.class文件,这是java引以为傲的可移植性的基石.class文件中,在CAFEBABE.主次版 ...
- 彻底搞清楚class常量池、运行时常量池、字符串常量池
彻底搞清楚class常量池.运行时常量池.字符串常量池 常量池-静态常量池 也叫 class文件常量池,主要存放编译期生成的各种字面量(Literal)和符号引用(Symbolic Reference ...
- 运行时常量池中的符号引用/String.intern() /ldc指令
运行时常量池,之前放在方法区(永久代)中,1.8之后被转移到元空间,放到了native memory中. 具体的数据结构是:(看对象的内存布局,句柄访问还是对象头中保存指向类的元数据的指针,这里以对象 ...
- String放入运行时常量池的时机与String.intern()方法解惑
运行时常量池概述 Java运行时常量池中主要存放两大类常量:字面量和符号引用.字面量比较接近于Java语言层面的常量概念,如文本字符串.声明为final的常量值等. 而符号引用则属于编译原理方面的概念 ...
- String:字符串常量池
String:字符串常量池 作为最基础的引用数据类型,Java 设计者为 String 提供了字符串常量池以提高其性能,那么字符串常量池的具体原理是什么,我们带着以下三个问题,去理解字符串常量池: 字 ...
- Java String:字符串常量池(转)
作为最基础的引用数据类型,Java 设计者为 String 提供了字符串常量池以提高其性能,那么字符串常量池的具体原理是什么? 字符串常量池的设计思想是什么? 字符串常量池在哪里? 如何操作字符串常量 ...
- 从HotSpot VM源码看字符串常量池(StringTable)和intern()方法
引言 字符串常量池(StringTable)是JVM中一个重要的结构,它有助于避免重复创建相同内容的String对象.那么StringTable是怎么实现的?"把字符串加入到字符串常量池中& ...
- java字符串常量池——字符串==比较的一个误区
转自:https://blog.csdn.net/wxz980927155/article/details/81712342 起因 再一次js的json对象的比较中,发现相同内容的json对象使用 ...
随机推荐
- java猫和猫的名字
这篇文章之所以叫猫和猫的名字,是因为是以猫为案例来讲的 主要的内容就是java构造函数和参数的传递 class Animal { public static String name; Animal(S ...
- 程序员:统治世界or修复bug?
程序员:统治世界or修复bug? 时至今日,我们依然生活在一个市场和技术受到高度崇拜的世界里,但是历史演化的规律提醒着我们:当一个东西开始成为社会崇拜的对象时,其中暗藏的不利因素将悄然的进行着.有人认 ...
- C# 多线程编程第二步——线程同步与线程安全
上一篇博客学习了如何简单的使用多线程.其实普通的多线程确实很简单,但是一个安全的高效的多线程却不那么简单.所以很多时候不正确的使用多线程反倒会影响程序的性能. 下面先看一个例子 : class Pro ...
- CCPC-Wannafly Winter Camp Day7 (Div2, onsite)
Replay Dup4: 啥都不会? 只能看着两位聚聚A题? X: 模拟题不会写, 日常摔锅 u, v分不清, 日常演员 又是自己没理清楚就抢键盘上机导致送了一万个罚时, 日常背锅 A:迷宫 Solv ...
- poj1228 Grandpa's Estate
地址:http://poj.org/problem?id=1228 题目: Grandpa's Estate Time Limit: 1000MS Memory Limit: 10000K Tot ...
- P1351 联合权值(树形dp)
P1351 联合权值 想刷道水题还交了3次.....丢人 (1.没想到有两个点都是儿子的状况 2.到处乱%(大雾)) 先dfs一遍处理出父亲$fa[x]$ 蓝后再一遍dfs,搞搞就出来了. #incl ...
- SQL优化之limit 1
在某些情况下,如果明知道查询结果只有一个,SQL语句中使用LIMIT 1会提高查询效率. 例如下面的用户表(主键id,邮箱,密码): create table t_user( id int prim ...
- 20145325张梓靖 《Java程序设计》第10周学习总结
20145325张梓靖 <Java程序设计>第10周学习总结 教材学习内容总结 网络编程 网络编程的实质就是两个(或多个)设备(例如计算机)之间的数据传输. 计算机网络 路由器和交换机组成 ...
- 内核加载模块时提示usb_common: exports duplicate symbol of_usb_get_dr_mode
1.分析: 既然符号重复了,那么说明有一个部分既被编译到内核中也被编译成模块了,因此在加载模块时,内核报符号重复的提示 2.解决 直接配置内核的某一部分编译成模块,例如笔者就直接将USB这一部分编译成 ...
- 【Java----判断字符串是否乱码】
import java.util.regex.Matcher; import java.util.regex.Pattern; public class ChineseUtill { private ...