JDK9对String字符串的新一轮优化

 更新时间:2021年03月16日 15:07:34   作者:程序新视界  
这篇文章主要介绍了JDK9对String字符串的新一轮优化,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下

String类可以说是Java编程中使用最多的类了,如果能对String字符串的性能进行优化,那么程序的性能必然能大幅提升。

这不JDK9就对String字符串进行了改进升级,在某些场景下可以让String字符串内存减少一半,进而减少JVM的GC次数。

String的底层存储

在面试的时候我们通常会说String字符串有不可变的特性,每次都要创建新的字符串。那么,为什么String字符串是不可变的呢?

先来看一下String字符串的底层存储结构:

public final class String
  implements java.io.Serializable, Comparable<String>, CharSequence {
  
  private final char value[];

  public String() {
    this.value = "".value;
  }

  public String(String original) {
    this.value = original.value;
    this.hash = original.hash;
  }
  // ...
}  

看到什么了?当我们new一个String对象时,对应的字符串其实是以char数组的形式存储在String对象内部。而这个char数组是final的,也就是说不可变的。

这也就是为什么我们说String字符串拥有不可变的特性,当字符串改变了,char数组不可变,就只能创建一个新的对象,新的char数组了。

底层存储的优化

上面说的情况是JDK8及以前版本,到了JDK9,String中字符串的存储不再用char数组了,改用byte数组。

public final class String
  implements java.io.Serializable, Comparable<String>, CharSequence {

  @Stable
  private final byte[] value;

  private final byte coder;
  
  @Native static final byte LATIN1 = 0;
  @Native static final byte UTF16 = 1;
  
  static final boolean COMPACT_STRINGS;
 
  public String() {
    this.value = "".value;
    this.coder = "".coder;
  }

  @HotSpotIntrinsicCandidate
  public String(String original) {
    this.value = original.value;
    this.coder = original.coder;
    this.hash = original.hash;
  }
  
  // ...
}

不仅将char数组改为byte数组,而且新增了一个coder的成员变量。

在程序中,绝大多数字符串只包含英文字母数字等字符,使用Latin-1编码,一个字符占用一个byte。如果使用char,一个char要占用两个byte,会占用双倍的内存空间。

但是,如果字符串中使用了中文等超出Latin-1表示范围的字符,使用Latin-1就没办法表示了。这时JDK会使用UTF-16编码,那么占用的空间和旧版(使用char[])是一样的。

coder变量代表编码的格式,目前String支持两种编码格式Latin-1和UTF-16。Latin-1需要用一个字节来存储,而UTF-16需要使用2个字节或者4个字节来存储。

据说这一改进方案是JDK的开发人员用大数据和人工能智能,调研了成千上万的应用程序的heapdump信息后,得出:大部分的String都是以Latin-1字符编码来表示的,只需要一个字节存储就够了,两个字节完全是浪费。

COMPACT_STRINGS属性则是用来控制是否开启String的compact功能。默认情况下是开启的。可以使用-XX:-CompactStrings参数来对此功能进行关闭。

改进的好处

改进的好处是非常明显的,首先如果项目中使用Latin-1字符集居多,内存的占用大幅度减少,同样的硬件配置可以支撑更多的业务。

当内存减少之后,进一步导致减少GC次数,进而减少Stop-The-World的频次,同样会提升系统的性能。

小结

随着JDK的迭代String字符串的内存结构及方法等也在不断地进行演变。这是因为String字符串往往是JVM中占用内存最多的类,通过对它的改造升级,对性能的提升会更加明显。

到此这篇关于JDK9对String字符串的新一轮优化的文章就介绍到这了,更多相关JDK9对String字符串优化内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • Java NIO深入分析

    Java NIO深入分析

    本篇技术文章主要对Java新api(New IO)做了详细深入的讲解,有助于程序对NIO有更加深入的理解。
    2017-12-12
  • 深入Spring Boot实现对Fat Jar jsp的支持

    深入Spring Boot实现对Fat Jar jsp的支持

    这篇文章主要介绍了深入Spring Boot实现对Fat Jar jsp的支持,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2018-06-06
  • Java简单计时的实现案例(可以用来限时循环)

    Java简单计时的实现案例(可以用来限时循环)

    这篇文章主要介绍了Java简单计时的实现案例(可以用来限时循环),具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2020-08-08
  • 关于Intellij IDEA中的Version Control问题

    关于Intellij IDEA中的Version Control问题

    这篇文章主要介绍了Intellij IDEA中的Version Control问题,本文通过图文并茂的形式给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2021-11-11
  • springboot无法从静态上下文中引用非静态变量的解决方法

    springboot无法从静态上下文中引用非静态变量的解决方法

    这篇文章主要介绍了springboot无法从静态上下文中引用非静态变量的解决方法,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
    2019-06-06
  • java基础知识I/O流使用详解

    java基础知识I/O流使用详解

    编程语言的I/O类库中常常使用流这个抽象的概念,它代表任何有能力产生数据的数据源对象或时有能力接收数据的接收端对象,本文为大家介绍Java中I/O系统基础知识
    2014-01-01
  • Java程序测试上传Maven工程代码示例解析

    Java程序测试上传Maven工程代码示例解析

    这篇文章主要介绍了Java程序测试上传Maven工程代码示例解析,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
    2020-08-08
  • 使用springmvc的controller层获取到请求的数据方式

    使用springmvc的controller层获取到请求的数据方式

    这篇文章主要介绍了使用springmvc的controller层获取到请求的数据方式,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2021-08-08
  • Java版数据结构插入数据时遇到的结点为空的问题详解

    Java版数据结构插入数据时遇到的结点为空的问题详解

    这篇文章主要介绍了Java版数据结构插入数据时遇到的结点为空的问题及解决办法,需要的朋友们可以学习下。
    2019-09-09
  • Java util.List如何实现列表分段处理

    Java util.List如何实现列表分段处理

    这篇文章主要介绍了Java util.List如何实现列表分段处理,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
    2020-09-09

最新评论