使用G1 GC,降低内存消耗20%
由于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”,这样可以减少由于重复字符串而引起的内存浪费。这样做有可能能够降低应用程序的整体内存占用量。
- 15.5 使用pure-ftpd搭建ftp服务
- JDK容器学习之Queue: ArrayBlockingQueue
- 手机APP安装包缩减方案
- react-native添加redux支持
- Java并发学习之ReentrantLock的工作原理及使用姿势
- Linux基础(day63)
- IOS WebView控件详解
- Java并发学习之synchronized使用小结
- 18.3/18.4/18.5 用keepalived配置高可用集群
- JDK容器学习之Queue:DelayQueue
- React-Native组件之 Navigator和NavigatorIOS
- JDK容器学习之Queue:ConcurrentLinkedQueue
- JDK容器学习之Queue: PriorityQueue
- React Native导航器之react-navigation使用
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法
- 一条命令让你明白shell中read命令的常用参数
- 防抖与节流
- 一道题理解Linux中sort命令的多个参数
- Centos7服务器下启动jar包项目的最佳方法
- JavaScript易错点(长期更新)
- Centos7.5配置java环境安装tomcat的讲解
- CSS3卡片光照效果
- Linux文本查找命令find的用法详解
- Canvas系列(2):曲线图形
- Shell中去除字符串里的空格或指定字符的方法
- 使用‘fsck’修复Linux中文件系统错误的方法
- linux/OSX中“DD”命令制作ISO镜像操作系统安装U盘的方法
- 《高效能程序员的修炼》读书笔记
- linux之centos7防火墙基本使用详解
- Ubuntu安装scrcpy完成手机投屏和控制(Ubuntu用QQ微信的另一种方法)