一、场景描述
上周开始系统在业务高峰期一直收到Full gc报警,监控显示fgc频繁,下图是监控图,左边红框是优化前效果,右边是优化后,优化后fgc基本为0
二、原因查找
1.查看gc日志,发现old区fgc后大小没有变化,如下图:
2.去线上dump内存看是什么对象,用memory analyzer分析,Retained Size竟然有2.4G,全是sun.awt.SunToolkit这个对象,其实到这一步已经可以确定是什么问题了,只是自己对系统不是很熟悉,导致定位具体的问题代码花了一些时间
三、原因分析
系统中有一个调用频繁的接口会调用下面这个方法,目的是获取图片的宽高信息,但是Image这个对象用完不会自动释放,需要手动调用 flush()方法;以前没有调用这个方法,就导致一有请求就会有大对象进入old区,在业务高峰期old区一会就被打满,所以一直进行fgc
public static Image getImage(String path) {
ImageIcon icon = new ImageIcon(path);
Image img = icon.getImage();
return img;
}
四、解决办法
其实不管是用Image还是BufferedImage,读取图片的宽高不用把图片全部加载到内存,在图片的宽高信息其实是存储在文件头中的,只 要按不同的格式读取文件的头信息就可以拿到宽高信息
使用ImageReader代码如下
Iterator readers = ImageIO.getImageReadersByFormatName(StringUtil.getFileSuffix(filePath));
ImageReader reader = (ImageReader)readers.next();
iis = ImageIO.createImageInputStream(is);
reader.setInput(iis, true);
return Pair.of(reader.getWidth(0),reader.getHeight(0));
相关 [系统 full gc] 推荐:
触发Full GC执行的情况
- - Web前端 - ITeye博客Full GC是否真的存在
- - Java译站利用Arena Allocation避免HBase触发Full GC
- Adam - 淘宝JAVA中间件团队博客FULL GC有可能导致JVM暂停1分钟以上吗?
- - 高级语言虚拟机Tomcat的JreMemoryLeakPreventionListener监听周期性频繁执行full gc
- -Full Circle 51期发布
- PT - Wow! Ubuntu初级分代GC
- - C++博客-首页原创精华区GC 日志分析
- - 码蜂笔记迟到:Full Circle 中文版45期
- L - LinuxTOY迟到的社区杂志 Full Circle 发布 45 期中文版. 在这一期杂志中,我们给您带来了以下内容:. 决胜命令行 —— Conky 第二部分. How-To : Python 编程 , 虚拟化 : Debian Xen 以及 使用 m23 安装 Ubuntu. Linux 实验室 —— 多重启动U盘.
jps -v xxx 显示xxx进程的各项jvm参数
jstat -gcutil pid xxx
显示xxx的堆分配情况以及垃圾回收次数时间
jstack 用法
Top 一下看一下cpu最高进程
Shift+h 查看线程
或者 top -p pid -H 查看该进程下的所有线程
找到最高的线程 vmid
jstack pid | grep -A 10 vmid(线程id的16进制其中字母要小写)
jmap -histo:live pid 强制进行fullgc 查看实例数
ps -eLo pid,lwp,pcpu | grep 6124 |sort -rnk 3
Top -H -p 6124(进程id)
注意:
内存溢出的影响周期和JVM内存设置大小有关系,分配得越小,越容易出现。