《JVM掘坟笔记之StringTable的垃圾回收证明》

1,103 阅读2分钟

挖掘JVM坟头背景

应目前就业形势的广大面试官造火箭的客观要求,各位掘友是否开始了新一轮的掘坟头学习?手快的大佬已经在此复习了。迷茫的你是否这样?

既然实战和面试JVM这座油斗肯定是要掘掉,那今天和大家一起简单研究一下StringTable的回收,在刚学的时候书中一般只说垃圾回收对象的比较多,到底StringTable串池里的内容GC有没有处理呢?

步入正题

油斗地宫的位置分布图如下:

大佬们是不是很兴奋!直接看到设计图的感觉就是爽
根据已知地宫条件,我们都知道1.6的内存结构已经成为JVM斗的历史了。那时的StringTable还在常量池中。现在在堆里了,惊不惊喜意不意外?和对象实例放一起了。。。现在流行的还是1.8,那么下面实例用1.8去演示。

生死看淡不服就干

正所谓工欲善其事,必先利其器。打开idea来一个测试演示:

1.配置jvm参数

-Xmx10m 设置虚拟机堆内存最大值 -XX:+PrintStringTableStatistics 打印串表的统计信息 以下是打印垃圾回收内容 : -XX+PrintGCDetails
-verbose:gc

2.随便找个坑

 public static void main(String[] args) {
        int i=0;
        try{}
        catch (Throwable e)
        {
            e.printStackTrace();
        }finally {
            System.out.println(i);
        }
    }

日志打印如下,这直接就把地宫看全了。。。。

就这点操作内容就出来了,虽然没有垃圾回收的日志(10m可以存下,所以没有回收)。但是果然牛逼。

3.继续深入

莫名其妙开车了,额...

我们都知道(也许吧),串池的底层实现是hashTable,也就是数组加链表 上图看到的总占用空间是679976 (等等1759那不是什么雪藏的雪碧?)
好的吧,那么原始的空间就看到了。那么咱们加点东西,来吧兄弟。

修改下内容

public static void main(String[] args) {
        int i=0;
        try{
            for(int j=0;j<10000;j++)
            {
                String.valueOf(j).intern();
                i++;
            }
        }
        catch (Throwable e)
        {
            e.printStackTrace();
        }finally {
            System.out.println(i);
        }
    }

intern是把堆中对象数据放入到串池中,修改后运行如下

可以看到1759个键值明显提升到8931,679976直奔1196800,GC日支出现。

[GC (Allocation Failure) [PSYoungGen: 2048K->504K(2560K)] 2048K->664K(9728K), 0.0007770 secs] [Times: user=0.00 sys=0.00, real=0.00 secs] 

那么为什么entries没有达到1万多个呢?就是因为GC已经把之前没用的内容回收了。在之前是没有GClog的哦,很明显GC是会处理串池里的数据的。

那就先到这了,谢谢大佬的点赞!!!