ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

JVM-StringTable

2021-09-21 22:03:05  阅读:116  来源: 互联网

标签:String 常量 StringTable System 字符串 JVM println out


String的基本特性

  • String 字符串
    • String s1 = "vic"; //字面量的定义方式
    • String s2 = new String("vic");
  • String 声明为final,不可被继承
  • 实现了Serializable、Comparable,可序列化、可排序

JDK8及以前内部定义了final char[] values 存储字符串数据,JDK9之后改为byte[]

根据JDK官方描述:大部分内容都是拉丁文所以一个byte就能存储,所以改为byte[]+编码的方式节省空间

StringBuffer、StringBuild都同样的做了修改

不可变字符序列

  • 当对字符串重新赋值时,需要重写指定内存区域赋值,不能使用原来的value进行赋值
  • 当对现有的字符串进行连接操作时,也需要重新指定内存区域赋值,不能使用原有的value进行赋值
  • 当调用String的replace()方法修改指定字符或字符串时,也需要重新指定内存区域赋值,不能使用原来的value赋值

通过字面量的方式给一个字符串赋值,此时的字符串值声明在字符串常量池中

字符串常量池中不会存在相同内容的字符串

String.intern() 如果字符串常量池中没有对应data字符串的话,则在常量池中生成,并反回在字符串常量池中地址

  • String的String Pool是一个固定大小的HashTable,JKD6及之前默认长度为1009,JDK7后默认长度调整为60013
    • 因为如果String Pool中放入过多的String,会造成比较多的Hash冲突,而导致链表长度变长,而链表长度变长后直接导致了String.intern性能下降
  • -XX:StringTableSize 可设置StringTable长度
    • JDK8时StringTableSize最小值1009

String的内存分配

String类型的常量池比较特殊,主要使用方式有两种:

  • 只用使用双引号声明出来的String对象会直接存储在常量池中。比如:String s = "String";
  • 如果不是用双引号声明的String对象,可以使用String提供的intern()方法

Java6及以前,字符串常量池存在永久代
Java7,字符串常量池的位置调整到Java堆内
Java8,字符串常量在堆内

为什么StringTable要调整?

  1. permSize默认比较小
  2. 永久代垃圾回收的频率很低

String基本操作

public static void main(String[] args) {
    System.out.println();
    System.out.println("1");
    System.out.println("2");
    // 字符串"1"、"2"不会被再次加载
    System.out.println("1");
    System.out.println("2");
}
class Memory {
    public static void main(String[] args){
        int i = 1;
        Object obj = new Object();
        Memory mem = new Memory();
        mem.foo(obj);
    }

    private void foo(Object param) {
        String str = param.toString();
        System.out.println(str);
        
    }
}

image.png

字符串拼接操作

  1. 常量和常量的拼接结果在常量池,原理是编译期优化
  2. 只要其中一个是变量,结果就在堆中,变量拼接的原理是StringBuilder
  3. 如果拼接结果调用intern() 方法,则主动将常量池还没有的字符串对象放入池中,并返回次对象地址
public void test1() {
    String s1 = "a" + "b" + "c";
    String s2 = "abc";
    /*
     * 常量和常量的拼接结果在常量池
     */
    System.out.println(s1 == s2); // true
    System.out.println(s1.equal(s2)); // true
}
public void test2() {
    String s1 = "javaEE";
    String s2 = "hadoop";
    
    String s3 = "javaEEhadoop";
    String s4 = "javaEE" + "hadoop";
    String s5 = s1 + "hadoop";
    String s6 = "javaEE" + s2;
    String s7 = s1 + s2;
    
    /*
     * 只要其中一个是变量,则相当于在堆空间中new String(), 具体内容为拼接的结果:javaEEhadoop
     */
    System.out.println(s3 == s4); // true
    System.out.println(s3 == s5); // false
    System.out.println(s3 == s6); // false
    System.out.println(s3 == s7); // false
    System.out.println(s5 == s6); // false
    System.out.println(s5 == s7); // false
    System.out.println(s6 == s7); // false
    
    String s8 = s6.intern();
    System.out.println(s3 == s8); // true 
}
public void test3() {
    String s1 = "a";
    String s2 = "b";
    String s3 = "ab";
    /*
     * s1 + s2的执行细节:
     * 1. StringBuilder s = new StringBuilder();
     * 2. s.append("a");
     * 3. s.append("b");
     * 4. s.toString();   -> 约等于new String("ab");
     */
    String s4 = s1 + s2;
    System.out.println(s3 == s4); // false
}

标签:String,常量,StringTable,System,字符串,JVM,println,out
来源: https://www.cnblogs.com/baojiong/p/15317969.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有