字符串重复
JDK开发组研究得出的一组有趣的统计数据:
1.java应用内存里面的字符串占比大概是25%。
2.java应用内存里面的字符串有13.5%是重复的。
3.字符串的平均长度是45。
什么是重复字符串呢?
看下面的代码:
1. `String string1 = newString("Hello King");`2. `String string2 = newString("Hello King");`
两个字符串对象string1和string2,它们的内容是一样的,都是Hello King,但是string1和string2是两个不同的对象。
string1.equals(String2)=true,但是(string1==string2) =false,所以string1和string2就是所谓的重复对象。
Java处理的方式
1.通过使用String.intern()方法 2.通过启用字符串重复数据删除(仅适用于G1垃圾收集器)
启用字符串重复数据删除
此功能此后仅在Java8上可用,并且仅在使用G1垃圾收集器时才能启用。
使用以下标志可以启用重复数据删除。
1. `-XX:+UseG1GC-XX:+UseStringDeduplication`
注意事项
(1)只适用于G1收集器
JVM中有很多的GC收集器(串行、并行、CMS等等),XX:+UseStringDeduplication只能用在G1收集器上,如果你是使用的别的收集器需要切换到G1才可以。
(2)只适用于长期存活的对象
XX:+UseStringDeduplication主要是用来消除长时间存活的重复字符串对象,它不会对短期存活的对象做去重。如果字符串的生命周期很短,很可能还没来记得做去重就已经死亡了。但是,如果你的应用有大量的缓存(尤其是缓存的对象是长时间存活的对象),UseStringDeduplication这个参数就可能非常有用了!
(3)-XX:StringDeduplicationAgeThreshold=3
默认情况下,一个字符串对象经过3次GC以后还存活才会被列为去重的候选对象,可以用-XX:StringDeduplicationAgeThreshold来改变经历的GC的次数,比如:
1. `-XX:StringDeduplicationAgeThreshold=6`
(4)仅能用于Java 8 update 20以后
只有从Java 8 update 20以后才开始支持这个参数,因此,如果你的JDK版本比较老的话就没法用这个功能了。
(5)-XX:+PrintStringDeduplicationStatistics查看去重信息
如果你想查看字符串去重的一些统计信息,比如说去重花了多长时间、多少重复字符串被去重、节省了多少内存等等,可以传递-XX:+PrintStringDeduplicationStatistics这个参数给JVM,在GC日志中就可以打印出这些信息来。
总结
如果你的应用使用的是G1收集器,并且JDK的版本大于 JDK 8 update 20,那么可以尝试开启-XX:+UseStringDeduplication,如果你的应用中存在大量长时间存活的对象,那结果一定还不错。