jvm频繁GC问题查找记录

来源:互联网 发布:聊天软件默默 编辑:程序博客网 时间:2024/05/16 01:38

下面是我在公司对一个不熟悉的项目在生产环境下JVM内存异常的处理思路(回复领导的邮件)

在3个月后终于找到具体的原因,由于系统频繁且重复的图片压缩造成的(每次压缩需要1秒钟左右,占用内存为图片大小*6左右),跟我之前的判断完全一致。


是的,是在JVM中进行配置;配置的大小没有具体的评判标准,需要根据具体环境进行调整,受到新建对象大小,频率,对象生命周期长短,堆内存总大小等的影响。

老年代与新生代内存大小的比例可由JVMNewRatio参数配置:NewRatio =老年代内存大小/新生代内存大小,在默认的情况下,NewRatio=2

从我们的日志能够看到,老年代大小是1G,那么默认情况下NewRatio的大小就是512M

21日的日志能够看到,大概每隔10-50秒会发生一次有效的GC(回收了比较多的内存),但14日的日志,基本每秒都在发生有效GC,这些现象表明,一些生命周期很短的对象从新生代进入了老年代,从而触发了full gc,而这些对象本来应该在新生代进行短暂存在后,就会被及时地被清除(新生代的GCfull GC代价小很多),而不应该进入老年代。

发生这种问题的原因,一般会是由于以下一些原因引起:

1.      新生代太小,使得一些新对象无法再新生代创建,而直接进入了老年代。比如新生代总内存大小只有10M,而业务上经常创建一些20M的存活1秒的临时对象,这些对象就只能创建在老年代。

2.      新对象创建非常频繁,将新生代充满,只能使用老年代的对象。比如新对象的存活周期为1秒,新生代配置了500M,但业务上有些阶段在1秒内频繁创建了1G对象数据,那么其中大部分数据都进入了老年代,但1秒后,这些数据马上又变成了老年代里面的垃圾。

3.      新生代内存分为三个区域:Edensurvivor1survivor2,有时由于这三个区域的比例划分也会使得一些对象过早地进入了老年代。这个比例划分由SurvivorRatio参数设置,SurvivorRatio=Eden/survivor,默认为8

4.      MaxTenuringThreshold参数也会使一些本应该在新生代回收的对象进入老年代(默认是15)。

 

在我们这个问题里面,我觉得需要根据新对象创建的频率,绝大部分短生命周期的周期时间等来决定这些参数来尝试。

0 0
原创粉丝点击