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

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

(全文完)

(0)

相关推荐

  • Java8新特性lambda表达式有什么用(用法实例)

    我们期待了很久lambda为java带来闭包的概念,但是如果我们不在集合中使用它的话,就损失了很大价值.现有接口迁移成为lambda风格的问题已经通过default methods解决了,在这篇文章将深入解析Java集合里面的批量数据操作(bulk operation),解开lambda最强作用的神秘面纱. 1.关于JSR335 JSR是Java Specification Requests的缩写,意思是Java 规范请求,Java 8 版本的主要改进是 Lambda 项目(JSR 335),其

  • Java8新特性之再见Permgen_动力节点Java学院整理

    很多开发者都在其系统中见过"java.lang.OutOfMemoryError: PermGen space"这一问题.这往往是由类加载器相关的内存泄漏以及新类加载器的创建导致的,通常出现于代码热部署时.相对于正式产品,该问题在开发机上出现的频率更高,在产品中最常见的"问题"是默认值太低了.常用的解决方法是将其设置为256MB或更高. PermGen space简单介绍 PermGen space的全称是Permanent Generation space,是指内

  • Java8深入学习系列(三)你可能忽略了的新特性

    前言 我们之前已经介绍了关于java8中lambda和函数式编程的相关内容,虽然我们开始了Java8的旅程,但是很多人直接从java6上手了java8, 也许有一些JDK7的特性你还不知道,在本章节中带你回顾一下我们忘记了的那些特性. 尽管我们不能讲所有特性都讲一遍,挑出常用的核心特性拎出来一起学习. 异常改进 try-with-resources 这个特性是在JDK7种出现的,我们在之前操作一个流对象的时候大概是这样的: try { // 使用流对象 stream.read(); stream

  • Java8新特性之重复注解(repeating annotations)浅析

    一.什么是重复注解 允许在同一申明类型(类,属性,或方法)的多次使用同一个注解 二.一个简单的例子java 8之前也有重复使用注解的解决方案,但可读性不是很好,比如下面的代码: 复制代码 代码如下: public @interface Authority {     String role();} public @interface Authorities {    Authority[] value();} public class RepeatAnnotationUseOldVersion

  • Java8 新特性Lambda表达式实例详解

    Java8 新特性Lambda表达式实例详解 在介绍Lambda表达式之前,我们先来看只有单个方法的Interface(通常我们称之为回调接口): public interface OnClickListener { void onClick(View v); } 我们是这样使用它的: button.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { v.setText("

  • JAVA8 十大新特性详解

    "Java is still not dead-and people are starting to figure that out." 本教程将用带注释的简单代码来描述新特性,你将看不到大片吓人的文字. 一.接口的默认方法 Java 8允许我们给接口添加一个非抽象的方法实现,只需要使用 default关键字即可,这个特征又叫做扩展方法,示例如下: 复制代码 代码如下: interface Formula {    double calculate(int a); default do

  • Java8新特性之lambda的作用_动力节点Java学院整理

    我们期待了很久lambda为java带来闭包的概念,但是如果我们不在集合中使用它的话,就损失了很大价值.现有接口迁移成为lambda风格的问题已经通过default methods解决了,在这篇文章将深入解析Java集合里面的批量数据操作(bulk operation),解开lambda最强作用的神秘面纱. 1.关于JSR335 JSR是Java Specification Requests的缩写,意思是Java 规范请求,Java 8 版本的主要改进是 Lambda 项目(JSR 335),其

  • Java8新特性之默认方法(default)浅析

    一.什么是默认方法,为什么要有默认方法 简单说,就是接口可以有实现方法,而且不需要实现类去实现其方法.只需在方法名前面加个default关键字即可. 为什么要有这个特性?首先,之前的接口是个双刃剑,好处是面向抽象而不是面向具体编程,缺陷是,当需要修改接口时候,需要修改全部实现该接口的类,目前的java 8之前的集合框架没有foreach方法,通常能想到的解决办法是在JDK里给相关的接口添加新的方法及实现.然而,对于已经发布的版本,是没法在给接口添加新方法的同时不影响已有的实现.所以引进的默认方法

  • Java8新特性之Lambda表达式浅析

    说到java 8,首先会想到lambda(闭包)以及虚拟扩展方法(default method),这个特性早已经被各大技术网站炒得沸沸扬扬了,也是我们java 8系列开篇要讲的第一特性(JEP126 http://openjdk.java.net/jeps/126),jdk8的一些库已经应用了lambda表达式重新设计了,理解他对学习java 8新特性有着重要的意义. 一.函数式接口 函数式接口(functional interface 也叫功能性接口,其实是同一个东西).简单来说,函数式接口是

  • 详谈Java8新特性泛型的类型推导

    1. 泛型究竟是什么? 在讨论类型推导(type inference)之前,必须回顾一下什么是泛型(Generic).泛型是Java SE 1.5的新特性,泛型的本质是参数化类型,也就是说所操作的数据类型被指定为一个参数.通俗点将就是"类型的变量".这种类型变量可以用在类.接口和方法的创建中.理解Java泛型最简单的方法是把它看成一种便捷语法,能节省你某些Java类型转换(casting)上的操作: List<Apple> box = new ArrayList<Ap

随机推荐