zoukankan      html  css  js  c++  java
  • JVM

     
    StringTable:在方法区中的运行常量池中,会将第一次定义的String存入其中,下次再出现时直接将变量指向里面的值。结构是hash表
     
            String s1 = "ha";
            String s2 = "ha";
            String s3 = s1 +s2;
            String s4 = "ha" + "ha";
            String s5 = "haha";
            String s6 = new String("haha");
            System.out.println(s3 == s4);
            System.out.println(s4 == s5);
            System.out.println(s5 == s6);

    输出:

    false

    true

    false

    s3本质调用了 new StringBuilder.append("a").append("b").toString(); 声明了新的引用变量,开辟了新的空间,所以指向的是堆中的对象地址而不是StringTable中的字符串了。

    s6同理

    s4 = "ha" + "ha";因为是两个常量拼接,在编译时就会直接变成"haha"进行处理,进入StringTable

    s5 = "haha",因为也是常量,会先在StringTable中查找,找到后s5指向了StringTable中的"haha",因此s4 == s5返回true。

    String.intern()方法,如果String在StringTable中不存在,则可以将这个String加入StringTable中,并返回这个对象。

    比如上面的方法中加入s3.intern(),

            String s1 = "ha";
            String s2 = "ha";
            String s3 = s1 +s2;
            s3.intern();
            String s4 = "ha" + "ha";
            System.out.println(s3 == s4);

    输出:

    true

    因为s3的值"haha"被放入了StringTable,s3指向了StringTable的"haha"对象

    把haha变为main

            String s1 = "ma";
            String s2 = "in";
            String s3 = s1 +s2;
            s3.intern();
            String s4 = "ma" + "in";
            System.out.println(s3 == s4);

    输出:

    main String,java等属于关键词,在一开始就在StringTable中存在了,所以s3.intern没能插入进去。

    改回haha,如果再在s3前加入一个String ss = "haha";

            String s1 = "ha";
            String s2 = "ha";
            String ss = "haha";
            String s3 = s1 +s2;
            s3.intern();
            String s4 = "ha" + "ha";
            System.out.println(s3 == s4);

    输出:

    false

    因为s3.intern()执行时发现StringTable中有了"haha"了,所以没能加入成功,s3依旧是指向了堆内存中的对象。

    -Xms500m  设置堆内存为500mb

    -XX:StringTableSize=2000  将StringTable中的桶个数设为2000。 hash表桶的数量越多(数组部分长度越长),数据越分散,hashcode撞车的概率越小,速度越快。 默认值是6万多

    -XX:+PrintStringTableStatistics 显示StringTable的状况。

    StringTable有内存回收机制

    打开“Run->Edit Configurations”菜单

     在VM option(虚拟机设置)中,加入代码:-XX:StringTableSize=2000 ,点击ok,然后运行下面的代码

            long t1 = new Date().getTime();
            String[] a = new String[1000000];
            for(int i=0; i<1000000; i++){
                a[i] = ("" + i).intern();
            }
            long t2 = new Date().getTime();
            System.out.println(t2 - t1);

    运行时间为9000多毫秒。

    然后修改VM option:-XX:StringTableSize=20000,点击ok,然后再尝试

    运行时间为1000多毫秒

    然后修改VM option:-XX:StringTableSize=200000,点击ok,然后再尝试

    运行时间为400多毫秒

  • 相关阅读:
    Vue2.1.7源码学习
    JavaScript 复制对象【Object.assign方法无法实现深复制】
    数组去重你知道几种?
    基于webpack2.x的vue2.x的多页面站点
    欲练JS,必先攻CSS——前端修行之路
    闭包的7种形式
    遇见未知的CSS
    redux 个人整理
    log4j.properties打印日志信息(1)
    Java Web开发之Servlet、JSP基础
  • 原文地址:https://www.cnblogs.com/clamp7724/p/11751278.html
Copyright © 2011-2022 走看看