运行时常量池
组成
常量池
就是一张表,虚拟机指令根据这张常量表找到要执行的类名、方法名、参数类型、字面值等信息
- 运行时常量池,常量池是.class文件中,当该类被加载,它的常量池信息就会放入运行时常量池,并把里面的符号地址变为真实地址。
StringTable
先看几道面试题:
String s1 = "a";
String s2 = "b";
String s3 = "a" + "b";
String s4 = s1 + s2;
String s5 = "ab";
String s6 = s4.intern();
//问
System.out.println(s3 == s4); //false
System.out.println(s3 == s5); //true
System.out.println(s3 == s6); //true
String x2 = new String("c") + new String("d");
String x1 = "cd"
x2.intern();
//问,如果调换了【最后两行代码】的位置呢?如果是jdk1.6呢
System.out.println(x1 == x2); //false
调换位置:true
1.6调换位置:false
//StringTable ["a","b","ab"] hashtable结构,不能扩容
public class Demo1_22{
//常量池中的信息,都会被加载到运行时常量池中,这时 a,b,ab都是常量池中的符号,还没有变为java对象
//1dc #2 会把 a 符号变为 "a" 字符串对象
//1dc #3 会把 b 符号变为 "b" 字符串对象
//1dc #4 会把 ab 符号变为 "ab" 字符串对象
public static void main(String[] args){
String s1 = "a"; //惰性的
String s2 = "b";
String s3 = "ab";
String s4 = s1+s2; //new StringBuilder().append("a").append("b").toString() new String("ab)
String s5 = "a" + "b"; //javac 在编译器的优化,结果已经在编译器确定为ab
}
}
StringTable特性
-
常量池中的字符串仅是符号,第一次用到时才会变为对象
-
利用串池的机制,来避免重复创建字符串对象
-
字符串变量拼接的原理是StringBulider(1.8)
-
字符串常量拼接的原理是编译器优化
-
可以使用inter()方法,主动将串池中还没有的字符串对象放入串池 1.8将这个字符串对象尝试放入串池,如果有则并不会放入,如果没有则放入串池,会把串池中的对象返回
1.6将这个字符串对象尝试放入串池,如果有则并不会放入,如果没有会把此对象复制一份,放入串池,会把串池中的对象返回
StringTable位置
StringTable垃圾回收
Stringtable性能调优
-
调整-XX:StringTableSize=桶个数
-
考虑将字符串对象是否入池