栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

30.jvm内存结构部分——StringTable编译期优化

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

30.jvm内存结构部分——StringTable编译期优化

package design.wlb.studyjava.demo.restudy.c4jvm专题.chapter02.c30StringTable编译期优化;

public class Client {
	//我们通过new关键字创建的堆对象,都会使用堆的内存。
	//jdk1.6中,StringTable串池在常量池在方法区中,jdk1.8中,常量池在元空间不归jvm管理,但串池不在常量池中,是在堆中。

	//StringTable["a","b","ab"](懒加载)
	public static void main(String[] args) {
		String s1 = "a";		//ldc #2 astore_1 从常量池加载为java字符串常量对象,将这个对象放入串池中,并存储到局部变量表的1号位置。
		String s2 = "b";
		String s3 = "ab";
		String s4 = s1 + s2;
		String s5 = "a"+"b";	//javac编译器优化,在编译时,直接认为此为固定的常量 "ab" ,故而反编译后的指令为ldc #4 astore 5 存入到第五个局部变量表中
		System.out.println(s5==s3);

		//s4在非串池的其他堆中,s5在串池中。
	}

	
}

由我们的javap反编译工具可知,

String s5 = "a"+"b";

在jvm指令对应的是"ldc #4", 以及astore 5


它和我们想象的有点区别,它并不是使用的StringBuilder进行字符串拼接了,因为此处"a"+"b",两者都是字符串常量,在javac编译期,jdk就认识它只会是"ab".故而,进行了java编译期优化,在生成的class文件后,就已经变成了String s5 = "ab";

所以它的加载方式也和s3一模一样。ldc #4 astore 5,从运行时常量池中取出"ab",然后存入局部变量表的5号位置【astore aload 是一对操作局部变量表的jvm指令】


也就是说,jvm从运行期常量池查表#4的位置获取将其变为java对象"ab",再将java字符串常量对象"ab"放入串池(另一个堆区),但放入串池中的时候会去查串池中的key 有不有,此时因为有了String s3 = "ab",串池中已经有了"ab",所以jvm直接从串池中查表找到了它。

所以s3和s5都是从串池中获取值,故而s3 == s5 答案是false;


补充:

1.串池也叫字符串常量池

2.串池可以理解为逻辑上在运行期常量池里面(jdk1.6在永久代里面,物理上也是在运行常量池中,jdk1.8运行期常量池在元空间里面,但串池逻辑上在,但物理上是存在jvm的堆中)

好,这一篇就讲到这里。

上一篇:29.jvm内存结构部分——StringTable_字符串变量的拼接_tgbyhn31的博客-CSDN博客

下一篇:31.jvm内存结构部分——StringTable字符串延迟加载_tgbyhn31的博客-CSDN博客

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/1003950.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号