StringPool(字符串常量池)
字符串常量池的解释 字符串常量池(String Pool)保存着所有字符串字面量(literal strings),这些字面量在编译时期就确定哪些是要放入字符串常量池。具体来说,只有使用双引号("")创建的字符串字面量才会被认为是常量,从而被放入常量池中。 在运行时,还可以使用 String 的 intern() 方法在运行过程将字符串添加到 String Pool 中。调用该方法会判断字符串常量池是否有该字面量,如没有,会在字符串常量池创建。之后,会返回字符串常量池中的对象。 通过new创建的字符串字面量,会先将,无论是否在字符串常量池存在,都会创建新的对象且不放入字符串常量池。 String str1 = "Hello world!"; String str2 = "Hello world!"; String str3 = new String("Hello world!"); String str4 = new String("Hello world!"); String str5 = str4.intern();//运行过程中把字符串添加到String Pool,并返回String Pool中的对象 System.out.println(str1 == str2);//运行结果:true。 System.out.println(str1 == str3);//运行结果:false。 System.out.println(str3 == str4);//运行结果:false。 System.out.println(str1 == str5);//运行结果:true。 System.out.println(str4 == str5);//运行结果:false。 字符串常量池长度 在 jdk6中,StringTable的长度是固定的,就是1009的长度。所以如果常量池中的字符串过多,会产生hash冲突,导致链表变长,降低查询效率。 在jdk7中,StringTable的长度可以通过一个参数指定: -XX:StringTableSize=99991 字符串常量池的位置 不同版本的Java虚拟机(JVM)可能会采用不同的方式来实现字符串常量池,并且在不同的JVM实现中,字符串常量池的位置也可能会发生变化。 JDK 6 字符串常量池存在于运行时常量池,运行时常量池存在方法区。方法区的实现为永久代(PermGen)。 PermGen默认大小只有4m,这种设计可能会导致PermGen空间溢出(java.lang.OutOfMemoryError: PermGen space)的问题,并且在频繁加载大量类文件时容易出现性能问题。 JDK 7 为了解决这些问题,从 JDK 7 开始,字符串常量池被移动到了堆内存中。 JDK 8 还是在堆内存中。 字符串的拼接 如果定义字符串时有拼接的表达式,编译器会根据表达式的参数是否为"“直接引用来判断是否将字符串字面量放入字符串常量池。 如表达式"Hello”+" world!",编译器会将两个字符串拼接成一个新的字符串"Hello world!",然后对比这个新字符串对象和常量池中的字符串字面量"Hello world!“是否相同。由于Java字符串常量池的特性,当两个字符串的内容相同时,它们所引用的字符串对象实例也是相同的。因此,表达式"Hello”+" world!" == “Hello world!“的结果为true。 ...