String、StringBuffer、StringBuilder

String、StringBuffer、StringBuilder

String

final class

    • 所有属性也都是 final 的
    • 原生的保证了基础线程安全
      • 因为无法对它内部数据进行任何修改

典型的 Immutable 类

    • 所以拼接、裁剪字符串等动作,都会产生新的 String 对象
      • 对应用性能有明显影响
      • 操作不当可能会产生大量临时字符串

StringBuffer

可修改字符序列

    • StringBuffer 和 StringBuilder 底层都是利用可修改的(char,JDK 9 以后是 byte)数组
    • 继承了 AbstractStringBuilder

把各种修改数据的方法都加上 synchronized 关键字

    • 线程安全
      • 也随之带来了额外的性能开销
    • 简单粗暴

StringBuilder

可修改字符序列

    • 在能力上和 StringBuffer 基本相同
    • 继承了 AbstractStringBuilder

Java 1.5 中新增

    • 是绝大部分情况下进行字符串拼接的首选

线程不安全

    • 有效减小了开销

内部数组

内部数组的大小应该如何决定呢?

目前的实现

    • 构建时初始字符串长度加 16
      • 如果构建对象时没有输入最初的字符串
        • 初始值就是 16
      • 可以在创建时,主动指定合适的大小
    • 扩容会产生多重开销
      • 要抛弃原有数组,创建新的数组,还要进行 arraycopy

String的演化

在历史版本中,使用 char 数组保存数据

    • 非常直接
    • Java 中的 char 是两个 bytes 大小
      • 但拉丁语系语言的字符不需要太宽的 char
      • 这样无区别的实现就产生了一定的浪费

Compact Strings

    • 将数据存储方式从 char 数组改变为一个 byte 数组加上一个标识编码的所谓 coder,并且将相关字符串操作类都进行了修改
    • 紧凑字符串
      • 更小的内存占用、更快的操作速度
    • 所有相关的 Intrinsic 之类也都进行了重写
      • 保证没有任何性能损失。
    • 这个特性对于绝大部分应用来说是透明的
      • 因为虽然底层实现发生了改变,但 Java 字符串的行为并没有大的变化,
      • 绝大部分情况不需要修改已有代码

字符串缓存

intern 机制

Intern 是一种显式地排重机制

    • Java的intern机制是指在运行时,如果一个字符串常量(即用双引号括起来的字符串字面量)已经存在于字符串池中,那么在创建新的该字符串常量时,会返回已存在的字符串常量的引用,而不是新创建一个对象。

intern() 方法

    • 作用是提示 JVM 把相应字符串缓存起来,以备重复使用。
    • String 在 Java 6 以后提供
    • 创建字符串对象并调用 intern() 方法时
      • 如果字符串常量池中已经有缓存的字符串
        • 返回缓存里的实例
      • 如果没有
        • 将此String对象添加到池中缓存起来

早期的版本保存在 PermGen中

    • PermGen也就是"永久代"
    • 这个空间是很有限的
    • 基本不会被 FullGC 之外的垃圾收集照顾到
    • 所以,如果使用不当,OOM 就会光顾。

后续版本中保存在堆中

    • 避免永久代占满的问题
      • 永久代在 JDK 8 中被 MetaSpace(元数据区)替代
    • 默认缓存大小也在不断地扩大中
      • -XX:+PrintStringTableStatistics
        • 查看默认缓存
      • -XX:StringTableSize=N
        • 调整默认缓存

G1 GC 下的字符串排重

在 Oracle JDK 8u20 之后,推出了这个新的特性

将相同数据的字符串指向同一份数据

    • JVM 底层的改变,因此不需要修改 Java 类库

目前是默认关闭的

    • -XX:+UseStringDeduplication
      • 开启G1 GC 下的字符串排重功能

Intrinsic 机制

JVM 的底层优化机制

运行的往往就是特殊优化的本地代码,而不是 Java 代码生成的字节码

一种利用 native 方式 hard-coded 的逻辑

-XX:+PrintCompilation -XX:+UnlockDiagnosticVMOptions -XX:+PrintInlining

    • 查看 intrinsic 发生的状态
相关推荐
shuair1 小时前
idea 2023.3.7常用插件
java·ide·intellij-idea
小安同学iter2 小时前
使用Maven将Web应用打包并部署到Tomcat服务器运行
java·tomcat·maven
Yvonne9782 小时前
创建三个节点
java·大数据
不会飞的小龙人3 小时前
Kafka消息服务之Java工具类
java·kafka·消息队列·mq
是小崔啊3 小时前
java网络编程02 - HTTP、HTTPS详解
java·网络·http
brevity_souls4 小时前
Spring Boot 内置工具类
java·spring boot
小钊(求职中)4 小时前
Java开发实习面试笔试题(含答案)
java·开发语言·spring boot·spring·面试·tomcat·maven
shix .4 小时前
什么是tomcat
java·tomcat
java技术小馆4 小时前
Deepseek整合SpringAI
java·spring cloud
天荒地老笑话么4 小时前
Mac安装配置Tomcat 8
java·macos·tomcat