String类的底层原理和版本演变
1 String类的底层演变
(1) JDK8以及之前版本

(2)JDK9以及之后版本

```java
JDK8的字符串存储在char类型的数组里面,在java中,一个char类型占两个字节。但是很多时候,一个字符只需要一个字节就可存储,比如各种字母什么的,两个字节存储势必会浪费空间,JDK9的一个优化就在这,内存的优化,所以JDK9之后字符串改成byte类型数组进行存储。
private final byte coder;
在JDK9的String类中,新增了一个属性coder,它是一个编码格式的标识,使用LATIN1还是UTF16,这个是在String生成的时候自动确定的,如果字符串中都是能用LATIN1编码表示,那coder的值就是0,否则就是UTF16编码,coder的值就是1。
可以看到JDK9在这方面的优化,在较多情况下不包含那些奇奇怪怪的字符的时候,足以应付,而这个空间却小了1byte,实现了String空间的压缩。
2 String常量池的演变
2.1 StringTable变化
String 的 StringPool是一个固定大小的 Hashtable。在jdk6中,StringTable的长度固定为1009。如果放进 StringPool的String非常多,就会造成Hash冲突严重,从而导致链表会很长,而链表长了后直接会造成的影响就是当调用 intern() 时性能会大幅下降。从jdk7起,StringTable的长度默认值是60013。使用-XX:StringTableSize可设置StringTable的长度。 在jdk8之前,对StringTableSize的设置没有最小限制。jdk8开始,StringTable可设置的最小值是1009。验证:通过 jps 命令查看进程号使用 jinfo -flag StringTableSize 进程号 查看StringTable大小
```
2.2 内存位置变化
Java6及以前,字符串常量池存放在永久代。Java7开始,字符串常量池的位置调整到Java堆内。
所有的字符串都保存在堆(Heap)中,和其他普通对象一样,这样在进行调优应用时仅需要调整堆大小就可以了。
```
官网说明
https://www.oracle.com/technetwork/java/javase/jdk7-relnotes-418459.html#jdk7changes
JDK6环境下测试:
/*jdk6中,修改JVM内存大小:-XX:PermSize=6m -XX:MaxPermSize=6m -Xms6m -Xmx6m*/publicclassStringTableTest{publicstaticvoidmain(String[] args){Set<String> set =newHashSet<String>();int i=0;while(true){set.add(String.valueOf(i++).intern());}}}执行结果异常信息:Exception in thread "main" java.lang.OutOfMemoryError:PermGen spaceat java.lang.String.intern(NativeMethod)
```
JDK7环境下测试:
/*jdk7中,修改JVM内存大小:-XX:PermSize=6m -XX:MaxPermSize=6m -Xms6m -Xmx6m -XX:-UseGCOverheadLimit*/publicclassStringTableTest{publicstaticvoidmain(String[] args){Set<String> set =newHashSet<String>();int i=0;while(true){set.add(String.valueOf(i++).intern());}}}执行结果异常信息:Exception in thread "main" java.lang.OutOfMemoryError:Java heap spaceat java.lang.Integer.toString(Integer.java:331)at java.lang.String.valueOf(String.java:2954)at StringTableTest.main(StringTableTest.java:14)
```
3 String的拼接原理
3.1 拼接原理
源代码:
publicstaticvoidmain(String[] args){String s1 ="hello";String s2 ="world";String s3 = s1+s2;System.out.println(s3);}```
使用 JDK8 编译后字节码:
0 ldc #2<hello>2 astore_13 ldc #3<world>5 astore_26new #4<java/lang/StringBuilder>9 dup
10 invokespecial #5<java/lang/StringBuilder.<init>>13 aload_1
14 invokevirtual #6<java/lang/StringBuilder.append>17 aload_2
18 invokevirtual #6<java/lang/StringBuilder.append>21 invokevirtual #7<java/lang/StringBuilder.toString>24 astore_3
25 getstatic #8<java/lang/System.out>28 aload_3
29 invokevirtual #9<java/io/PrintStream.println>32return
```
使用 JDK9 编译后字节码:
0 ldc #2<hello>2 astore_13 ldc #3<world>5 astore_26 aload_17 aload_28 invokedynamic #4<makeConcatWithConstants,BootstrapMethods #0>13 astore_3
14 getstatic #5<java/lang/System.out>17 aload_3
18 invokevirtual #6<java/io/PrintStream.println>21return
```
结论:
```java
JDK8及之前,字符串变量的拼接,底层使用的是StringBuilder对象,利用append方法进行拼接。
(注:jdk1.4之前使用StringBuffer)
JDK9以后的编译器已经改成使用动态指令invokedynamic,
调用StringConcatFactory.makeConcatWithConstants方法进行字符串拼接优化。
```
3.2 核心方法
makeConcatWithConstants方法在StringConcatFactory类中定义。makeConcatWithConstants内部调用了doStringConcat,而doStringConcat方法则调用了generate方法来生成MethodHandle;generate根据不同的STRATEGY来生成MethodHandle,这些STRATEGY(策略)有BC_SB(等价于JDK8的优化方式)BC_SB_SIZEDBC_SB_SIZED_EXACTMH_SB_SIZEDMH_SB_SIZED_EXACTMH_INLINE_SIZED_EXACT(默认)前五种策略本质还是用StringBuilder的实现,而默认的策略MH_INLINE_SIZED_EXACT是直接使用字节数组来操作,并且字节数组长度预先计算好,可以减少字符串复制操作。可以通过添加JVM参数来改变默认的策略,例如将策略改为BC_SB-Djava.lang.invoke.stringConcat=BC_SB-Djava.lang.invoke.stringConcat.debug=true```
源码:
==makeConcatWithConstants内部调用了doStringConcat方法==

==doStringConcat方法则调用了generate方法来生成MethodHandle==

==generate根据不同的STRATEGY来生成MethodHandle==

==这些STRATEGY(策略)分别是==
privateenumStrategy{/*** Bytecode generator, calling into {@linkjava.lang.StringBuilder}.*/BC_SB,/*** Bytecode generator, calling into {@linkjava.lang.StringBuilder};* but trying to estimate the required storage.*/BC_SB_SIZED,/*** Bytecode generator, calling into {@linkjava.lang.StringBuilder};* but computing the required storage exactly.*/BC_SB_SIZED_EXACT,/*** MethodHandle-based generator, that in the end calls into {@linkjava.lang.StringBuilder}.* This strategy also tries to estimate the required storage.*/MH_SB_SIZED,/*** MethodHandle-based generator, that in the end calls into {@linkjava.lang.StringBuilder}.* This strategy also estimate the required storage exactly.*/MH_SB_SIZED_EXACT,/*** MethodHandle-based generator, that constructs its own byte[] array from* the arguments. It computes the required storage exactly.*/MH_INLINE_SIZED_EXACT}
```
==默认的策略MH_INLINE_SIZED_EXACT==

