JVM1小时1次FGC调优
2016-01-19 00:08
429 查看
通过cat发现项目一个奇怪现象,每隔一个小时都会进行一次fgc,很有规律,且和项目使用高低峰无关。最开始以为是内存泄漏。通过观察,发现线下研发环境也一样,fgc时堆的年轻代,年老代,持久代的内存都未占满,应该不是内存泄漏问题。开始怀疑项目中使用了JMX监控zookeeper状态时,保留了JMXConnector的连接对象。研发环境把这块去掉,观察发现没有fgc问题。问题找到了,上网搜了下,果然有前辈遇到过有现成的解决方案:
参考源:http://www.51testing.com/html/10/367410-858164.html
引发的原因是由于使用了RMI,会自动1小时调用1次system.gc()。
大多数的应用虽然配置了CMS gc方式,但是如果没有使用-XX:+ExplicitGCInvokesConcurrent,则会出现显示调用system.gc(),且不会进行 CMS的FGC,带来的影响是造成tps的波动(fgc停机时间越长,则波动会越大)。
收集各方的意见后,总结针对此类问题的解决方法如下:
1、增加参数 -XX:+DisableExplicitGC
该方法System.gc()的调用就会变成一个空调用。但是该方法不适用在大量使用NIO的direct memory,经常、反复的申请DirectByteBuffer的应用中使用,会造成“java.lang.OutOfMemoryError:
Direct buffer memory ”。该方法需根据应用具体情况而定。
2、增加参数 -Dsun.rmi.dgc.client.gcInterval=3600000 -Dsun.rmi.dgc.server.gcInterval=3600000
其中3600000即为定时触发的时间间隔设置,单位是毫秒,可适当延长触发FGC的定时时间间隔。
-Dsun.rmi.dgc.client.gcInterval=Long.MAX_VALUE -Dsun.rmi.dgc.server.gcInterval=Long.MAX_VALUE 则将fc时间间隔设为long型的最大值
3、增加参数 -XX:+ExplicitGCInvokesConcurrent 或者-XX:+ExplicitGCInvokesConcurrentAndUnloadsClasses
该方法可以指定System.gc()采用 CMS 算法,FGC时停机时间会变短,但是CMS GC次数不会变,仍然是1小时1次。
根据项目线上GC的内存状况,结合2和3增加虚拟机参数:
-XX:+ExplicitGCInvokesConcurrentAndUnloadsClasses -Dsun.rmi.dgc.client.gcInterval=36000000 -Dsun.rmi.dgc.server.gcInterval=36000000
考虑使用ExplicitGCInvokesConcurrentAndUnloadsClasses而不是ExplicitGCInvokesConcurrent,担心有通过反射等方式加载的类之后并未被使用,还有通过maven传递依赖过来的jar包太多,有很多也许运行时并未用到,能通过垃圾回收会清理持久代中不再使用的classes。如果之后发现有运行时类找不到的错误,则再改回ExplicitGCInvokesConcurrent。10小时触发一次(这个时间设置需要观察堆内存的状态变化)。-Dsun.rmi.dgc.client.gcInterval=36000000这个其实可以不配的,服务器默认都是配置-server的。
之所以不用1方案,屏蔽System.gc()还是有风险的。
参考文章:JVM调优的"标准参数"的各种陷阱
参考源:http://www.51testing.com/html/10/367410-858164.html
引发的原因是由于使用了RMI,会自动1小时调用1次system.gc()。
大多数的应用虽然配置了CMS gc方式,但是如果没有使用-XX:+ExplicitGCInvokesConcurrent,则会出现显示调用system.gc(),且不会进行 CMS的FGC,带来的影响是造成tps的波动(fgc停机时间越长,则波动会越大)。
收集各方的意见后,总结针对此类问题的解决方法如下:
1、增加参数 -XX:+DisableExplicitGC
该方法System.gc()的调用就会变成一个空调用。但是该方法不适用在大量使用NIO的direct memory,经常、反复的申请DirectByteBuffer的应用中使用,会造成“java.lang.OutOfMemoryError:
Direct buffer memory ”。该方法需根据应用具体情况而定。
2、增加参数 -Dsun.rmi.dgc.client.gcInterval=3600000 -Dsun.rmi.dgc.server.gcInterval=3600000
其中3600000即为定时触发的时间间隔设置,单位是毫秒,可适当延长触发FGC的定时时间间隔。
-Dsun.rmi.dgc.client.gcInterval=Long.MAX_VALUE -Dsun.rmi.dgc.server.gcInterval=Long.MAX_VALUE 则将fc时间间隔设为long型的最大值
3、增加参数 -XX:+ExplicitGCInvokesConcurrent 或者-XX:+ExplicitGCInvokesConcurrentAndUnloadsClasses
该方法可以指定System.gc()采用 CMS 算法,FGC时停机时间会变短,但是CMS GC次数不会变,仍然是1小时1次。
根据项目线上GC的内存状况,结合2和3增加虚拟机参数:
-XX:+ExplicitGCInvokesConcurrentAndUnloadsClasses -Dsun.rmi.dgc.client.gcInterval=36000000 -Dsun.rmi.dgc.server.gcInterval=36000000
考虑使用ExplicitGCInvokesConcurrentAndUnloadsClasses而不是ExplicitGCInvokesConcurrent,担心有通过反射等方式加载的类之后并未被使用,还有通过maven传递依赖过来的jar包太多,有很多也许运行时并未用到,能通过垃圾回收会清理持久代中不再使用的classes。如果之后发现有运行时类找不到的错误,则再改回ExplicitGCInvokesConcurrent。10小时触发一次(这个时间设置需要观察堆内存的状态变化)。-Dsun.rmi.dgc.client.gcInterval=36000000这个其实可以不配的,服务器默认都是配置-server的。
之所以不用1方案,屏蔽System.gc()还是有风险的。
参考文章:JVM调优的"标准参数"的各种陷阱
相关文章推荐
- java对世界各个时区(TimeZone)的通用转换处理方法(转载)
- java-注解annotation
- java-模拟tomcat服务器
- java-用HttpURLConnection发送Http请求.
- java-WEB中的监听器Lisener
- Android IPC进程间通讯机制
- Android Native 绘图方法
- Android java 与 javascript互访(相互调用)的方法例子
- 介绍一款信息管理系统的开源框架---jeecg
- 聚类算法之kmeans算法java版本
- java实现 PageRank算法
- PropertyChangeListener简单理解
- c++11 + SDL2 + ffmpeg +OpenAL + java = Android播放器
- 插入排序
- 冒泡排序
- 堆排序
- 快速排序
- 二叉查找树