JVM-07运行时常量池

44 阅读2分钟

运行时常量池

组成

image.png

常量池

就是一张表,虚拟机指令根据这张常量表找到要执行的类名、方法名、参数类型、字面值等信息

  • 运行时常量池,常量池是.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位置

image.png

StringTable垃圾回收

Stringtable性能调优

  • 调整-XX:StringTableSize=桶个数

  • 考虑将字符串对象是否入池