引言

很多人认为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的。

StringTable---字符串常量池的垃圾回收跟踪案例的更多相关文章

  1. JVM字符串常量池StringTable

    String的基本特性 String:字符串,使用一对""引起来表示. String sl = "hello"://字面量的定义方式: String s2 = ...

  2. 8.StringTable(字符串常量池)

    一.String的基本特性 String:字符串,使用一对 "" 引起来表示 String s1 = "atguigu" ; // 字面量的定义方式 Strin ...

  3. 从HotSpot VM源码看字符串常量池(StringTable)和intern()方法

    引言 字符串常量池(StringTable)是JVM中一个重要的结构,它有助于避免重复创建相同内容的String对象.那么StringTable是怎么实现的?"把字符串加入到字符串常量池中& ...

  4. Java String:字符串常量池(转)

    作为最基础的引用数据类型,Java 设计者为 String 提供了字符串常量池以提高其性能,那么字符串常量池的具体原理是什么? 字符串常量池的设计思想是什么? 字符串常量池在哪里? 如何操作字符串常量 ...

  5. String:字符串常量池

    String:字符串常量池 作为最基础的引用数据类型,Java 设计者为 String 提供了字符串常量池以提高其性能,那么字符串常量池的具体原理是什么,我们带着以下三个问题,去理解字符串常量池: 字 ...

  6. 对于JVM中方法区,永久代,元空间以及字符串常量池的迁移和string.intern方法

    在Java虚拟机(以下简称JVM)中,类包含其对应的元数据,比如类的层级信息,方法数据和方法信息(如字节码,栈和变量大小),运行时常量池,已确定的符号引用和虚方法表. 在过去(当自定义类加载器使用不普 ...

  7. Knowledge Point 20180309 字符串常量池与String,intern()

    引言 什么都先不说,先看下面这个引入的例子: public static void test4(){ String str1 = new String("SEU") + new S ...

  8. 深入探究JVM之内存结构及字符串常量池

    前言 Java作为一种平台无关性的语言,其主要依靠于Java虚拟机--JVM,我们写好的代码会被编译成class文件,再由JVM进行加载.解析.执行,而JVM有统一的规范,所以我们不需要像C++那样需 ...

  9. Class常量池、运行时常量池、字符串常量池的一些思考

    Class常量池.运行时常量池.字符串常量池 class常量池 java代码经过编译之后都成了xxx.class文件,这是java引以为傲的可移植性的基石.class文件中,在CAFEBABE.主次版 ...

随机推荐

  1. 文档驱动开发模式在 AIMS 中的应用与实践

    摘要:程序员常会说:我最讨厌别人写的代码没有文档,我也最讨厌自己需要写文档. 有一个很老的梗: 我最讨厌别人写的代码没有文档,我也最讨厌自己需要写文档. 有这种想法的程序员应该算是一个老鸟了,对于大多 ...

  2. 查找Command

    Find [路径] [匹配表达式] -name filename : 查找指定名称的文件 -user username: 查找属于指定用户的文件 -group grpname: 查找属于指定组的文件 ...

  3. 剑指offer 面试题5:替换空格

    题目描述 请实现一个函数,将一个字符串中的每个空格替换成"%20".例如,当字符串为We Are Happy. 则经过替换之后的字符串为We%20Are%20Happy. 编程思想 ...

  4. #2020征文-开发板# 用鸿蒙开发AI应用(五)HDF 驱动补光灯

    目录: 前言 硬件准备 HDF 驱动开发 总结 前言上一篇,我们在鸿蒙上运行了第一个程序,这一篇我们来编写一个驱动开启摄像头的红外补光灯,顺便熟悉一下鸿蒙上的 HDF 驱动开发. 硬件准备先查一下原理 ...

  5. oracle dataguard搭建

    搭建前环境准备 1.查看主库的oracle的uid和gid并在备库创建用户 # 主库查看oracle $ id oracle uid=54321(oracle) gid=54321(oinstall) ...

  6. web dynpro配置注意事项

    如果你想使用web dynpro 开发的应用,但是发现浏览器报错,那么你按照下面的步骤逐一进行检查吧.特别是返回的500错误,或者是你发现浏览器的地址栏中以http://<hostname> ...

  7. 定制个性化的GUI

    你现在还在使用SAP GUI710或者是GUI720,又或者更早的640等吗?那么古董先生,推荐您使用GUI730吧,您可能会730好在哪?那我建议您去百度或者Google问吧.对于新的GUI730, ...

  8. C# 关机/重启/注销计算机

    一.调用 shutdown.exe 执行操作 调用 shutdown.exe 执行计算机关机.重启.注销操作,还可以设置多长时间后执行操作,代码如下: 1 /// <summary> 2 ...

  9. spring boot项目问题汇总

    spring遇到的问题汇总 有关日志的打印和日志如何使用 在实际项目中,我们的程序都是运行在linux上,有错误时也不能在本地的控制台上直观看到,所有合理打印日志对于程序员迅速定位到错误. 打印日志时 ...

  10. pycharm2021永久激活

    Pycharm破解版地址: 链接: https://pan.baidu.com/s/1dEkzKRFMaeNjWF4h7y2TdQ 提取码: eqr3  Anaconda地址:版本是python3.6 ...