![]()
下面呢我们来研究一下StringTable 的位置。
之前前面的章节其实已经给大家介绍过,我们这个string table 它在我们jvm内存结构中所处的一个位置。
但是它是跟版本有关的,
在jvm 1.6的时候,StringTable它是常量池的一部分,它就随着常量池存储在我们这个永久代中。
从jvm 1.7开始,它把StringTable转移到了堆中,jvm1.7/1.8 它就把这个StringTable从永久代变到了堆里面。
为什么要做这个更改呢?
就是因为永久代的内存回收效率很低。
永久代它是需要full gc的时候才会触发它的永久代的垃圾回收,但是我们full gc啊,它是等到整个老年代的空间不足时才会触发,这个触发的时机有点晚,就间接的导致StringTable,它的回收效率并不高。
其实StringTable它使用的非常的频繁,它里面不都是存的字符串常量吗?
我们一个java 应用程序中,大量的字符串常量对象都会分配到StringTable里,那如果它的这个回收效率不高,就会占用大量的内存,进而会导致容易产生永久代的内存不足。
所以基于这样一些缺点,从jvm1.7开始,那么jvm的工程师就把StringTable转移到了堆里。在堆里面的StringTable,它只需要Minor GC就会触发了StringTable的垃圾回收,把一些常量池中的用不到的一些字符串常量对象也可以回收,这样就大大减轻了我们这个内存的字符串对内存的一个占用。
所以这是一个从jvm1.6到jvm1.7/1.8的一个优化。
那有些同学说了,你光这么说,那怎么证明从jvm1.8,StringTable的位置跟jvm1.6的位置不一样呢?
好,那么这里准备这样一个案例。
我们不断的往StringTable里,存放大量的字符串对象,并且用一个长时间存活的对象来引用这些字符串对象,那势必是不是就造成他们的内存空间不足?
那如果是在jvm1.6的环境下,去运行这个案例。那大家想它内存空间不足,一定是触发永久代的内存空间不足。
但是说如果是你这个在jvm1.7或者jvm1.8这个环境下。去做同样的案例实验,它触发的内存不足肯定会报一个堆空间的内存不足。
所以我们就从这个角度,去看看它到底最终出现这个内存溢出错误现象的不同,来间接的观测StringTable 它存在的一个位置。
这个分析我们就先分析到这。
好,这一篇就讲到这里。
上一篇:34.jvm内存结构部分——String_table面试题[通过jvm来做题]_tgbyhn31的博客-CSDN博客
下一篇:暂无
