Java8新特性之字符串去重介绍
8月19日,oracle发布了jdk 8u20,jdk 8u20包含很多新特性,比如java编译器更新、支持在运行时通过api来修改minheapfreeratio和maxheapfreeratio参数、新的gc调优指南文档。不过在众多新特性中,最令人期待的还属字符串去重(string deduplication )。如何减少内存占用一直是一个永恒的话题,而在java应用中,经常会看到string对象会占用应用30%的内存,它是java中最常用的对象之一。新的字符串去重特性可以帮助减少应用中string对象的内存占用,目前该特性只适用于g1垃圾收集器,并且默认不被开启。
f* lange解释了字符串去重特性的实现方式:
垃圾收集器会在访问string对象时对其字符数组进行标记,并将string的哈希值以及弱引用保存到一个数组中。当垃圾收集器发现另一个具有相同哈希值的string对象时,它就会逐字符比对这两个对象。如果他们完全匹配,那其中一个string就会被修改指向到另一个string的字符数组。由于第一个字符数组已经不再被引用,所以它也就可以被回收了。垃圾收集器会尽量减少整个操作的开销,比如某个string对象扫描未发现有重复,那接下来的一段时间内它不会再被检查。
紧接着,f* lange通过代码的方式解释了字符串去重特性的神奇效果。首先使用java 8 update 20通过参数-xmx256m -xx:+useg1gc运行以下代码:
public class lotsofstrings {
private static final linkedlist<string> lots_of_strings = new linkedlist<>();
public static void main(string[] args) throws exception {
int iteration = 0;
while (true) {
for (int i = 0; i < 100; i++) {
for (int j = 0; j < 1000; j++) {
lots_of_strings.add(new string("string " + j));
}
}
iteration++;
system.out.println("survived iteration: " + iteration);
thread.sleep(100);
}
}
}
代码会在30次循环之后因outofmemoryerror异常而结束运行。在使用参数 -xx:+usestringdeduplication -xx:+printstringdeduplicationstatistics开启字符串去重特性后,程序可以多运行一段时间。通过jvm的日志也可以详细了解整个去重过程的详细信息。请读者自行测试。
最后,f* lange还解释了字符串去重与字符串驻留的区别,它们很相似,除了字符串驻留重用了整个的string实例,而字符串去重只是针对string的字符数组。
(全文完)
下一篇: 将MySQL的临时目录建立在内存中的教程