StringTable垃圾回收跟踪案例

简介: StringTable垃圾回收跟踪案例

引言

很多人认为jvm字符串常量不会被回收的,其实这个说法的有误区的,我们通过一些jvm参数可以看到StringTable的垃圾回收。

案例说明

参数说明

参数 说明
-Xmx10m 堆空间大小
-XX+PrintStringTableStatistics 打印串池统计信息
-XX:+PrintGCDetails 打印GC日志详情
-verbose:gc 打印GC日志

先来一段空程序,我们使用参数运行:

-Xmx10m -XX+PrintStringTableStatistics -XX:+PrintGCDetails -verbose:gc
 public static void main(String[] args) {
        int i=0;
        try {
        }catch (Throwable e){
            e.printStackTrace();
        }finally {
            System.out.println(i);
        }
    }

结果如下:

0
Heap
 PSYoungGen      total 2560K, used 1388K [0x00000007bfd00000, 0x00000007c0000000, 0x00000007c0000000)
  eden space 2048K, 67% used [0x00000007bfd00000,0x00000007bfe5b100,0x00000007bff00000)
  from space 512K, 0% used [0x00000007bff80000,0x00000007bff80000,0x00000007c0000000)
  to   space 512K, 0% used [0x00000007bff00000,0x00000007bff00000,0x00000007bff80000)
 ParOldGen       total 7168K, used 0K [0x00000007bf600000, 0x00000007bfd00000, 0x00000007bfd00000)
  object space 7168K, 0% used [0x00000007bf600000,0x00000007bf600000,0x00000007bfd00000)
 Metaspace       used 2927K, capacity 4496K, committed 4864K, reserved 1056768K
  class space    used 319K, capacity 388K, committed 512K, reserved 1048576K
SymbolTable statistics:
Number of buckets       :     20011 =    160088 bytes, avg   8.000
Number of entries       :     11756 =    282144 bytes, avg  24.000
Number of literals      :     11756 =    455312 bytes, avg  38.730
Total footprint         :           =    897544 bytes
Average bucket size     :     0.587
Variance of bucket size :     0.587
Std. dev. of bucket size:     0.766
Maximum bucket size     :         6
StringTable statistics:
Number of buckets       :     60013 =    480104 bytes, avg   8.000
Number of entries       :       831 =     19944 bytes, avg  24.000
Number of literals      :       831 =     56304 bytes, avg  67.755
Total footprint         :           =    556352 bytes
Average bucket size     :     0.014
Variance of bucket size :     0.014
Std. dev. of bucket size:     0.118
Maximum bucket size     :         2

我们看到程序输出了堆信息,以及串池统计信息,需要了解的是我们的串池实现其实是类似Map的存储结构,里面的存储结构是数组的方式,每一个bucket就是一个数组结构。

Number of buckets       :     60013 =    480104 bytes, avg   8.000
Number of entries       :       831 =     19944 bytes, avg  24.000
Number of literals      :       831 =     56304 bytes, avg  67.755

代表了里面存储的字符串个数。

我们假设如下,如果不存在gc,我们写入10万个字符,那么Number of entries 会增加到10万。我们调整程序如下:

  int i=0;
        try {
           for(int j=0;j<100000;j++){
               String.valueOf(j).intern();
               i++;
           }
        }catch (Throwable e){
            e.printStackTrace();
        }finally {
            System.out.println(i);
        }

运行查看结果:

