JVM学习笔记——内存结构篇( 七 )

StringTable字符串延迟加载在这里我们再次强调一下StringTable中元素的加载原则:

  • StringTable中的值只会加载一次,不会重复加载
  • 存放在常量池的值在运行时不会加载,只有在第一次运行时才会加载到StringTable中
我们采用一个简单程序来证明:
package cn.itcast.jvm.t1.stringtable;/** * 演示字符串字面量也是【延迟】成为对象的 */public class TestString {public static void main(String[] args) {int x = args.length;System.out.println(); // 字符串个数 2275System.out.print("1");System.out.print("2");System.out.print("3");System.out.print("4");System.out.print("5");System.out.print("6");System.out.print("7");System.out.print("8");System.out.print("9");System.out.print("0");System.out.print("1"); // 字符串个数 2285System.out.print("2");System.out.print("3");System.out.print("4");System.out.print("5");System.out.print("6");System.out.print("7");System.out.print("8");System.out.print("9");System.out.print("0");System.out.print(x); // 字符串个数 2285}}StringTable的intern功能介绍我们的intern的功能主要分为两个版本:
  • jdk1.6:将这个字符串对象尝试放入串池,如果有则并不会放入,如果没有会把此对象复制一份,放入串池,会把串池中的对象返回
  • jdk1.8:将这个字符串对象尝试放入串池,如果有则并不会放入,如果没有则放入串池,会把串池中的对象返回
我们利用同样的代码来进行不同版本的介绍:
// 1.6版本package cn.itcast.jvm;public class Demo1_23 {public static void main(String[] args) {// 我们来仔细分析这个操作// 首先StringTable里面加入"a",然后堆里加上一个"a";然后StringTable里面加入"b",然后堆里加上一个"b"// 最后使用了toString方法,将"ab"放入堆中String s = new String("a") + new String("b");// StringTable=["a","b"]// 堆:new String("a")new String("b")new String("ab")// 将这个字符串对象尝试放入串池,如果有则并不会放入,如果没有则放入串池,会把串池中的对象返回// 目前s没有在StringTable中,所以将其复制一份放入StringTable,并将StringTable里面的"ab"返回回去// 这时s和StringTable里面的"ab"是不一样的!String s2 = s.intern();// 这时x,s2是StringTable里面的"ab",s是堆里面的"ab"String x = "ab";System.out.println( s2 == x);//trueSystem.out.println( s == x );//false}}public static void main(String[] args) {String x = "ab";String s = new String("a") + new String("b");// StringTable=["a","b","ab"]// 堆new String("a")new String("b") new String("ab")// 将这个字符串对象尝试放入串池,如果有则并不会放入,如果没有则放入串池,会把串池中的对象返回// 目前StringTable里存在"ab",所以将StringTable里面的ab返回给s2即可// 目前s2和x属于StringTable里面的ab,s属于堆里面的abString s2 = s.intern();System.out.println( s2 == x);//trueSystem.out.println( s == x );//false}}// 1.8版本package cn.itcast.jvm.t1.stringtable;public class Demo1_23 {public static void main(String[] args) {String s = new String("a") + new String("b");// StringTable=["a","b"]// 堆new String("a")new String("b") new String("ab")// 将这个字符串对象尝试放入串池,如果有则并不会放入,如果没有则放入串池,会把串池中的对象返回// 这里由于StringTable里面不存在,会将堆中s的字符串做成一个引用直接放入StringTable里面,再将StringTable的值返回// 这时s,s2,x均属于堆里面的ab,不过s2是堆里的ab,s,x为StringTable里面的引用的堆里面的ab,但他们相等String s2 = s.intern();String x = "ab";System.out.println( s2 == x);//trueSystem.out.println( s == x );//true}}public static void main(String[] args) {String x = "ab";String s = new String("a") + new String("b");// StringTable=["a","b","ab"]// 堆new String("a")new String("b") new String("ab")// 将这个字符串对象尝试放入串池,如果有则并不会放入,如果没有则放入串池,会把串池中的对象返回// 目前StringTable里存在"ab",所以将StringTable里面的ab返回给s2即可// 目前s2和x属于StringTable里面的ab,s属于堆里面的abString s2 = s.intern();System.out.println( s2 == x);//trueSystem.out.println( s == x );//false}}

经验总结扩展阅读