JVM 调优实战之优化 eclipse 启动时间

本篇文章来自《深入理解 Java 虚拟机》的学习理解。

Java 语言之所以强大是因为有着 JVM 的垃圾回收机制,但是这并不意味着我们将垃圾回收交给 JVM 之后就可以不用操心了。当 JVM 出现问题或者系统性能遇到瓶颈的时候,我们要试着去分析和了解 JVM,才能更好的去发现问题,解决问题。本篇博客从 JVM 调优实战的角度出发,讲解如何对 JVM 进行优化。

调优前的运行状态

博主的机器配置:64 位 Win8 操作系统,JDK 版本1.7.67,CPU Intel Xeon L5520,16G 内存。初始的配置文件 eclipse.ini 如下:

-startup
plugins/org.eclipse.equinox.launcher_1.3.0.v20140415-2008.jar
--launcher.library
plugins/org.eclipse.equinox.launcher.win32.win32.x86_64_1.1.200.v20140603-1326
-product
org.eclipse.epp.package.jee.product
--launcher.defaultAction
openFile
--launcher.XXMaxPermSize
256M
-showsplash
org.eclipse.platform
--launcher.XXMaxPermSize
256m
--launcher.defaultAction
openFile
--launcher.appendVmargs
-vmargs
-Dosgi.requiredJavaVersion=1.7
-Xms40m
-Xmx512m

虚拟机运行数据通过 VisualVM 的插件 VisualGC 进行采集。得到的数据如下

这里写图片描述

从数据中可以看出 yong GC 触发了 122 次,耗时8.6秒。full GC 触发了 8 次,耗时6秒。

GC 日志截图如下:

这里写图片描述

要对 JVM 进行调优,首先就是要阅读并理解 GC 日志。这里简单介绍下如何理解 GC 日志。

2017-04-30T14:04:35.592+0800: 1.945: [GC [PSYoungGen: 23008K->1504K(23040K)] 38513K->23046K(50688K), 0.0121788 secs] [Times: user=0.11 sys=0.00, real=0.02 secs] 
2017-04-30T14:04:35.607+0800: 1.957: [Full GC [PSYoungGen: 1504K->0K(23040K)] [ParOldGen: 21542K->19613K(46080K)] 23046K->19613K(69120K) [PSPermGen: 8442K->8440K(21504K)], 0.2090261 secs] [Times: user=0.91 sys=0.03, real=0.22 secs] 

前面的数字 1.945 和 1.957 代表了 GC 发生的时间,是从 Java 虚拟机启动后经过的秒数。

日志开头的 GC 和 Full GC 说明了这次垃圾收集的停顿类型,而不是用来区分新生代 GC 还是老年代 GC 的。 Full GC 说明这次 GC 是发生了 Stop-The-World 的。如果是调用 System.gc() 方法触发的收集,则会显示 Full GC(System)。

接下来的 PSYoungGen,ParOldGen,PSPermGen 表示 GC 发生的区域,显示的名称和使用的 GC 收集器密切相关。

后面方括号内部的 23008K->1504K(23040K) 含义是 GC 前该内存已使用容量 -> GC 后该区域已使用容量(该区域总容量),方括号外面的 38513K->23046K(50688K) 表示 GC 前 Java 堆已使用容量 -> GC 后 Java 堆已使用容量(Java 堆总容量)。

最后的 0.0121788 secs 表示该区域 GC 所占用的时间,单位是秒。

有了以上基础知识后,我们就可以着手分析 GC 日志了。

  • 首先来解决新生代的 Minor GC,新生代 GC 总共耗时 2.407 秒。频繁 GC 明显是由于分配给新生代的内存空间太小而导致的。因此有必要使用 -Xmn 参数调整新生代的大小。

  • 再来看看 8 次的 Full GC,总共耗时 6.211 秒。从 GC 日志中查看原因,Old space 还有很多空余内存,然而 Perm space 则没有内存需要扩容而导致的GC。

  • class 编译的时间也过长,加上 -Xverify:none 禁止字节码验证。

根据分析,优化方案确定为将 Java 堆容量提升到 1024MB,新生代容量提升到 256MB,永久代容量 134MB。优化后启动 eclipse 的效果如下。

这里写图片描述

这回没有 Full GC 了,Minor GC 也从122次下降到了23次。总体的效果已经出来了。但是发现新生代的GC还是过于频繁,通过Visual GC 控制台,发现 Eden space 大小不固定,也是导致新生代 GC 频繁的原因。因此给定参数-XX:SurvivorRatio=8,使得Survivor和Eden的比例是8:1:1(JVM 默认参数就是这个,但博主不知为何在不显示指定的情况下 Survivor 和 Eden 空间会动态调整,显示指定后却没有这种问题,希望高人解答)。

又发现Old space 最多用到 300 多 MB,因此可以把 Yang space的内存适当调大些, Old space 的内存调小些。

JVM 的 GC 耗时也比较长,对于我这种重视交互的人来说有点受不了,所以果断换上 CMS + ParNew 的组合,提高垃圾收集速度。-XX:+UseConcMarkSweepGC -XX:+UseParNewGC

再次优化后的结果如下:

这里写图片描述

这次 Minor gc 次数再次下降,只有 3 次,总共耗时 327.845 毫秒,总体来说比较满意。这里附上优化后的最终配置,供大家参考:

-vm
D:/java/install/JDK/jdk1.7.0_67/bin/javaw.exe
-startup
plugins/org.eclipse.equinox.launcher_1.3.0.v20140415-2008.jar
--launcher.library
plugins/org.eclipse.equinox.launcher.win32.win32.x86_64_1.1.200.v20140603-1326
-product
org.eclipse.epp.package.jee.product
--launcher.defaultAction
openFile
--launcher.XXMaxPermSize
256M
-showsplash
org.eclipse.platform
--launcher.XXMaxPermSize
256m
--launcher.defaultAction
openFile
--launcher.appendVmargs
-vmargs
-Dosgi.requiredJavaVersion=1.7
-Dsun.awt.keepWorkingSetOnMinimize=true
-server
-Xverify:none
-Xms1024m
-Xmx1024m
-XX:NewSize=400m
-XX:MaxNewSize=400m
-XX:PermSize=118m
-XX:MaxPermSize=118m
-XX:+DisableExplicitGC
-XX:SurvivorRatio=8
-XX:+UseConcMarkSweepGC
-XX:+UseParNewGC
-XX:ParallelCMSThreads=4
-XX:+CMSPermGenSweepingEnabled
-XX:+CMSClassUnloadingEnabled
-XX:CMSInitiatingOccupancyFraction=80
-XX:CompileThreshold=100
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值