一个Java swing桌面应用程序的JVM内存调优

阅读更多
背景介绍

       用java swing(jdk 1.7.0_71)开发了一款类似于windows explorer的桌面产品,除了文件管理等常用的功能外,还附带了标签(TAG)管理功能,也就是对文件或者文件夹指定标签,根据标签对文件进行管理.

 

遇到的问题

       应用中有一个根据关键字进行文件查找的功能,查找本身并没有什么问题,只是对符合查找条件的文件或者文件夹进行画面显示的时候,遇到了jvm内存爆满的问题.因为测试了一种极端的情况,查找C盘下的所有带a关键字的文件和文件夹,因为结果集特别大,所以画面显示的时候遭遇了JVM内存储爆满.

 

原因分析

       结果集显示的时候,其实就是往JPanel里面不断地add新的文件JPanel,一个文件JPanel里面至少有两个JLabel,一个用来显示图标,另一个显示文件名,所有的这些对象都在不断地向JVM堆里面涌动,而且这些对象在切换到别的画面之前,都不会被JVM回收.这样就造成了JVM内存储爆满.

 

整个过程如下:

 

1>缺省配置启动java,最大堆内存为247.5M,这个数值是绝对不够用的

因为

NewRatio=2 default

SurvivorRatio=8 default

 

所以

Eden space=64M

Survivor space=8M

Tenured gen=175.5M

最终结果如下:

 

 

Console报错:

Exception in thread "RMI TCP Connection(idle)" Exception in thread "RMI TCP Connection(idle)" java.lang.OutOfMemoryError: Java heap space

Exception in thread "AWT-EventQueue-0" java.lang.OutOfMemoryError: Java heap space

Exception in thread "AWT-EventQueue-0" java.lang.OutOfMemoryError: Java heap space

Exception in thread "AWT-EventQueue-0" java.lang.OutOfMemoryError: Java heap space

Exception in thread "AWT-EventQueue-0" java.lang.OutOfMemoryError: Java heap space

Exception in thread "AWT-EventQueue-0" java.lang.OutOfMemoryError: Java heap space

Exception in thread "AWT-EventQueue-0" java.lang.OutOfMemoryError: Java heap space

Exception in thread "AWT-EventQueue-0" java.lang.OutOfMemoryError: Java heap space

Exception in thread "JMX server connection timeout 23" java.lang.OutOfMemoryError: Java heap space

java.lang.NullPointerException

at sun.awt.SunToolkit.postEvent(SunToolkit.java:473)

at sun.awt.windows.WComponentPeer.postEvent(WComponentPeer.java:849)


一个Java swing桌面应用程序的JVM内存调优_第1张图片
 

2>把最大堆内存调整到上限1024M

-XX:+PrintGCDetails  -Xms1024m -Xmx1024m

实际获得的heap合计:990M

因为

NewRatio=2 default

SurvivorRatio=8 default

 

所以

Eden space=273M

Survivor space=34M

Tenured gen=683M

最终,成功执行完查找操作,只是很勉强(Tenured gen只剩下了1K)

 

结果如下:

 

一个Java swing桌面应用程序的JVM内存调优_第2张图片
 

3>从2>的结果可以看出,问题的关键在于Tenured gen的空间大小,尽可能地把空间分给Tenured gen是解决问题的关键,于是,我们可以追加-XX:NewRatio参数来调大Tenured gen的空间,比如:

 

-XX:+PrintGCDetails  -Xms1024m -Xmx1024m -XX:NewRatio=4

因为绝大部分对象都是无法回收的,所以为了降低gc时间,其实我们也可以通过调大-XX:SurvivorRatio的值,变相拿掉Survivor space,比如:

-XX:+PrintGCDetails  -Xms1024m -Xmx1024m -XX:NewRatio=4  -XX:SurvivorRatio=65536

 

4>之前使用的gc属于单线程的serial collector,比较适合于单机,如果想尝试一下CMS并发收集器的话,也是可以的,虽然必要性不大

-XX:+PrintGCDetails  

-Xms1024m -Xmx1024m

-Xmn200m                                  直接指定年轻代大小,也可以通过-XX:NewRatio调节

-XX:SurvivorRatio=65536           变相去掉Survivor space

-XX:+UseConcMarkSweepGC    使用CMS内存收集

-XX:ReservedCodeCacheSize=10m            尽可能节省空间

-XX:MaxPermSize=20m                               尽可能节省空间

-XX:+CMSScavengeBeforeRemark        强制remark之前开始一次minor gc,减少remark的暂停时间,不过我们这种情况没有必要加,因为大部分对象都不会被gc掉

-XX:+UseCMSInitiatingOccupancyOnly        为了配合CMSInitiatingOccupancyFraction使用,不指定的话,jvm根据历史数据自动判断什么时候进行gc

-XX:CMSInitiatingOccupancyFraction=95    Tenured gen代使用空间达到95%才进行gc

 


一个Java swing桌面应用程序的JVM内存调优_第3张图片
 

  • 一个Java swing桌面应用程序的JVM内存调优_第4张图片
  • 大小: 108.2 KB
  • 一个Java swing桌面应用程序的JVM内存调优_第5张图片
  • 大小: 99.1 KB
  • 一个Java swing桌面应用程序的JVM内存调优_第6张图片
  • 大小: 80.9 KB
  • 查看图片附件

你可能感兴趣的:(jvm,cms,swing,jconsole)