常量池之字符串常量池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对象使用 ...
随机推荐
- linux更改文件或目录的属主和属组
chown 1.效用 更改一个或者多个文件或者目录的属主以及属组,使用职权范围是超等用户 2.格局 chown [选项] 用户或者组 文件 3.首要参量 --dereference:受影响 ...
- 解决升级到Xcode10,react native项目运行报错问题
今天刚升级到Xcode10,就遇到两个报错问题 错误一:Xcode 10: Build input file double-conversion cannot be found error: Buil ...
- Bootstrap fileinput v2.0(ssm版)
前言bootstrap fileinput是一个很好的文件上传插件.但是官方不出api,这就尴尬了.百度一下,每个人写法都不相同,好多代码本身都是错的.我修改后才能跑起来.综上所述:所以今天我摸索了一 ...
- G.Finding the Radius for an Inserted Circle 2017 ACM-ICPC 亚洲区(南宁赛区)网络赛
地址:https://nanti.jisuanke.com/t/17314 题目: Three circles C_{a}Ca, C_{b}Cb, and C_{c}Cc, all ...
- Python面试题目之打乱打乱有序列表
# 要求打乱一个有序列表 # 待处理列表 L1 = [11,22,33,44,55,66,77,] 方法: # 引入random模块,该模块的shuffle方法见下图 import random L1 ...
- git clone时提示(gnome-ssh-askpass:29288): Gtk-WARNING **: cannot open display:
一.背景 在服务器上克隆源码 二.解决 unset SSH_ASKPSS
- What's the difference between SDK and Runtime in .NET Core?
What's the difference between SDK and Runtime in .NET Core? Answer1 According to the .Net Core Guide ...
- 利用ES6中的Array.find/ Array.findIndex来判断数组中已存在某个对象
前端开发过程中,我们会经常遇到这样的情景:比如选中某个指标obj,将其加入到数组checkedArr中({id: 1234, name: 'zzz', ...}),但是在将其选中之前要校验该指标是否已 ...
- C# 后台模块 Word 模板操作
public static string CreateWord() { //********************************************** //来自博客http://bl ...
- npm package.json中的dependencies和devDependencies的区别
转载:http://www.cnblogs.com/jes_shaw/p/4497836.html 一个node package有两种依赖,一种是dependencies一种是devDependenc ...