黑马JVM总结(八)

(1)StringTable面试题

1.8

1.6时

(2)StringTable的位置

jvm1.6时StringTable是常量池的一部分,它随着常量池存储在永久代当中,在1.7、1.8中从永久代变成了堆中,为什么做这个更改呢?因为永久代的内存效率很低,永久代是在Full GC的时候才会触发永久代的垃圾回收,Full GC只有等到老年代的空间不足时才会触发,触发的时机比较晚导致StringTable的回收效率不高

StringTable用的非常的频繁它里面存储的都是字符串常量,我们java程序中字符串常量对象都会分配到StringTable中,它的回收效率不高会占用大量的内存,它的效率不高,会产生永久代的内存不足,基于这个缺点,把它转到堆里面,在堆里面只需要Minor GC就可以触发垃圾回收,一些常量池中的用不到的字符串对相关就可以垃圾回收,大大减轻了字符串对内存的占用

下面用例子证明一下StringTable串池的位置:我们把字符串放到集合中不让它回收

上面没有触发内存不足,是因为循环次数不足以触发,我们在1.6的情况下吧永久代的内存设置小一些,就会暴露内存不足的现象

报的是永久代内存溢出

切换到1.8环境下:设置最大参数

报这个GC overhead.... 这个是jvm垃圾回收的规则是由虚拟机参数控制的:

有个虚拟机参数

可以 关闭这个参数:

再次运行堆内存空间不足

通过以上就可以证明StringTable1.8用的是空间,1.6用的是永久代

(3)String_Table的垃圾回收

StringTable也会受到垃圾回收的管理的,当内存空间不足时StringTable中哪些没有被引用的字符串常量也会被垃圾回收

-Xmx10m:设置虚拟机堆内存的最大值

-XX:+:PrintStringStatistics打印字符串表的统计信息,通过它我们就可以看到串池中的字符串个数,及大小信息

-XX:+PrintGCDetails -verbose:gc 打印垃圾回收的信息把垃圾回收的次数啊时间啊显示出来

堆内存占用,垃圾回收信息

符号表:类的字节码里类名、方法名、变量名

StringTable的统计信息

StringTable的底层类似我们的HashTable的实现:数组+列表

数组的个数称为桶:

StringTable是以哈希表的方式存储数据的通的个数叫做buckets

存储的字符串对象:entries个数

字符串常量个数:literals

上面的代码我们什么都没有做,但是有数据,java程序在运行时类名,方法名,这些数据也是以字符串常量的形式表示的他们也存在串池中已经有那么多字符串对象了

我们写入代码:加入串池,观看前后串池的字符串常量个数变化

变为1854 ,此时没有触发垃圾回收,我们可以进行修改加入串池的个数

修改为存入串池为10000个:当10兆的堆内存可能存不下,会触发垃圾回收,我们可以看到存入串池的字符串个数,并没有全部存入7226

为什么只存入七千多呢,因为触发了垃圾回收

通过以上案例我们可以得出StringTable也是可以发生垃圾回收的

相关推荐
晨小安4 小时前
ThreadLocal及其内存泄漏问题深度解析
java·jvm·tomcat·哈希表
jingli910 小时前
一个测试用例把连接池卡死 30 秒:SQLite 连接池 max_size=1 下的重入自锁复盘
jvm·sqlite·测试用例
imDwAaY1 天前
Java中垃圾回收器 G1 和 CMS 有什么区别?
jvm·后端
xiaoqiMikko1 天前
JVM 线上排查实战(五):升 JDK 17 后进程起不来,十几个老 GC 参数挨个实测(完结)
java·jvm
Flynt1 天前
Java 27 悄悄改了 3 个默认值,我在 1 核小机器上逐个验证了一遍
java·jvm·性能优化
xiaoqiMikko1 天前
JVM 线上排查实战(三):grep BLOCKED 找不到的死锁,和 jstack 根本不报的死锁
java·jvm
此时不提桶,更待何时6 天前
01-06-A-JVM排查实战详解
java·jvm
wuminyu7 天前
HotSpot的轻量锁与膨胀后的ObjectMonitor状态重建原理
java·linux·c语言·jvm·c++
需要8267 天前
JVM 内存区域与对象创建:一次 GC 从哪来
java·jvm·spring boot·spring·servlet·tomcat
凤山老林7 天前
Spring Boot 应用 JVM 性能调优实战:GC 日志分析、堆内存规划与容器环境避坑
jvm·spring boot·gc·堆内存