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在串池中。
}
/**
* 0: ldc #2 // String a
* 2: astore_1
* 3: ldc #3 // String b
* 5: astore_2
* 6: ldc #4 // String ab
* 8: astore_3
* 9: new #5 // class java/lang/StringBuilder
* 12: dup
* 13: invokespecial #6 // Method java/lang/StringBuilder."<init>":()V
* 16: aload_1
* 17: invokevirtual #7 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
* 20: aload_2
* 21: invokevirtual #7 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
* 24: invokevirtual #8 // Method java/lang/StringBuilder.toString:()Ljava/lang/String;
* 27: astore 4
*
* 29: ldc #4 // String ab
* 31: astore 5
* 33: getstatic #9 // Field java/lang/System.out:Ljava/io/PrintStream;
* 36: aload 5
* 38: aload_3
* 39: if_acmpne 46
* 42: iconst_1
* 43: goto 47
* 46: iconst_0
* 47: invokevirtual #10 // Method java/io/PrintStream.println:(Z)V
* 50: return
*/
}
由我们的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的堆中)
好,这一篇就讲到这里。