常量池、运行时常量池、stringTable

1 篇文章 0 订阅

三者关系

1、常量池:俗称静态常量池,存在于*.class文件中,就是一张表,虚拟机指令根据这张表找到要执行的类名、类方法、参数类型、字面量等信息
常量池:
在这里插入图片描述
虚拟机指令:
在这里插入图片描述
2、运行时常量池:类被加载时,其常量池信息会被放入运行时常量池,并把里面的符号地址变为真实地址。

3、StringTable 串池:运行时常量池的 一部分,储存字符串常量

StringTable

特性

1、stringTable数据结构为一个hash表(数组+链表),不可扩容,存字符串常量,唯一不重复。
2、常量池中的字符串仅是符号,第一次用到才变为对象
3、其创建方式为懒创建,用到时才创建。

在这里插入图片描述

如图:当类被加载时,a b ab 都是常量池中的符号,还未变成java字符串对象。
当图中1执行时,会先去stringtable中看看是否有“a”,发现没有,将“a”加入字符串常量池stringtable
2、3也是如此,当下次有类似String s4 = “ab” 时,stringtable会直接引用已存在的“ab” ,故s4==s3。

4、字符串变量的拼接原理是StringBuilder,如String s4 = s1+s2;//等价于new StringBuilder().append(“s1”).append(“s2”).toString,所以字符串变量拼接是new出了一个字符串对象,存在于java堆中
5、字符串常量拼接原理是编译期优化,String s3 = “a”+“b”;//直接寻找拼接之后的“ab”,若在stringTable中,直接引用,否则加入stringTable
6、可以使用String.intern()方法,主动将StringTable中还没存在的字符串对象加入StringTable
》6.1、jdk1.8中intern将字符串对象放入StringTable,如果有则不会放入,否则放入StringTable,最终都会返回StringTable中的对象
》6.2、jdk1.8中intern将字符串对象放入StringTable,如果有不放入,否则复制会把该对象复制一份放入StringTable,最终返回StrinTable中的对象

    public static void main(String[] args) {
        String s1 = "a";
        String s2 = "b";
        String s3 = "a"+"b";
        String s4 = s1+s2;//等价于new StringBuilder().append("s1").append("s2").toString
        String s5 = "ab";
        String s6 = s4.intern();

        System.out.println("s3==s4:"+ (s3==s4));//false
        System.out.println("s3==s5:"+ (s3==s5));//true
        System.out.println("s3==s6:"+ (s3==s6));//true

        String x2 = new String("c") + new String("d");
        String x1 = "cd";//1
        x2.intern();//2
        //如果怕调换1、2顺序,则下面的结果为true,但前提是jdk1.6以上,若是jdk1.6则还是false
        System.out.println("x2==x1:"+ (x2==x1));//false


        final String a = "123";//
        final String b = "456";
        String c = "123456";
        String d = a + b;//此处a、b被final修饰,相当于常量

        System.out.println("c == d:"+ (c == d));//true
    }

串池位置

1、jdk1.6前存在方法区的永久代中
2、jdk1.6后存在堆中

永久代中只有fullGC才可回收,回收效率低,浪费内存
在这里插入图片描述

StringTable垃圾回收

因为StringTable为不可扩容的Hash表,所以内存满时会进行垃圾回收

StringTable性能调优

1、如字符串常量较多(如读取大文件)可调整-XX:StringTableSize=桶个数
减少串池hash冲突
2、考虑通过intern将字符串对象入池,减少内存开销
未入池的字符串对象每个都要再堆中分配内存,而在串池中重复的字符串引用同一个字符串对象
参考:java中级程序员必会的教程,解密JVM【黑马程序员出品】

  • 5
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值