[GC (Allocation Failure) [PSYoungGen: 2048K->496K(2560K)] 2048K->504K(9728K), 0.0015310 secs] [Times: user=0.00 sys=0.00, real=0.00 secs] 
[GC (Allocation Failure) [PSYoungGen: 2544K->512K(2560K)] 2552K->528K(9728K), 0.0010023 secs] [Times: user=0.01 sys=0.00, real=0.00 secs] 
[GC (Allocation Failure) [PSYoungGen: 2560K->480K(2560K)] 2576K->520K(9728K), 0.0013527 secs] [Times: user=0.01 sys=0.00, real=0.00 secs] 
100000
Heap
 PSYoungGen      total 2560K, used 1295K [0x00000007bfd00000, 0x00000007c0000000, 0x00000007c0000000)
  eden space 2048K, 39% used [0x00000007bfd00000,0x00000007bfdcbc60,0x00000007bff00000)
  from space 512K, 93% used [0x00000007bff00000,0x00000007bff78020,0x00000007bff80000)
  to   space 512K, 0% used [0x00000007bff80000,0x00000007bff80000,0x00000007c0000000)
 ParOldGen       total 7168K, used 40K [0x00000007bf600000, 0x00000007bfd00000, 0x00000007bfd00000)
  object space 7168K, 0% used [0x00000007bf600000,0x00000007bf60a000,0x00000007bfd00000)
 Metaspace       used 3095K, capacity 4496K, committed 4864K, reserved 1056768K
  class space    used 339K, capacity 388K, committed 512K, reserved 1048576K
SymbolTable statistics:
Number of buckets       :     20011 =    160088 bytes, avg   8.000
Number of entries       :     12129 =    291096 bytes, avg  24.000
Number of literals      :     12129 =    467440 bytes, avg  38.539
Total footprint         :           =    918624 bytes
Average bucket size     :     0.606
Variance of bucket size :     0.606
Std. dev. of bucket size:     0.778
Maximum bucket size     :         6
StringTable statistics:
Number of buckets       :     60013 =    480104 bytes, avg   8.000
Number of entries       :     15285 =    366840 bytes, avg  24.000
Number of literals      :     15285 =    866120 bytes, avg  56.665
Total footprint         :           =   1713064 bytes
Average bucket size     :     0.255
Variance of bucket size :     0.267
Std. dev. of bucket size:     0.516
Maximum bucket size     :         4

我们发现日志显示发生了三次Yong gc,Number of entries 是15285,没有达到10万,说明了我们的串池是会发生GC的。

目录
相关文章
JVM08_字符串常量池基本特性、内存分配、拼接操作、intern、StringTable垃圾回收(三)
⑤. intern()的使用 ①. new String("ab")会创建几个对象 ②. new String("a") + new String("b")创建几个对象呢? ③. 关于String.intern( )的面试题 ④. 总结String的intern()的使用
153 0
JVM08_字符串常量池基本特性、内存分配、拼接操作、intern、StringTable垃圾回收(三)
|
2月前
|
算法 Java
JVM GC和常见垃圾回收算法
JVM GC和常见垃圾回收算法
62 0
|
2月前
|
Java Go
Golang底层原理剖析之垃圾回收GC(二)
Golang底层原理剖析之垃圾回收GC(二)
64 0
|
2月前
|
存储 监控 算法
垃圾回收器、垃圾回收算法、空间分配担保、JVM调优、GC回收对象的过程
垃圾回收器、垃圾回收算法、空间分配担保、JVM调优、GC回收对象的过程
|
11天前
|
监控 算法 Java
JVM之GC算法的实现(垃圾回收器)
JVM之GC算法的实现(垃圾回收器)
|
13天前
|
算法 Java
垃圾回收机制(Garbage Collection,GC)是Java语言的一个重要特性,它自动管理程序运行过程中不再使用的内存空间。
【6月更文挑战第24天】Java的GC自动回收不再使用的内存,关注堆中的对象。通过标记-清除、复制、压缩和分代等算法识别无用对象。GC分为Minor、Major和Full类型,针对年轻代、老年代或整个堆进行回收。性能优化涉及算法选择和参数调整。
22 3
|
19天前
|
算法 Java
Java垃圾回收(Garbage Collection,GC)是Java虚拟机(JVM)的一种自动内存管理机制,用于在运行时自动回收不再使用的对象所占的内存空间
【6月更文挑战第18天】Java的GC自动回收内存,包括标记清除(产生碎片)、复制(效率低)、标记整理(兼顾连续性与效率)和分代收集(区分新生代和老年代,用不同算法优化)等策略。现代JVM通常采用分代收集,以平衡性能和内存利用率。
41 3