由于Web服务API调用(例如JSON,REST,SOAP,...),外部数据源调用(SQL,从DB拿到的数据,...),文本解析,文本构建等等,如今的Java应用程序会执行大量的字符串操作。 因此,字符串对象可以轻松占用至少30%的内存。 显然,这些String对象的大部分都是重复的。 由于字符串重复,浪费了大量内存。 因此,为了优化重复字符串对象浪费的内存,JEP 192中增加了对重复字符串的优化。
JEP 192 :G1的String去重
当我们使用G1 GC时,它会从内存中删除垃圾对象。 它还从内存中删除重复的字符串对象,叫做string deduplication(字符串去重)。 而且只需要通过传递以下JVM参数就可以激活此功能:
-XX:+UseG1GC -XX:+UseStringDeduplication
Note 1:要想使用此功能,你需要把你的Java升级到Java 8 update 20以及往后的版本。
Note 2:“ -XX:+UseStringDeduplication” 参数是运行在G1之上的,所以你需要在G1下使用此参数才会生效。
例子
接下来用一个简单的程序来验证此功能。
public class StringDeduplicationExample {
public static List<String> myStrings = new ArrayList();
public static void main(String[] args) throws Exception {
for (int counter = 0; counter < 200; ++counter) {
for (int secondCounter = 0; secondCounter < 1000; ++secondCounter) {
//添加一千次
myStrings.add(("Hello World-" + counter));
}
System.out.println("Hello World-" + counter + " 被添加了1000次");
}
}
}
这个程序基本逻辑就是创造了一堆重复的字符串:
1000个 “Hello World-0” 字符串实例
1000个 “Hello World-1” 字符串实例
1000个 “Hello World-2” 字符串实例
...
...
...
1000个 “Hello World-199” 字符串实例
然后分别用两个不同的JVM参数来运行这个程序。
Run#1
本次运行我们使用 ‘-XX:+ UseStringDeduplication’ 来运行程序。即:
-Xmx20M -XX:+UseG1GC -XX:+UseStringDeduplication
Run#2
第二次运行我们去掉 ‘-XX:+ UseStringDeduplication’ 来运行程序。即:
-Xmx20M -XX:+UseG1G
在两次运行期间,我们捕获了heap dump并通过堆分析工具HeapHero.io分析了dump文件。 HeapHero.io可以检测由于各种低效的编程实践而浪费的内存量,包括由于重复字符串而浪费掉的内存量。
以下是由HeapHero.io生成的报告:
第一次带参数的运行分析报告: http://heaphero.io/heap-s3-progress.jsp?p=YXJjaGl2ZWQvMjAxOC8wNC8xOS8tLXN5c3Byb3BlcnR5LTIwbWIuaHByb2YtMTktNTAtMy0t 第二次不带参数的运行分析报告: http://heaphero.io/heap-s3-progress.jsp?p=YXJjaGl2ZWQvMjAxOC8wNC8xOS8tLW5vc3lzcHJvcGVydHktMjBtYi5ocHJvZi0xOS01MS00LS0=
以下是报告中的一些指标:
Run#1 带去重参数:
Run#2 不带去重参数:
报告中的几个有趣的指标:
即使执行了相同的代码,在Run #1(传递了参数'-XX:+ UseStringDeduplication'),我们可以看到总堆大小为7.94mb,而在Run #2中(没有传递去重参数'-XX:+ UseStringDeduplication' ),整个堆大小有了相当大的增加 - 15.89mb。
尽管在两次运行(206092)中都有相同数量的字符串对象,但由于Run #1中的重复字符串而浪费的内存量为5.6mb,而在Run #2中则多达13.81mb。
由于“-XX:+ UseStringDeduplication”参数使内存消耗大大减少,它可以从应用程序中清除大量重复的字符串。因此,鼓励大家多使用“-XX:+ UseG1GC -XX:+ UseStringDeduplication”,这样可以减少由于重复字符串而引起的内存浪费。这样做有可能能够降低应用程序的整体内存占用量。
本文分享自 ImportSource 微信公众号,前往查看
如有侵权,请联系 cloudcommunity@tencent.com 删除。
本文参与 腾讯云自媒体同步曝光计划 ,欢迎热爱写作的你一起参与!