G1中的String去重操作
-
背景:对许多Java应用(有大的也有小的)做的测试得出以下结果:
-
堆存活数据集合里面string对象占了25号
-
堆存活数据集合里面重复的String对象有13.5号
-
String对象的平均长度是45
-
许多大规模的Java应用的瓶颈在于内存,测试表明,在这些类型的应用里面,Java堆中存活的数据集合差不多258是String对象。更进一步,这里面差不多一半string对象是重复的,重复的意思是说:
string1. equals (string2)=true。堆上存在重复的String对象必然是一种内存的浪费。这个项目将在G1垃圾收集器中实现自动持续对重复的String对象进行去重,这样就能避免浪费内存。
-
实现
- 当垃圾收集器工作的时候,会访问堆上存活的对象。对每一个访问的对象都会检查是否是候选的要去重的string对象。
- 如果是,把这个对象的一个引用插入到队列中等待后续的处理。一个去重的线程在后台运行,处理这个队列。处理队列的一-个元素意味着从队列删除这个元素,然后尝试去重它引用的String对象。
- 使用一个hashtable来 记录所有的被String对象使用的不重复的char数组。当去重的时候,会查这个hashtable,来看堆上是否已经存在一个一模一样的char数组。
- 如果存在,String对象会被调整引用那个数组,释放对原来的数组的引用,最终会被垃圾收集器回收掉。
- 如果查找失败,char数组会被插入到hashtable, 这样以后的时候就可以共享这个数组了
-
命令行选项
- UseStringDeduplication (bool) :开启String去重,默认是不开启的,需要手动开启。
- PrintStringDedupl icationStatistics (bool) :打印详细的去重统计信息
- StringDedupl icationAgeThreshold (uintx) :达到这个年龄的String对象被认为是去重的候选对象