3.3 常见笔试题
/*产生2个字符串对象:字符串常量池中一个,堆内存中一个。
*/String s =newString("abc");/*产生1个字符串对象:常量池中的"abc"。代码在编译阶段会优化为 String s = "abc";
*/String s ="a"+"b"+"c";/*5个字符串对象常量池:"a", "b"堆内存:new方式的"a",new方式的"b",new方式的"ab"注意:常量池中不会产生"ab"
*/String s =newString("a")+newString("b");/*
jdk8及之前创建3个字符串对象:常量池: "c" , "ab"堆中: new "abc"jdk9之后创建2个字符串对象:常量池: "c"堆中: new "abc"
*/String s1 ="c";String s2 ="a"+"b"+s1;```
4 intern()方法的演变
4.1 intern()方法调用区别
publicclassStringDemo5{publicstaticvoidmain(String[] args){String s1 =newString("ab");String s2 ="ab";System.out.println(s1==s2);//fasle//intern()方法从常量池中取出"ab"对象String s1 =newString("ab").intern();String s2 ="ab";System.out.println(s1==s2);//true/*从常量池中取出和s1内容相同的"ab"对象,此时常量池中没有"ab"对象。如果常量池中没有该字符串对象:jdk6及之前,intern()方法会创建新的字符串对象,放入常量池并返回新的地址。jdk7及之后,intern()方法会将调用者对象的地址放入常量池,并返回调用者对象地址。*/String s1 =newString("a")+newString("b");s1.intern();String s2 ="ab";System.out.println(s1==s2);//jdk6 false; jdk7之后true}}
```
4.2 intern()方法总结
```java
intern()方法将这个字符串对象尝试放入常量池中,并返回地址。
jdk1.6中:
如果池中有,则不会放入,返回已有的池中的对象的地址。
如果池中没有,则把此对象重新创建一份,放入池中,并返回池中新的对象地址。
jdk1.7起:
如果池中有,则不会放入,返回已有的池中的对象的地址。
如果池中没有,则把此对象的引用地址复制一份,放入池中,并返回池中的引用地址。
```
相关文章:

