String intern
String类中有个intern()
的native,该方法会查询常量池中是否存在该字符串,若存在,则返回;若不存在则加入常量池并返回。在实现细节方面,JDK6又是与JDK7是不一样的。
1 | public native String intern(); |
下面以一段常见的demo来说明问题。
String的创建:
直接使用双引号声明出来的
String
对象会直接存储在常量池中。使用new关键字创建的
String
对象存储在堆中。
1 | public static void main(String[] args) { |
该程序在JDK6上的内存结构图
该程序在JDK7上的内存结构图
1 | public static void main(String[] args) { |
该程序在JDK7上的内存结构图
在不同的JDK中,常量池存放的地方也不同
JDK6:常量池在永久代中
JDK7:常量池在堆中
JDK8:常量池在元空间中
其中永久代和元空间都是方法区的一种HotSpot VM实现,方法区是JVM所定义的规范。
结合常量池的存放位置,可以更好地理解intern()行为的区别。在JDK6中,永久代和堆不一样,所以常量池无相应字符串时会创建新对象。在JDK7中,由于都在堆中,常量池会引用堆中的字符串对象,不会创建新对象。
Reference
https://tech.meituan.com/2014/03/06/in-depth-understanding-string-intern.html