Java 8新特性:字符串去重

本文首发与InfoQ

8月19日,Oracle发布了JDK 8u20,JDK 8u20包含很多新特性,比如Java编译器更新、支持在运行时通过API来修改MinHeapFreeRatio和MaxHeapFreeRatio参数、新的GC调优指南文档。不过在众多新特性中,最令人期待的还属字符串去重(String Deduplication )。如何减少内存占用一直是一个永恒的话题,而在Java应用中,经常会看到String对象会占用应用30%的内存,它是Java中最常用的对象之一。新的字符串去重特性可以帮助减少应用中String对象的内存占用,目前该特性只适用于G1垃圾收集器,并且默认不被开启。

Fabian Lange解释了字符串去重特性的实现方式:

垃圾收集器会在访问String对象时对其字符数组进行标记,并将String的哈希值以及弱引用保存到一个数组中。当垃圾收集器发现另一个具有相同哈希值的String对象时,它就会逐字符比对这两个对象。如果他们完全匹配,那其中一个String就会被修改指向到另一个String的字符数组。由于第一个字符数组已经不再被引用,所以它也就可以被回收了。垃圾收集器会尽量减少整个操作的开销,比如某个String对象扫描未发现有重复,那接下来的一段时间内它不会再被检查。

紧接着,Fabian 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的日志也可以详细了解整个去重过程的详细信息。请读者自行测试。

最后,Fabian Lange还解释了字符串去重与字符串驻留的区别,它们很相似,除了字符串驻留重用了整个的String实例,而字符串去重只是针对String的字符数组。 

时间: 2024-11-08 19:04:06

Java 8新特性:字符串去重的相关文章

深入理解JVM内幕:从基本结构到Java 7新特性

转自:http://www.csdn.net/article/2012-12-05/2812509-Java-JVM CSDN首页>软件研发 深入理解JVM内幕:从基本结构到Java 7新特性 发表于2012-12-05 09:02|6064次阅读| 来源ImportNew|38 条评论| 作者 朱伟杰 JavaJVM编程语言 摘要:许多没有深入理解JVM的开发者也开发出了很多非常好的应用和类库.不过,如果你更加理解JVM的话,你就会更加理解Java,这样你会有助于你处理类似于我们前面的案例中的

Java 8新特性之旅:使用Stream API处理集合

在这篇"Java 8新特性教程"系列文章中,我们会深入解释,并通过代码来展示,如何通过流来遍历集合,如何从集合和数组来创建流,以及怎么聚合流的值. 在之前的文章"遍历.过滤.处理集合及使用Lambda表达式增强方法"中,我已经深入解释并演示了通过lambda表达式和方法引用来遍历集合,使用predicate接口来过滤集合,实现接口的默认方法,最后还演示了接口静态方法的实现. 源代码都在我的Github上:可以从 这里克隆. 内容列表 使用流来遍历集合. 从集合或数组

Java 8 新特性终极版指南详解_java

前言: Java 8已经公布有一段时间了,种种迹象表明Java 8是一个有重大改变的发行版.在Java Code Geeks上已经有很多介绍Java 8新特性的文章,例如Playing with Java 8 – Lambdas and Concurrency.Java 8 Date Time API Tutorial : LocalDateTime和Abstract Class Versus Interface in the JDK 8 Era.本文还参考了一些其他资料,例如:15 Must

Java 8新特性 内建函数式接口详解_java

Java 8新特性内建函数式接口 在之前的一片博文 Lambda 表达式,提到过Java 8提供的函数式接口.在此文中,将介绍一下Java 8四个最基本的函数式接口 对于方法的引用,严格来讲都需要定义一个接口.不管我们如何操作实际上有可能操作的接口只有四种. Java 8 提供了函数式接口包java.util.function.*,在该包下有许多Java 8内建的函数式接口.不过基本上分为四种基本的: 功能型接口 (Function) 将 T 作为输入,返回 R 作为输出,他还包含了和其他函数组

Java 8新特性方法引用详细介绍_java

Java 8新特性方法引用 对于引用来说我们一般都是用在对象,而对象引用的特点是:不同的引用对象可以操作同一块内容! Java 8的方法引用定义了四种格式: 引用静态方法     ClassName :: staticMethodName 引用对象方法:  Object:: methodName 引用特定类型方法: ClassName :: methodName 引用构造方法: ClassName  :: new  静态方法引用示例 /** * 静态方法引用 * @param <P> 引用方法

Java 8 新特性

这篇文章是一篇介绍Java8新特性英文博客的中文翻译,Java8发布有些时日,但是大家对它的了解和认识还不够,大部分企业和用户还停留在之前的版本中,本次翻译主要针对对Java8感兴趣和致力于从事Java开发的人员提供有价值的中文资料,希望能够对大家的工作和学习有所帮助.Java8的中文资料相对匮乏,这是我看过介绍Java8新特性最好的一篇文章,作者通过实例和理论相结合的方式,通俗易懂的阐述了Java8的一些新特性,今天让小村长为你揭开Java8的神秘面纱,一同走进码农的精神世界.注释 : 由于本

IBM Java 7 新特性和在 WAS 8.5 中的配置

什么是 Java 7--- 高层面的目标? 几乎所有平台的 Java 版本的发布,都涉及到 Java 语言本身 和 JVM 的各个方面.那么对于 Java 7 来说,从 JSR 草稿中,我们得到 Java 7 的高层次的目标是: 兼容性 ― 任何在以前版本上运行的程序必须能不用做任何改变就能在 Java SE 7 中运行: 开发效率 ― 提升开发效率,最小的学习曲线: 性能 ― 新的并行 API 接口,引入了一种真正的异步 I/O API,使得 I/O 密集型的应用程序有更好的性 能: 适用性

十大出人意料的Java 8新特性

Lambdas表达式,lambdas表达式,依然是lambdas表达式,这也许是你听的最多的关于Java 8的讨论了吧.但是lambdas表达式仅仅是Java 8的一小部分,Java 8还有许多新的特性--新特性包含一些功能强大的类及其高级用法,另外一些则是早就应该在Java中的功能. 我整理了10大Java 8中我认为最值得学习的新特性,总有一样你会遇到并喜欢上它,一起来看看吧. 1.默认方法(default方法) 这是Java语言的一个新特性,我们可以在接口类中加入具体的方法体了(也叫做de

可变参数列表-Java SE5新特性(转)

Java1.5增加了新特性:可变参数:适用于参数个数不确定,类型确定的情况,java把可变参数当做数组处理.注意:可变参数必须位于最后一项.当可变参数个数多于一个时,必将有一个不是最后一项,所以只支持有一个可变参数.因为参数个数不定,所以当其后边还有相同类型参数时,java无法区分传入的参数属于前一个可变参数还是后边的参数,所以只能让可变参数位于最后一项. 可变参数的特点:(1)只能出现在参数列表的最后: (2)...位于变量类型和变量名之间,前后有无空格都可以:(3)调用可变参数的方法时,编译