JVM学习笔记(10) StringTable


一.String基本特性

在这里插入图片描述

String在JDK9中存储结构变更

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

在这里插入图片描述
在这里插入图片描述

在这里插入图片描述
在这里插入图片描述
根据设置不同的table长度来查看性能变化
在这里插入图片描述


二.String的内存分配

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述在这里插入图片描述
在这里插入图片描述

在这里插入图片描述


三.String的基本操作

在这里插入图片描述
在这里插入图片描述

在这里插入图片描述
在这里插入图片描述

四.字符串拼接操作

在这里插入图片描述

会进行编译器优化
在这里插入图片描述

如果拼接符号的前后出现了变量,则相当于在堆空间中new String() , 具体的内容为拼接的结果
inner() : 判断字符串常量池中是否存在javaEEHadoop的值,如果存在,则返回常量池中javaEEHadoop的地址
如果字符串常量池中不存在字符串,则在字符串中加载一份,并返回此对象的地址
在这里插入图片描述
在这里插入图片描述

拼接符号左右都是字符串常量或者常量引用
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

字符串拼接和append的运行效率的差别

通过StringBuilder 的append() 的方式添加字符串的效率要远高于使用String的字符串拼接的方式
好处: StringBuilder的appned() 方式 : 自始至终值创建过一个StringBuilder对象,
使用String的字符串拼接的方式: 创建了多个StringBuilder和String对象
使用String的字符串拼接方式,内存中由于创建了较多的StringBuilder和String对象,内存占用更大,如果进行GC,需要花费额外的时间
在这里插入图片描述

public class StringDemo {

    private static final int highLevel = 100000;

    @Test
    public void test1() {
        long start = System.currentTimeMillis();

        // method1();   // 4656

        method2();      // 3

        long end = System.currentTimeMillis();

        System.out.println("花费的时间是: " + (end - start));
    }

    public void method1() {
        String str = "";
        for (int i = 0; i < highLevel; i++) {
            str = str + "a"; // 每次循环都会创建一个StringBuilder(),还会创建一个String
        }
    }

    public void method2() {
        StringBuilder sb = new StringBuilder(); 
        // 如果预料到需要加的数据比较多,可以再初始化的时候就将创建的对象空间设置的大点,
        // 比如100万个数字,可以从空参构造器的93毫秒减少到 64左右
		// StringBuilder sb = new StringBuilder(highLevel);
        for (int i = 0; i < highLevel; i++) {
            sb.append("a");
        }
    }

}

五.intern()的使用

在这里插入图片描述
在这里插入图片描述

intern() 的使用 : jdk6 vs jdk7/8

可以查看对应的字节码文件来查看实际执行时创建了几个对象

在这里插入图片描述在这里插入图片描述

代码图示

public class String2Demo {

    /**
     * 注: 在jdk6中,使用intern()方法只是常规的在位于永久代(方法区)中的字符串常量池中创建一个字符串常量
     *     而在jdk7/8中,如图代码所示,由于在堆中已经存在了一个new String("11")对象,
     *                  此时在位于堆中的字符串常常量池中还未有"11"对象,
     *                  在此时调用intern()方法会在字符串常量池中创建一个"11"对象
     * 					(并不是真的创建了一个"11", 而是创建一个指向new String("11")的对象引用),此时由于节省空间的想法
     *                  由于堆中已经存在了一个了new String("11") 对象,,,字符串常量池中的"11"对象会指向
     *                  位于堆中的new String("1"), 即此时字符串常量池中的"11"对象存放的是堆中的new String("11")
     *                  的地址
     *                  然后再执行String s4 = "11";的时候,会在字符串常量池中发现已经存在了"11"对象,就会将"11"
     *                  对象的地址赋给s4,本质上也是指向了堆中的new String("11")
     *                  所以此时s3 == s4 是true
     *
     * @param args
     */
    public static void main(String[] args) {
        String s = new String("1");
        s.intern(); // 在调用此方法前,字符串常量池中已经存在了"1"
        String s2 = "1";
        System.out.println(s == s2); // jdk6 : false   jdk7/8 : false

        String s3 = new String("1") + new String("1");// s3变量记录的地址为new String("11")
        // 执行完上一行代码以后,字符串常量池中,是否存在"11" 呢? 答案 不存在
        s3.intern();// 在字符串常量池中生成"11".如何理解 ->
                                                        // jdk6 : 创建了一个新的对象"11", 也就有新的地址
                                                        // jdk7 : 此时常量中并没有创建"11", 而是创建一个指向堆空间中new String("11")的地址
        String s4 = "11";// s4变量记录的地址: 使用是上一行代码执行时,在常量池中生成的"11"的地址
        System.out.println(s3 == s4);// jdk6 : false  jdk7/8 : true
    }
}

在这里插入图片描述

在这里插入图片描述
在这里插入图片描述

在这里插入图片描述

示例1:

在这里插入图片描述

在这里插入图片描述在这里插入图片描述

当加了一行 x = "ab"后
在这里插入图片描述

示例2:

    public void stringDemo2() {
        String s1 = new String("ab");// 执行完之后,会在字符串常量池中生成"ab"
        // String s1 = new String("a") + new String("b"); // 执行完之后不会在字符串常量池中生成"ab"
        s1.intern(); // 如果上面那句加上这句的话,其实作用就和直接new String("ab") 一样了,这句其实没啥用,因为现在常量池中已经存在了"ab"
        String s2 = "ab";// s2 的值是常量池中的"ab"的地址, s1 则是堆中new String("ab")的地址(new String("ab")的ab指向的是常量池中的"ab")
        System.out.println(s1 == s2); // false
    }

intern() 的效率测试: 空间角度

使用intern()之后,会直接返回常量池中的对象的地址,这样子啊堆中新创建的new String() 就会因为没有引用一段时间后被自动清理掉,一次来达到了节约空间的作用
在这里插入图片描述

在这里插入图片描述

不用intern()

在这里插入图片描述

使用intern()

在这里插入图片描述
在这里插入图片描述

六.StringTable的垃圾回收

在这里插入图片描述


七.G1中的String去重操作

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值