常量池,运行时常量池,字符串常量池

常量池

  • 基本介绍

常量池:就是一张表,虚拟机指令根据这张常量表找到要执行的类名,方法名,参数类型,字面量(字符串,基本类型)等信息

运行时常量池:常量池是字节码文件中的,当该类被加载,它的常量池信息就会被放入运行时常量池中,并把里面的符号地址变成真实地址

常量池在运行时会被加载到运行时常量池中,这时常量池中的信息还只是常量池中的符号,还没有变成java对象

等到具体执行到引用此符号的那行代码时,将其变为对象


String str="a";的底层具体执行流程
常量池中存储着此字符串定义的信息符号,当该类被加载时,常量池被加载到运行时常量池中,这时常量池中的信息仍然是符号,还没有变成java对象,直到执行引用此符号的代码时才将此符号变为对象,“a”符号变为字符串对象,这时需要准备一块空间StringTable(字符串常量池)(此空间相当于一个哈希表(HaehTable),此哈希表结构固定,不能扩容);
将"a"对象作为key在字符串常量池中查找是否有与之相等的值,没有时,将此字符串放入到字符串常量池中
注意:每个字符串对象不是最开始就放入字符串常量池中,而是当用到时再创建其对象
String a="a";String b="b";
String c="ab";
String d=a+b;底层实现流程
new StringBudder().append("a").append("b").toString(); new String("ab");
字符串变量拼接原理:StringBilder(jdk1.8);此时的new String("ab")并没有在字符串常量池中存放,它在堆中存放
Syatem.out.println(c==d);
返回false;
c直接指向字符串常量池中的"ab"对象;
而d是new了一个String对象在堆中存储着
String s1="a"+"b";
javac在编译期间优化,结果已经在编译期间确定为ab
字符串常量的拼接原理:编译器优化

  • StringTable的特性

  1. StringTable的底层是HashTable

  2. 常量池中的字符出仅仅是符号,第一次用到时才变为对象。

  3. 利用串池的机制来避免重复创建字符串对象

  4. 字符串变量拼接的原理:StringBuilder

  5. 字符串常量拼接的原理是编译期优化

  6. 使用intern方法,主动将串池中还没有的字符串对象放入串池,

    例如String s1=new String("a")+new String("b");此时是字符串变量的拼接,new String("ab")在堆中存储,并未存到常量池中。

    1.8将这个字符串对象尝试放入串池,如果有则不会放入,如果没有则放入串池,会把串池中的对象返回。

    1.6将这个字符串对象尝试放入串池,如果有则不会放入,如果没有则将对象复制一份放入串池,会把串池中的对象返回。

  • StringTable存放位置

    在jdk1.6时,StringTable是常量池的一部分,随着常量池存储在永久代(PermGen)中

    jdk1.7开始,常量池被转入堆(Heap)中;

    做出此调整的原因:永久代的内存回收效率很低,只有老年代的内存不足,才会触发永久代的垃圾回收,间接导致StringTable的垃圾回收效率低下,然而StringTable的使用很频繁会占用永久代的大量内存

  • StringTable垃圾回收机制

    String是会触发垃圾回收的

  • StringTable调优

    1,调整 -XX:StringTableSize:桶的个数

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

六一快乐…………

posted on 2021-06-01 19:24  凡人精灵  阅读(586)  评论(0编辑  收藏  举报

导航