String类的底层原理和版本演变
1 String类的底层演变(1) JDK8以及之前版本 (2)JDK9以及之后版本 javaJDK8的字符串存储在char类型的数组里面,在java中,一个char类型占两个字节。但是很多时候,一个字符只需要一个字节就可存储&…...

软考高级信息系统项目管理师系列之二十三:项目采购管理
软考高级信息系统项目管理师系列之二十三:项目采购管理 一、项目采购管理内容整理二、项目采购管理1.采购的定义2.项目采购管理3.战略合作管理三、规划采购1.供应商管理2.采购需求与计划3.规划采购的输入、输出、工具和技术四、实施采购1.采购合同知识2.实施采购的输入、输出、…...

SpringMVC-0308
五、域对象共享数据0、三个域对象范围request:一次请求 第1~6都是向request共享session:一次会话(浏览器开启到浏览器关闭,与服务器关闭无关,session有钝化和活化操作,可以持久化数据࿰…...

[数据结构]:14-选择排序(顺序表指针实现形式)(C语言实现)
目录 前言 已完成内容 选择排序实现 01-开发环境 02-文件布局 03-代码 01-主函数 02-头文件 03-PSeqListFunction.cpp 04-SortCommon.cpp 05-SortFunction.cpp 结语 前言 此专栏包含408考研数据结构全部内容,除其中使用到C引用外,全为C语言代…...

基于C/C++综合训练 ----- 贪吃蛇
文章目录一、定义结构体对象二、游戏初始化1. 蛇初始化2. 食物初始化3. 围墙初始化4. 界面初始化三、逻辑编程1. 启动游戏2. 打印成绩3. main函数四、细节处理五、程序源码该篇环境为Visual Studio2022 游戏简述 :在控制终端绘画出一个矩阵表示游戏界面(围墙)&…...

Unity 混合操作(Blending)
渲染图形时,在执行所有着色器并应用所有纹理后,像素将写入到屏幕。这些像素与已有像素的组合方式由 Blend 命令控制。用于生成透明对象。《Unity Shader入门精要》大致解释:片元通过了模板测试和深度测试之后,会进行混合步骤。如果…...

Hive建表高阶语句
CTAS -as select方式建表CREATE TABLE ctas_employee as SELECT * FROM employee;CTE (CTAS with Common Table Expression)CREATE TABLE cte_employee AS WITH r1 AS (SELECT name FROM r2 WHERE name Michael), r2 AS (SELECT name FROM employee WHERE gender Male), r3 …...

面向新时代,海泰方圆战略升级!“1465”隆重发布!
过去四年,海泰方圆“1344”战略一直在引领公司前行,搭建了非常坚实的战略框架基座,并推动全员在实践和行动中达成深度共识。 “1344”战略 1个定位,代表着当前机构用户的一组共性需求,密码安全数据治理信创工程。 3…...

带你感受一次JVM调优实战
本文分成两部分,先了解理论,然后再进行实战。 理论篇 1.1 调优目标 JVM调优的两大目标是: 提高应用程序的性能和吞吐量: 通过优化JVM的垃圾回收机制、调整线程池大小和优化代码,可以提高应用程序的性能和吞吐量。…...

ALG和STUN
目录 ALG 应用层网关讲解 Client1使用FTP主动模式建立FTP Client1使用FTP被动模式建立FTP STUN讲解 ALG 应用层网关讲解 用来替换应用层信息 Client1使用FTP主动模式建立FTP 主动模式:服务器收到客户端发来的请求FTP的地址和端口 服务器使用20端口直接向客户端建…...
原生HTML放大镜
该放大区域用背景图片放大 <!DOCTYPE html> <html lang"zh"><head><meta charset"UTF-8"><meta name"viewport" content"widthdevice-width, initial-scale1.0"><meta http-equiv"X-UA-Compat…...

C++——模板
文章目录1 泛型编程2 函数模板2.1 函数模板概念2.2 函数模板格式2.3 函数模板的实例化2.3.1 隐式实例化2.3.1.1 定义2.3.1.2 代码演示2.3.1.3 运行结果2.3.1.4 缺点2.3.2 显式实例化2.3.2.1 格式2.3.2.2 代码演示2.3.2.3 运行结果2.4 模板参数的匹配原则2.4.12.4.22.4.33 类模板…...

Chapter2.1:线性表基础
该系列属于计算机基础系列中的《数据结构基础》子系列,参考书《数据结构考研复习指导》(王道论坛 组编),完整内容请阅读原书。 1.线性表的定义和基本操作 1.1 线性表的定义 线性表是具有相同数据类型的n(n≥0)n(n≥0)n(n≥0)个数据元素的有限序列&…...

Spring源码解析-Spring 循环依赖
Spring源码解析简图: Spring 如何解决循环依赖,⽹上的资料很多,但是感觉写得好的极少,特别是源码解读⽅⾯,我就⾃⼰单独出⼀ 篇,这篇⽂章绝对肝! 文章目录: 一. 基础知识 1.1 什么…...

从零开始学架构——架构设计的目的
软件架构的历史背景 软件架构真正流行是从20世纪90年代开始的,由于在Rational和Microsoft内部的相关活动,软件架构的概念开始越来越流行。 卡内基梅隆高校的玛丽肖(Mary Shaw)和戴维加兰 (David Garlan)对软件架构做了许多讨论,他们在 1994 年的一篇文章…...

Python 异步: 异步生成器(16)
动动发财的小手,点个赞吧! 生成器是 Python 的基本组成部分。生成器是一个至少有一个“yield”表达式的函数。它们是可以暂停和恢复的函数,就像协程一样。 实际上,Python 协程是 Python 生成器的扩展。Asyncio 允许我们开发异步生…...

.net6 web api使用EF Core,根据model类自动生成表
1.安装EF Core和mysql数据库的nuget包 Microsoft.EntityFrameworkCore Pomelo.EntityFrameworkCore.MySql 2.创建models文件夹,在文件夹下创建实体类 public class Users{public int Id { get; set; }[Column(TypeName "varchar(200)"), Required]publ…...

计算机科学导论笔记(五)
目录 七、操作系统 7.1 引言 7.1.1 操纵系统 7.1.2 自举过程 7.2 演化 7.3 组成部分 7.3.1 用户界面 7.3.2 内存管理器 7.3.3 进程管理器 7.3.4 设备管理器 7.3.5 文件管理器 7.4 操作系统 7.4.1 UNIX 7.4.2 Linux 7.4.3 Windows 七、操作系统 7.1 引言 计算机…...

通过命令打Java可执行jar包
文章目录1.背景2.操作步骤2.1. 准备好java源文件2.2 确认java源文件中是否有包名2.3 编译java文件2.4 初步打包2.5 解压jar包,得到MANIFEST.MF文件2.6 修改MANIFEST.MF文件2.7 再次打包3.验证4.打包参数参考5.参考文章1.背景 今天,无意中翻出了N年之前年…...

java基础系列(九) 接口和抽象类
一. 接口 简单的说,接口就是一种被规范的标准,只要符合这个标准都可以通用,接口的表现 在于对行为的抽象. 1.1 创建接口的格式 格式1: public interface 接口名 格式2: interface 接口名 1.2 在JDK1.8之后, 在接口中可以定义实现的方…...

Docker启动问题docker is starting…
环境window 10 家庭最新版直接上官网安装的 Docker DeskTop问题启动应用后setting打开一直转圈圈;主界面一直显示 docker is starting…解决方案3.1 先确定hyper-v是否开启搜hyper-v,点击启动或关闭Windows功能如下,选中Hyper-V服务3.2 进入任务管理期&a…...

Django/Vue实现在线考试系统-03-开发环境搭建-MySQL安装
1.概述 MySQL是一种关系型数据库管理系统,所使用的 SQL 语言是用于访问数据库的最常用标准化语言。MySQL 软件采用了双授权政策,分为社区版和商业版,由于其体积小、速度快、总体拥有成本低,尤其是开放源码这一特点,一般中小型和大型网站的开发都选择 MySQL 作为网站数据库…...

python实现波士顿房价预测
波士顿房价预测 目标 这是一个经典的机器学习回归场景,我们利用Python和numpy来实现神经网络。该数据集统计了房价受到13个特征因素的影响,如图1所示。 对于预测问题,可以根据预测输出的类型是连续的实数值,还是离散值ÿ…...

Pinia不酸,保甜
为什么是Pinia 怎么说呢,其实在过往的大部分项目里面,我并没有引入过状态管理相关的库来维护状态。因为大部分的业务项目相对来说比较独立,哪怕自身功能复杂的时候,可能也仅仅是通过技术栈自身的提供的状态管理能力来处理业务场景…...

uniapp生命周期
uniapp生命周期 uniapp生命周期不同于vue生命周期,uniapp生命周期分为: 应用生命周期 页面生命周期 组件生命周期 应用生命周期(官网) 注意 应用生命周期仅可在App.vue中监听,在其它页面监听无效。 onlaunch里进行页面跳转,如遇白…...

经典卷积模型回顾11—Xception实现图像分类(matlab)
Xception是一种深度卷积神经网络,它采用了分离卷积来实现深度神经网络的高准确性和高效率。Xception的名称来自“extreme inception”,意思是更加极致的Inception网络。 在传统的卷积神经网络中,每个卷积层都有若干个滤波器(即卷…...

移动App性能测试包含哪些内容?App性能测试工具有哪些?
随着互联网高科技的蓬勃发展,移动app的的需求量和供给量都较大。但一款好app的成功上线以及为用户带来高效体验,性能测试起着关键性的作用。性能测试是通过自动化的测试工具模拟多种正常、峰值以及异常负载条件来对系统的各项性能指标进行测试࿰…...

AI测试的迷思
近年来,我一直关注AI相关的测试,并积极参与多个全国性测试社区和社群。在这些社区中,我与不同公司和领域的测试专家交流探讨AI测试相关话题,包括业界顶尖公司的专家和国内知名测试学者。我也参加了多个大会,聆听了许多…...

[ 红队知识库 ] 一些常用bat文件集合
🍬 博主介绍 👨🎓 博主介绍:大家好,我是 _PowerShell ,很高兴认识大家~ ✨主攻领域:【渗透领域】【数据通信】 【通讯安全】 【web安全】【面试分析】 🎉点赞➕评论➕收藏 养成习…...

Qt广告机服务器(上位机)
目录功能结构adSever.promain.cpptcp_MSG.h 共用Tcp传输信息adsever.h 服务器adsever.cpp 服务器addate.h 时间处理addate.cpp 时间处理adtcp.h 客户端Socket处理adtcp.cpp 客户端Socket处理client.h 客户端信息类client.cpp 客户端信息类admsglist.h 信息记录模块admsglist.cp…...