其他分享
首页 > 其他分享> > JVM-StringTable

JVM-StringTable

作者:互联网

String的基本特性

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

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

StringBuffer、StringBuild都同样的做了修改

不可变字符序列

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

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

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

String的内存分配

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

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