jvm stringTable

本文探讨了Java中字符串常量池在JDK6和7/8版本中的行为差异:在JDK6中,堆空间和常量池地址不一致导致`s == s1`比较为false;而在JDK7/8中,字符串常量池移至堆内存,相同字符串会指向同一地址,`s == s1`在新版本下可能为true。
public class Demo1 {

	public static void main(String[] args) {

		String s = new String("111");
		s.intern();
		String s1 = "111";

		System.out.println(s == s1); //jdk6 : false    jdk7/8 : false

	}

}

字节码文件 : 

1-5 : 创建一个string对象, 并把这个string对象的值存储到常量池中(ldc指令)

6 : 调用string的intern方法, 将字符串存储到常量池中,  如果字符串常量池中存在该变量, 则返回字符串常量池中的地址

无论是jdk6 或者是jdk7/8   s=s1 比较的都是堆空间的地址和常量池中的地址, 所以全是false

2. 

public class Demo1 {

	public static void main(String[] args) {

		String s = new String("111") + new String("222");
		s.intern();
		String s1 = "111222";

		System.out.println(s == s1); //jdk6 : false    jdk7/8 : true

	}

}

 字节码 : 

1. 首先讨论  

String s = new String("111") + new String("222"); 创建了多少对象

对象1 : new StringBuilder();

对象2 : new String("111");

对象3 : 字符串常量池中的"111"

对象4 : new String("222")

对象5 : 字符串常量池中的"222"

对象6 : StringBuilder.toString()方法创建的字符串对象

注意 : StringBuilder.toString()创建的string对象不会同步到字符串常量池中

new String(); 创建的对象会同步到字符串常量池中

 结果讨论 : 

在jdk6中 , 方法区的实现是永久代,  字符串常量池存放在永久代中, 因此

String s = new String("111") + new String("222")和 String s1 = "111222" 比较的仍然是堆空间和常量池中的两个不同地址

在jdk7/8之后, 方法区的实现是原空间,  并且将字符串常量池存放到堆空间 , 当定义一个字符串对象时 , 如果堆中存在该对象,  那么在常量池中存放的就是堆空间中的地址, 因此结果为true

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值