常量池,运行时常量池,字符串常量池
作者:互联网
常量池
-
基本介绍
常量池:就是一张表,虚拟机指令根据这张常量表找到要执行的类名,方法名,参数类型,字面量(字符串,基本类型)等信息
运行时常量池:常量池是字节码文件中的,当该类被加载,它的常量池信息就会被放入运行时常量池中,并把里面的符号地址变成真实地址
常量池在运行时会被加载到运行时常量池中,这时常量池中的信息还只是常量池中的符号,还没有变成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的特性
-
StringTable的底层是HashTable
-
常量池中的字符出仅仅是符号,第一次用到时才变为对象。
-
利用串池的机制来避免重复创建字符串对象
-
字符串变量拼接的原理:StringBuilder
-
字符串常量拼接的原理是编译期优化
-
使用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,考虑将字符串对象是否入池
六一快乐…………
标签:常量,对象,池中,串池,字符串,运行,String 来源: https://www.cnblogs.com/ekig/p/14838548.html