【JVM之内存与垃圾回收篇】StringTable (5)

练习:

【JVM之内存与垃圾回收篇】StringTable

在 JDK6 中,在字符串常量池中创建一个字符串 "ab"

在 JDK8 中,在字符串常量池中没有创建 "ab",而是将堆中的地址复制到 串池中。

所以上述结果,在 JDK6 中是:

true false

在JDK8中是

true true

【JVM之内存与垃圾回收篇】StringTable

针对下面这题,在 JDK6 和 8 中表现的是一样的

【JVM之内存与垃圾回收篇】StringTable

使用 intern() 优化执行效率:空间使用上
结论:对于程序中大量存在的字符串,尤其是其中存在很多重复字符串时,使用 intern() 可以节省内存空间。
大的网站平台,需要内存中存储大量的字符串。比如社交网站,很多人都存储:北京市、海淀区等信息。这时候如果字符串都调用 intern() 方法,就会明显降低内存的大小。

StringTable的垃圾回收 /** * String的垃圾回收 * -Xms15m -Xmx15m -XX:+PrintStringTableStatistics -XX:+PrintGCDetails * @author: Nemo */ public class StringGCTest { public static void main(String[] args) { for (int i = 0; i < 100000; i++) { String.valueOf(i).intern(); } } }

执行之后只有 60000 多个对象,因为进行了垃圾回收。

G1 中的 String 去重操作

官方说明:

注意这里说的重复,指的是在堆中的数据,而不是常量池中的,因为常量池中的本身就不会重复

String str1 = new String("hello");
String str2 = new String("hello");
是指这个堆中的对象去重

描述

背景:对许多 Java 应用(有大的也有小的)做的测试得出以下结果:

堆存活数据集合里面 string 对象占了 25%

堆存活数据集合里面重复的 string 对象有 13.5%

string 对象的平均长度是 45

许多大规模的 Java 应用的瓶颈在于内存,测试表明,在这些类型的应用里面,Java 堆中存活的数据集合差不多 25% 是 String 对象。更进一步,这里面差不多一半 String 对象是重复的,重复的意思是说:
stringl.equals(string2)= true。堆上存在重复的 string 对象必然是一种内存的浪费。这个项目将在 G1 垃圾收集器中实现自动持续对重复的 string 对象进行去重,这样就能避免浪费内存。

实现

当垃圾收集器工作的时候,会访问堆上存活的对象。对每一个访问的对象都会检查是否是候选的要去重的 string 对象。

如果是,把这个对象的一个引用插入到队列中等待后续的处理。一个去重的线程在后台运行,处理这个队列。处理队列的一个元素意味着从队列删除这个元素,然后尝试去重它引用的 string 对象。

使用一个 hashtable 来记录所有的被string 对象使用的不重复的 char 数组。当去重的时候,会查这个 hashtable,来看堆上是否已经存在一个一模一样的 char 数组。

如果存在,string 对象会被调整引用那个数组,释放对原来的数组的引用,最终会被垃圾收集器回收掉。

如果查找失败,char 数组会被插入到 hashtable,这样以后的时候就可以共享这个数组了。

开启

命令行选项

UseStringDeduplication(bool):开启 String 去重,默认是不开启的,需要手动开启。

PrintStringDeduplicationStatistics(bool):打印详细的去重统计信息

StringDeduplicationAgeThreshold(uintx):达到这个年龄的 String 对象被认为是去重的候选对象

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/zgjgfw.html