常量池 StringTable

stringtable

  • 常量池是 .class文件,存放堆中数据的引用地址,而不是真实的对象,运行时常量池是jvm运行时将常量池中数据放入池中,此时引用地址真正的指向对象而不是.class文件;Stringtable是哈希表(不能扩容),它也叫做串池,用来存储字符串,这3个不是同一个东西,我们需要进行区分
  • String table中存储的并不是String类型的对象,存储的而是指向String对象的索引,真实对象还是存储在堆中
  • jdk1.6中,Stringtable是放在永久代(方法区)中,jvm进行FullGC才会对常量池进行垃圾回收,影响效率,因此在jdk1.8中将Stringtable放在堆中,jvm内存紧张时就会对Stringtable进行垃圾回收

StringTable 特性

  • 常量池中的字符串仅是符号,第一次用到时才变为对象
  • 利用串池的机制,来避免重复创建字符串对象
  • 字符串变量拼接的原理是StringBuilder (1.8)
  • 字符串常量拼接的原理是编译期优化 可以使用 intern方法,主动将串池中还没有的字符串对象放入串池
    • jdk1.8 将这个字符串对象尝试放入串池,如果有则并不会放入,如果没有则放入串池, 会把串 池中的对象返回
    • jdk1.6 将这个字符串对象尝试放入串池,如果有则并不会放入,如果没有会把此对象复制一份 (此时原对象还是指向原对象而不是池中的返回的对象), 放入串池, 会把串池中的对象返回

jvm参数设置

-XX:StringTableSize=桶个数

常见面试题

 public static void main(String[] args) {
        String str1 = "abc";
        //编译期间对其优化,实际待放入池中的数据就是“abc” , 此时池中已有该数据 ,则返回str1放入池中的“abc”的引用
        String str2 = "ab" + "c"; 
        //new出来的对象都是在堆中,因此str3和str1地址不同
        String str3 = new String("ab") + "c";
        //入池,已存在,返回池中对象
        String str4 = str3.intern();
        System.out.println(str1 == str2); // true
        System.out.println(str1 == str3); // false
        System.out.println(str1 == str4); // true
    }

参考资料:
https://blog.csdn.net/gw_9527/article/details/103002455
https://blog.csdn.net/Liyuehahaha/article/details/102547755


版权声明:本文为shuaigeyimei1原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。