欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

Java8新特性之字符串去重介绍

程序员文章站 2024-03-01 11:21:34
8月19日,oracle发布了jdk 8u20,jdk 8u20包含很多新特性,比如java编译器更新、支持在运行时通过api来修改minheapfreeratio和max...

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的字符数组。

(全文完)