JDK 9 对字符串 String 的优化,挺有意思!
String类可以说是Java编程中使用最多的类了,如果能对String字符串的性能进行优化,那么程序的性能必然能大幅提升。
这不JDK9就对String字符串进行了改进升级,在某些场景下可以让String字符串内存减少一半,进而减少JVM的GC次数。
String的底层存储
在面试的时候我们通常会说String字符串有不可变的特性,每次都要创建新的字符串。那么,为什么String字符串是不可变的呢?
先来看一下String字符串的底层存储结构:
public final class Stringimplements 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 Stringimplements java.io.Serializable, Comparable<String>, CharSequence {@Stableprivate 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;}@HotSpotIntrinsicCandidatepublic 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中占用内存最多的一类数据,因此对它(String)的优化收益非常大。
JDK 9 对字符串 String 的优化,挺有意思!相关推荐
- python字符串最大长度_字符串String的最大长度
开篇三个问题 作为Java的程序员,不知道在Java代码中定义了多少个字符串,可是看看下面3个问题.你是否认真思考过?是否动手实践过? 1.Java中的字符串String的最大长度是多少? 2.Ecl ...
- java string 最大长度是多少_字符串String的最大长度
开篇三个问题 作为Java的程序员,不知道在Java代码中定义了多少个字符串,可是看看下面3个问题.你是否认真思考过?是否动手实践过? 1.Java中的字符串String的最大长度是多少? 2.Ecl ...
- Go 学习笔记(31)— 字符串 string、字符 rune、字节 byte、UTF-8 和 Unicode 区别以及获取字符串长度
1. 字符串 string 类型 Go 语言中字符串的内部实现使用 UTF-8 编码,通过 rune 类型,可以方便地对每个 UTF-8 字符进行访问.当然, Go 语言也支持按照传统的 ASCII ...
- jdk 1.8 字符串+_JDK 9/10/11:Java字符串上+ =的副作用
jdk 1.8 字符串+ 问题" 为什么`array [i ++%n] + = i +"在Java 8和Java 10中给出不同的结果? "已于本周初发布在StackOv ...
- java语言用数组接收字符_Java基础——数组应用之字符串String类
字符串String的使用 Java字符串就是Unicode字符序列,例如串"Java"就是4个Unicode字符J,a,v,a组成的. Java中没有内置的字符串类型,而是在标准J ...
- 一篇让你读懂java中的字符串(String)
目录 创建字符串 方式1 方式2 方式3 三种方式的内存图 方式1 方式2 方式3 总结 理解池的概念 回忆引用 字符串判断相等 判断字符串引用是否相等 代码1 代码2 代码3 代码4 总结 判断字符 ...
- case when 包含某个字符_Go: 字符串和转换优化
ℹ️ 本文基于Go1.14. 在Go中,将字节数组转换为字符串可能会涉及到内存分配以及转换后的字符串的副本.但是,仅将字节转换为字符串以满足代码约束(例如switch语句中的比较或作为map的key) ...
- golang数据结构初探之字符串string
字符串string string 是Go语言中的基础数据类型. 特性速览 声明 声明string变量非常简单,常见的方式有以下两种: 声明一个空字符串后再赋值 var s string s = &qu ...
- R语言unlist函数将复杂数据(list列表、dataframe、字符串String)对象处理成简单向量vector形式:将包含dataframe和字符串的向量列表转换为单个向量(删除数据名称)
R语言unlist函数将复杂数据(list列表.dataframe.字符串String)对象处理成简单向量vector形式:将包含dataframe和字符串的向量列表转换为单个向量(删除数据名称) 目 ...
最新文章
- ASP.NET 对类进行XML序列化和反序列化
- 数字图像处理--空间滤波器
- iOS之中国银联移动支付控件升级的问题
- 通知:逆天异常库 V1.0版本支持下载了~~
- 通用的电子商务商城后台管理界面模板——后台
- ubuntu桌面状态栏不见
- 访问yy直播页面点击播放无响应分析
- redis 通道 java_【java】netty4,服务端向客户端主动发消息怎么把channel存储到redis缓存中?...
- 网络笔记(24) 云中网络:自己拿地成本高,购买公寓更灵活
- php 鼠标 移动 手型,css各种手型集合(css禁止手型)
- 年过完了,收心吧!送给大家送一波前端新书!
- Shiro @RequiresPermissions注解是如何运转的?
- linux who命令详解,Linux who命令实例详解
- 阿里云MQTT_Password工具下载地址
- ODBC连接HANA DB
- SEO 词库完整指南 转
- Win10设置共享文件夹
- 手机app调起百度高德地图
- 如何开通小程序广告流量主
- 【MATLAB图像处理实用案例详解(3)】—— 基于阈值分割的车牌定位识别
热门文章
- @async 默认线程池_SpringBoot 线程池的使用
- 【Java从入门到头秃专栏 7】语法篇(六) :Lambda表达式(->) 方法引用(::) stream流
- CENTOS5下VSFTPD的设置
- Angular动态创建组件
- Shell字符串操作集合
- 1495: 蛇行矩阵
- 重新学习Ubuntu -- 截图软件的选择和安装
- 如何通过BBED找回删除数据
- MySQL replace into (insert into 的增强版)
- 在装有raid卡的服务器上安装Ubuntu