StringTable

StringTable

运行时常量池

在这里插入图片描述
细节参考:https://www.cnblogs.com/54chensongxia/p/13708767.html

class文件 二进制字节码(类基本信息,常量池,类方法定义(包含了虚拟机指令))
常量池作用是给指令提供一些常量符号,根据常量符号以查表<符号表>方式查找 
常量池,就是一张表,虚拟机指令根据这张常量表找到要执行的类名、方法名、参数类型、字面量(字符串,整数,boolean类型..)等信息
运行时常量池,常量池是 *.class 文件中的,当该类被加载,它的常量池信息就会放入运行时常量池,并把里面的符号地址变为真实地址   运行时常量池有StringTable,符号表(类字节码中的类名,方法名,变量名。。。)

StringTable

String s1 = "a";
String s2 = "b";
String s3="ab";
常量池中:常量,对象的引用
常量池最初存在于字节码文件,运行时加载到运行时常量池中,这时候都()是常量池中的符号,还没变成java字符串对象,执行到ldc #2 会把符号变为 "a" 字符串对象,然后准备好一片空间StringTable[] (刚开始是空的,数据结构是hash表),没找到"a",就把"a"字符串对象放入串池塘,"b"同理。用到这行代码才会开始创建这个字符串对象(ldc(加载) #2)(懒惰行为)
"ab"类似 
String s1 = "a";
String s2 = "b";
String s3="ab";
String s4 = s1 + s2;
new StringBuilder().append("a").append("b").toString()
toString()方法又new String(new StringBuilder().append("a").append("b"))=new String("ab") jdk1.8
System.out.println(s3==s4); false
s3在串池 s4在堆中
String s1 = "a";
String s2 = "b";
String s3="ab"; "ab" 执行到这还没有被创建,会创建
String s4 = s1 + s2;
String s4="a"+"b";在常量池中直接找到的已有"ab" javac在编译器的一个优化,编译期间结果已经确定为ab(都是常量),

String s4 = s1 + s2; s1 s2是变量,在运行只可能被修改,结果不能确定,必须在运行期间用 StringBuilder 动态拼接
System.out.println("xxx");也会创建字符串对象放入串池,他是执行到这行才会创建。(字符串延迟加载)

intern

可以使用 intern 方法,主动将串池中还没有的字符串对象放入串池
    1.8 将这个字符串对象尝试放入串池,如果有则并不会放入,如果没有则放入串池, 会把串池中的对象返回
        //["a","b"]
        String s = new String("a") + new String("b");
        //堆中 new String("a")   new String("b") new String("ab")
        String s2 = s.intern(); //把s这个字符串<对象>尝试放入串池,如果有并不会放入,如果没有则放入,返回串池中的对象,这里是成功
        System.out.println(s2 == "ab");//true
        System.out.println(s == "ab");//true
=================
        String x = "ab"; //["ab"]
        String s = new String("a") + new String("b");
        //堆中 new String("a")   new String("b")  new String("ab")//["ab","a","b"]
        String s2 = s.intern(); //把s这个字符串<对象>尝试放入串池,如果有并不会放入,如果没有则放入,返回串池中的对象,这里是失败
        System.out.println(s2 == "ab");//true s2串池中
        System.out.println(s == "ab");//true  s堆   

===========================================================================================
   1.6 将这个字符串对象尝试放入串池,如果有则并不会放入,如果没有会把此对象复制一份,放入串池,会把串池中的对象返回	 放入串池的对象与调用intern的对象是两个对象。 副本和堆中不是一个
        String x = "ab"; //["ab"]
        String s = new String("a") + new String("b");
        //堆中 new String("a")   new String("b") new String("ab")//["a","b","ab"]
        String s2 = s.intern(); //把s这个字符串<对象>尝试放入串池,如果有并不会放入,如果没有则拷贝一份放入,返回串池中的对象,这里是失败 ["a","b","ab"]
        System.out.println(s2 == x);//true  s2串池的 x串池的
        System.out.println(s == x);//false  s堆中的
=================
        String s = new String("a") + new String("b"); //["a","b"]
        //堆中 new String("a")   new String("b") new String("ab") 
        String s2 = s.intern(); //把s这个字符串<对象>尝试放入串池,如果有并不会放入,如果没有则拷贝一份放入,返回串池中的对象,这里是成功  ["a","b","ab"]
        String x = "ab"; 
        System.out.println(s2 == x);//true  s2串池的 "ab串池的"
        System.out.println(s == x);//false s堆中的

StringTable的位置

1.7从永久代到堆中,永久代回收效率低(Full GC才会回收),间接导致StringTable回收效率低,容易导致永久代内存不足。

堆中Minor GC就会回收。

往常量池灌字符串常量并且加入list,防止垃圾回收

1.6 OOM(PermGen space)

1.7 OOM(GC overhead limit exceede) 98%时间 2%被回收 关闭这个选项就是OOM(java heap space)

StringTable垃圾回收机制

底层类似hash表,数组()+链表 会垃圾回收

StringTable性能调优

数组()越多,冲突小,查找速度越快,入池时间越短。调优就是调整桶的个数至少1009 -XX:StringTableSize=xx
    
考虑将字符串对象是否入池 (相同字符串,不会入池)去重
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值