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)的优化收益非常大。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/544932.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

PHP将数组存入数据库中的四种方式

PHP将数组存入数据库中的四种方式 最近突然遇到了一个问题&#xff0c;如何用PHP将数组存入到数据库中&#xff0c;经过自己的多方查找和研究&#xff0c;总结了以下四种方法&#xff1a;1.implode()和explode()方式2.print_r()和自定义函数方式3.serialize()和unserialize()方…

c#中.clear()作用_清单 .Clear()方法以及C#中的示例

c#中.clear()作用C&#xff03;List <T> .Clear()方法 (C# List<T>.Clear() Method) List<T>.Clear() method is used to clear the list, it remove all elements from the list. List <T> .Clear()方法用于清除列表&#xff0c;它从列表中删除所有元…

Android开发:利用Activity的Dialog风格完成弹出框设计

转&#xff1a;http://www.linuxidc.com/Linux/2011-08/41933.htm 在我们使用Dialog时&#xff0c;如果需要用到很多自己设计的控件&#xff0c;虽然可以让弹出框显示出我们需要的界面&#xff0c;但却无法找到地方完成控制代码的编写&#xff0c;如何解决这个问题呢,我们可以将…

Java中实现定时任务的3种方法!

今天我们不用任何框架&#xff0c;用最朴素的 Java API 来实现定时任务&#xff0c;本文会介绍 3 种实现方案&#xff0c;我们一起来看...1、 sleep 这也是我们最常用的 sleep 休眠大法&#xff0c;不只是当作休眠用&#xff0c;我们还可以利用它很轻松的能实现一个简单的定时任…

回文子序列_计算回文子序列的总数

回文子序列Problem statement: 问题陈述&#xff1a; Given a string str, find total number of possible palindromic sub-sequences. A sub-sequence does not need to be consecutive, but for any xixj i<j must be valid in the parent string too. Like "icl&q…

【Microsoft Azure学习之旅】测试消息队列(Service Bus Queue)是否会丢消息

组里最近遇到一个问题&#xff0c;微软的Azure Service Bus Queue是否可靠&#xff1f;是否会出现丢失消息的情况&#xff1f; 具体缘由如下&#xff0c; 由于开发的产品是SaaS产品&#xff0c;为防止消息丢失&#xff0c;跨Module消息传递使用的是微软Azure消息队列&#xff0…

使用SharedPreferences存储和读取数据

转&#xff1a;http://www.worlduc.com/blog2012.aspx?bid19403392 1、任务目标 &#xff08;1&#xff09;掌握Android中SharedPreferences的使用方法。 2、任务陈述 &#xff08;1&#xff09;运行后&#xff0c;显示如下界面&#xff0c;可以写入和读取SharedPreferences中…

Zookeeper 的 5 大核心知识点!

1 ZooKeeper简介ZooKeeper 是一个开源的分布式协调框架&#xff0c;它的定位是为分布式应用提供一致性服务&#xff0c;是整个大数据体系的管理员。ZooKeeper 会封装好复杂易出错的关键服务&#xff0c;将高效、稳定、易用的服务提供给用户使用。如果上面的官方言语你不太理解&…

PHP | 计算字符串中的单词总数

Given a string and we have to count the total number of words in it. 给定一个字符串&#xff0c;我们必须计算其中的单词总数。 str_word_count() function str_word_count()函数 To find the total number of words in a string, we can use str_word_count() function…

parted分区介绍

简介: 当硬盘或raid后,硬盘大于2T的时候,可以使用parted进行分区; 使用parted的前提是操作系统已经安装部署完成; 大于2T的硬盘在安装部署阶段可以使用raid的虚拟磁盘技术分区,如分出100G安装系统,剩余的在安装系统后,使用parted进行分区; 1.parted非交互式分区: …

SharedPreferences详解

我们在开发软件的时候,常需要向用户提供软件参数设置功能,例如我们常用的微信,用户可以设置是否允许陌生人添加自己为好友.对于软件配置参数的保存,如果是在window下通常我们会采用ini文件进行保存.如果是J2EE下面,我们会采用properties属性文件或者xml进行保存.在我们的Androi…

【视频版】最新版Swagger 3升级指南和新功能体验!

作者 | 王磊来源 | Java中文社群&#xff08;ID&#xff1a;javacn666&#xff09;转载请联系授权&#xff08;微信ID&#xff1a;GG_Stone&#xff09;Swagger 3.0 发布已经有一段时间了&#xff0c;它于 2020.7 月 发布&#xff0c;但目前市面上使用的主流版本还是 Swagger 2…

java treemap_Java TreeMap pollFirstEntry()方法与示例

java treemapTreeMap类pollFirstEntry()方法 (TreeMap Class pollFirstEntry() method) pollFirstEntry() method is available in java.util package. pollFirstEntry()方法在java.util包中可用。 pollFirstEntry() method is used to return and then remove the entry (key-…

各大厂面试高频的面试题新鲜出炉,你能答上几道?

关于生产环境如何配置线程数&#xff0c;还是要根据业务来进行区分&#xff0c;我们时常会听到什么IO密集型、CPU密集型任务...那么这里提一个问题&#xff1a;大家知道什么样的任务或者代码会被认定为IO/CPU密集&#xff1f;又是用什么样的标准来认定IO/CPU密集&#xff1f;如…

c/c++如何获取数组的长度

2019独角兽企业重金招聘Python工程师标准>>> C、C中没有提供 直接获取数组长度的函数&#xff0c;对于存放字符串的字符数组提供了一个strlen函数获取长度&#xff0c;那么对于其他类型的数组如何获取他们的长度呢&#xff1f;其中一种方法是使 用sizeof(array) / s…

JSP JAVA 自定义 错误页面(404,505,500)

当网站页面找不到或者服务器内部出错的时候&#xff0c;我们不想让用户看到默认的那张 404&#xff0c;500 的错误页面&#xff0c;那要是想自己做一张 找不到页面的页面改怎么做呢&#xff1f;在 web .xml 文件中 加入下面的语句就能达到这个效果<error-page><error-…

【送给读者】全新苹果 AirPods,包邮送一套!

为回馈长期以来科创人读者对本栏目的关注支持&#xff0c;本周小编联合了计算机领域八位高质量原创号主一起为大家送出一套 全新苹果AirPods 2代。以下推荐的公号原创率都很高&#xff0c;均为个人IP号&#xff0c;有些小伙伴应该已经关注部分公号。本次抽奖采用第三方抽奖小程…

java 方法 示例_Java扫描仪的hasNextBoolean()方法与示例

java 方法 示例扫描器类的hasNextBoolean()方法 (Scanner Class hasNextBoolean() method) hasNextBoolean() method is available in java.util package. hasNextBoolean()方法在java.util包中可用。 hasNextBoolean() method is used to check whether this Scanners next in…

进程控制(kill)

为什么80%的码农都做不了架构师&#xff1f;>>> kill&#xff1a;终止进程&#xff08;或传送信号到某进程&#xff09; kill [options] [process_ids] kill命令可以发送信号给进程&#xff0c;可以终止&#xff08;terminate&#xff09;&#xff08;默认操作&a…

oracle怎样修改表名、列名、字段类型、添加表列、删除表列

ALTER TABLE SCOTT.TEST RENAME TO TEST1--修改表名 ALTER TABLE SCOTT.TEST RENAME COLUMN NAME TO NAME1 --修改表列名 ALTER TABLE SCOTT.TEST MODIFY NAME1 NUMBER(20) --修改字段类型 ALTER TABLE SCOTT.TEST ADD ADDRESS VARCHAR2(40) --添加表列 ALTER TABLE SCOTT.TEST…