JVM-036-StringTable-intern的使用以及StringTable的垃圾回收

intern()的使用

介绍

翻译:

字符串常量池池最初是空的,由String类私有地维护。在调用intern方法时,如果池中已经包含了由equals(object)方法确定的与该字符串内容相等的字符串,则返回池中的字符串地址。否则,该字符串 对象将被添加到池中,并返回对该字符串对象的地址。

阅读更多

JVM-035-StringTable-字符串的拼接操作

字符串的拼接操作

原理

  1. 常量与常量的拼接结果在常量池中(堆中划分的一块内存),原理是编译期优化
  2. 常量池中不会存在相同内容的变量
  3. 拼接前后,只要其中有一个是变量,结果就在堆中(区别于1中的堆,在常量池之外的堆中)。变量拼接的原理是StringBuilder
  4. 如果拼接的结果调用intern()方法,根据该字符串是否在常量池中存在,分为:
    • 如果存在,则返回字符串在常量池中的地址
    • 如果字符串常量池中不存在该字符串,则在常量池中创建一份,并返回此对象的地址
阅读更多

JVM-034-StringTable-String的概述和基本操作

String在JDk9中存储结构的变更

String在jdk8及以前内部定义了final char value[]用于存储字符串数据。JDK9时改为final byte[] value

官方文档http://openjdk.java.net/jeps/254

原因:

  1. String类的当前实现将字符存储在char数组中,每个字符使用两个字节(16位)。

  2. 从许多不同的应用程序收集的数据表明,字符串是堆使用的主要组成部分,而且大多数字符串对象只包含拉丁字符(Latin-1)。这些字符只需要一个字节的存储空间,因此这些字符串对象的内部char数组中有一半的空间将不会使用,产生了大量浪费。

  3. 之前 String 类使用 UTF-16编码 的 char[] 数组存储,现在改为 byte[] 数组 外加一个编码标识存储。该编码表示如果你的字符集编码是ISO-8859-1或者Latin-1,那么只需要一个字节存。如果你是其它字符集编码,比如UTF-8,你仍然用两个字节存

  4. 结论:String再也不用char[] 来存储了,改成了byte [] 加上编码标记,节约了一些空间

  5. 同时基于String的数据结构,例如StringBuffer和StringBuilder也同样做了修改

    1
    2
    3
    4
    // 之前
    private final char value[];
    // 之后
    private final byte[] value
阅读更多