练习:
在 JDK6 中,在字符串常量池中创建一个字符串 "ab"
在 JDK8 中,在字符串常量池中没有创建 "ab",而是将堆中的地址复制到 串池中。
所以上述结果,在 JDK6 中是:
true false在JDK8中是
true true针对下面这题,在 JDK6 和 8 中表现的是一样的
使用 intern() 优化执行效率:空间使用上
结论:对于程序中大量存在的字符串,尤其是其中存在很多重复字符串时,使用 intern() 可以节省内存空间。
大的网站平台,需要内存中存储大量的字符串。比如社交网站,很多人都存储:北京市、海淀区等信息。这时候如果字符串都调用 intern() 方法,就会明显降低内存的大小。
执行之后只有 60000 多个对象,因为进行了垃圾回收。
G1 中的 String 去重操作官方说明:
注意这里说的重复,指的是在堆中的数据,而不是常量池中的,因为常量池中的本身就不会重复
String str1 = new String("hello");
String str2 = new String("hello");
是指这个堆中的对象去重
背景:对许多 Java 应用(有大的也有小的)做的测试得出以下结果:
堆存活数据集合里面 string 对象占了 25%
堆存活数据集合里面重复的 string 对象有 13.5%
string 对象的平均长度是 45
许多大规模的 Java 应用的瓶颈在于内存,测试表明,在这些类型的应用里面,Java 堆中存活的数据集合差不多 25% 是 String 对象。更进一步,这里面差不多一半 String 对象是重复的,重复的意思是说:
stringl.equals(string2)= true。堆上存在重复的 string 对象必然是一种内存的浪费。这个项目将在 G1 垃圾收集器中实现自动持续对重复的 string 对象进行去重,这样就能避免浪费内存。
当垃圾收集器工作的时候,会访问堆上存活的对象。对每一个访问的对象都会检查是否是候选的要去重的 string 对象。
如果是,把这个对象的一个引用插入到队列中等待后续的处理。一个去重的线程在后台运行,处理这个队列。处理队列的一个元素意味着从队列删除这个元素,然后尝试去重它引用的 string 对象。
使用一个 hashtable 来记录所有的被string 对象使用的不重复的 char 数组。当去重的时候,会查这个 hashtable,来看堆上是否已经存在一个一模一样的 char 数组。
如果存在,string 对象会被调整引用那个数组,释放对原来的数组的引用,最终会被垃圾收集器回收掉。
如果查找失败,char 数组会被插入到 hashtable,这样以后的时候就可以共享这个数组了。
开启命令行选项
UseStringDeduplication(bool):开启 String 去重,默认是不开启的,需要手动开启。
PrintStringDeduplicationStatistics(bool):打印详细的去重统计信息
StringDeduplicationAgeThreshold(uintx):达到这个年龄的 String 对象被认为是去重的候选对象