视频资源地址笔记资源地址我的笔记
27.stringtable·面试题 + 28.常量池与串池的关系29.字符串变量拼接30.编译器优化31.字符串延迟加载31.stringtable_intern_1.8
视频资源地址B站 https://www.bilibili.com/video/av70549061
笔记资源地址https://www.bilibili.com/video/av70549061
我的笔记 27.stringtable·面试题 + 28.常量池与串池的关系首先写一段声明字符串的代码,通过反编译查看他的常量池的样子。
关键指令:javap -v class地址
看字节码的内容,这一行:去常量池2位置中加载信息。 然后存入局部变量1中。如下图局部变量表。
以此类推,下图中三个变量都是这样加载进来,并赋值在局部变量表的。
常量池是存在字节码文件中的,上面这个例子已经证明了,但是这个静态的,当它运行起来之后,就会被加载到运行时常量池。如下图这些都会被加载到运行时常量池:
注意:
当字节码执行到ldc的时候,才会将符号跟java对象联系起来。
此时,会去查看Stringtable,。也就是所谓的串池,有没有包含a,如果不包含就加入进去。
这个行为是一个懒惰的行为,代码中用到这个对象,才会去串池中查找或者添加。
原文笔记:
反编译之后如下图所示。相当于执行了注释中的操作。
问题:
答案是fasle。因为s3在串池里,s4在堆里。 tostring方法的本质是调用了new string(“ab”) 方法。他俩的位置不一样,是两个对象。
新建一个string s5 = “a” + “b”; 然后反编译。
他是直接去常量池中加载的#4这个常量。并且存入了5号局部变量表。
所以s3和s5的变量都是存储的串池中的同一个字符串常量,所以他俩是相等的。
“a” + “b” 是 javac在编译期的优化。 这俩都是常量,相加不会变了,结果在编译期间已经确定为“ab”。
跟s4不一样,s4的生成是两个变量相加,需要动态拼接。就到了堆中了。
上面这个例子。只会在串池中创建10个对象,再下面继续打印,就是用的串池中的了。



