目录:
(1)StringTable的特性
(2)StringTable_intern_1.6
(3)StringTable-面试题
(4)StringTable的位置
(5)StringTable-垃圾回收
(6)StringTable调优
(1)StringTable的特性
(2)StringTable_intern_1.6
1.6
1.8:
(3)StringTable-面试题
1.6:
(4)StringTable的位置
永久代内存回收效率很低,永久代在复制gc的时候 ,才会触发永久代的垃圾回收,复制jc只有等到老年代的空间不足才会触发,触发的时机较慢,才会导致StringTable的回收效率不高,StringTable用的非常的频繁,我们java程序中大量的字符串、常量对象都会分配到StringTable中,如果StringTable的回收效率不高就会占用大量的内存,容易导致永久代的内存不足,这就是它的缺点
1.8的时候把StringTable转移到了堆里面,很容易把用不到的常量对象进行垃圾回收,就大大减轻了字符串对内存的占用
此时没有报错,更改虚拟机的内存设置 :设置永久代的最大内存大小
在次运行:报的是永久代的内存溢出异常
在1.8环境下运行此代码:
修改最大堆内存设置
如果98%的时间用到垃圾回收上,只有2%的堆空间回收了,会报下面的异常,如果想要报堆空间不足的异常需要加参数
重新运行:此时是堆控件不足
此时就证明了1.8,串池用的是堆内存 空间,1.6串池用的是永久代
(5)StringTable-垃圾回收
StringTable也会收到垃圾回收的管理的,当内存空间不足时,StringTable没有引用的字符串常量仍然会被垃圾回收,
Xmx10m:设置虚拟机堆内存大小
-XX:+PrintString... :打印字符串表的统计信息通过它我么可以见到串池中字符串实例的个数、大小信息
-XX :+PrintGC...:打印垃圾回收的相关信息,把垃圾回收的次数啊、花费的时间显示出来
运行:首先是堆内存的占用
符号表:类的字节码里面类名、方法名、变量名,他们也需要读入到内存中,将来以查表的方式找他们
StringTable的底层实现类似于HashTable,哈希表示数组加链表
数组的个数称为桶bucket
Number of buckets:桶的个数
Number of entries:键值对的个数
Number of literals:字符串常量的个数
Total footprint:总的占用空间
运行:发现字符常量个数变大
修改:变大写入串池的个数
并触发GC垃圾回收 ,并在控制台打印
(6)StringTable调优
StringTable的底层是哈希表,哈希表的性能是跟它的大小相关的,如果哈希表桶的个数较多,相对元素分散,哈希碰撞的几率减少查找的速度变快,反之,桶的个数较少,那么哈希碰撞的几率增高,导致链表较长,从而查找的速度收到影响 通过下面案例,调整=桶的个数
去掉设置的这个参数
此时花费的时间变多了
默认桶的大小
设置小一些:
花费时间:
String占用
在idea回车后:String的占用情况
通过读取到常量池: