JAVA内存泄露分析及解决
一,问题产生
项目采用Tomcat6.0为服务器,数据库为mysql5.1,数据库持久层为hibernate3.0,以springMVC3.0为框架,项目开发完成后,上线前夕进行稳定性拷机,测试数据为插入4条/S,更新4条/S,访问300次/S,前期运行速度顺畅,三天后就开始运行缓慢,访问量达到1500W次后以抛出Java heap space结束.
二.问题分析
1.前期分析为连接池内存溢出,期间优化了连接池参数,调整了tomcat线程参数,替换数据库连接池,问题依旧
2.看来问题不是简单的参数配置,需要进行一点深入的研究分析了,在和同事研究了一些资料后,对JAVA的垃圾收集机制有了一定的了解,JVM的内存模型分为新生代和老生代,JDK本身提供了一个监视工具jconsole.exe,进入bin文件夹打开后,选择连接--tomcat--内存,可以开始监视JVM内存回收情况,通过一段时间的监视后,发现了老生代的内存回收存在异常.
从上图可以看出,每次回收的内存都比上一次少,可以判断老生代的内存发生了泄露.
3.虽然知道了存在内存泄露,但是无法判断是哪里发生了泄露,为此我们需要把堆(dump)导出来进行分析,JDK也提供了导出工具jvisualvm.exe,启动后右键点击线程--堆Dump,可以导出Dump文件.
4.使用MAT(MemoryAnalyzer)分析Dump文件,该工具的下载地址为:http://www.eclipse.org/mat,可以下载离线版,也可以集成到eclipse,使用很方便.打开该工具导入Dump文件,稍等一会,就可以得出MAT提供的分析报告
MAT指出了该Dump中一个HashMap的实例发生了内存泄露,占用了JVM819M的内存,继续点击Details可以得到更详细的信息
这个detail比较详细的指出了问题所在,一个叫viewCache的hashMap实例占用共859M内存,虽然每个实例只有几百字节,但是一共产生了134W个实例.
5.分析出这个问题点,接下去就是排查代码问题了,排查代码得知该项目使用springMVC,其中viewCache是spring中使用的一个视图缓存,在项目中如一个处理视图跳转的代码:
LinkedList list = this.getPathParam(mvValue);
for (int i = 0; i < list.size(); i++) {
String paramName = (String) list.get(i);
String paramValue = null;
paramValue = RequestUtils.getParamString(map, paramName);
paramValue = paramValue == null ? "" : paramValue;
mvValue = StringUtils.replace(mvValue, "#" + paramName+"#", paramValue);
}
return new ModelAndView(mvValue);
由于paramValue每次都是动态生成的uuid,造成了每次的mvvalue都不同,这样每次都会生成一个不一样的视图,这样的视图累积到100多W个的时候,终于把tomcat撑暴了.百度了一下,果然也已经有人注意到了这个问题:http://jackyrong.iteye.com/blog/1744342.
6.知道了问题所在后,就可以修改代码了,我们需要将ModelAndView的视图名称固定,动态参数可以通过ModelAndView提供的addObject方法传入,修改后的代码如下:
//判断如果视图名称包含"snms_result.jsp",则将视图名称返回值统一,解决因动态产生视图名称过多产生的内存泄露问题, by feitianbubu 2013年5月27日 11:21:31
ModelAndView mv=new ModelAndView(mvValue);
LinkedList list = this.getPathParam(mvValue);
for (int i = 0; i < list.size(); i++) {
String paramName = (String) list.get(i);
String paramValue = null;
paramValue = RequestUtils.getParamString(map, paramName);
paramValue = paramValue == null ? "" : paramValue;
mv.addObject("id", ",'"+paramValue+"'");
}
return mv;
7. 代码commit SVN,发布拷机,观察内存回收情况
(为了更快模拟环境采用1000次/S插入数据和1000次/S读取数据,所以GC会比较频繁)
可以看出老生代内存得到有效回收,内存泄露的问题得到解决
JAVA内存泄露分析及解决的更多相关文章
- JAVA简单内存泄露分析及解决
一.问题产生 项目采用Tomcat6.0为服务器,数据库为mysql5.1,数据库持久层为hibernate3.0,以springMVC3.0为框架,项目开发完成后,上线前夕进行稳定性拷机,测试 ...
- Java内存泄露分析和解决方案及Windows自带查看工具
Java内存泄漏是每个Java程序员都会遇到的问题,程序在本地运行一切正常,可是布署到远端就会出现内存无限制的增长,最后系统瘫痪,那么如何最快最好的检测程序的稳定性,防止系统崩盘,作者用自已的亲身经历 ...
- Android handler 内存泄露分析及解决方法
1. 什么是内存泄露? Java使用有向图机制,通过GC自动检查内存中的对象(什么时候检查由虚拟机决定),如果GC发现一个或一组对象为不可到达状态,则将该对象从内存中回收.也就是说,一个对象不被任何引 ...
- 使用Eclipse Memory Analyzer 进行JAVA内存泄露分析
一,安装 Eclipse Memory Analyzer 在Memory Analyzer的官网找到 update site的地址:
- 记一次Java的内存泄露分析
当前环境 jdk == 1.8 httpasyncclient == 4.1.3 代码地址 git 地址:https://github.com/jasonGeng88/java-network-pro ...
- java内存泄露的理解与解决(转)
Java内存管理机制 在C++语言中,如果需要动态分配一块内存,程序员需要负责这块内存的整个生命周期.从申请分配.到使用.再到最后的释放.这样的过程非常灵活,但是却十分繁琐,程序员很容易由于疏忽而忘记 ...
- Java 内存泄露的理解与解决过程
本文详细地介绍了Java内存管理的原理,以及内存泄露产生的原因,同时提供了一些列解决Java内存泄露的方案,希望对各位Java开发者有所帮助. Java内存管理机制 在C++ 语言中,如果需要动态分配 ...
- 【转】.. Android应用内存泄露分析、改善经验总结
原文网址:http://wetest.qq.com/lab/view/107.html?from=ads_test2_qqtips&sessionUserType=BFT.PARAMS.194 ...
- .Net内存泄露原因及解决办法
.Net内存泄露原因及解决办法 1. 什么是.Net内存泄露 (1).NET 应用程序中的内存 您大概已经知道,.NET 应用程序中要使用多种类型的内存,包括:堆栈.非托管堆和托管堆.这里我们需 ...
随机推荐
- jQuery(九):节点遍历
一.遍历子元素 children()方法可以用来获取元素的所有子元素,语法如下: 示例: <!DOCTYPE html> <html lang="en"> ...
- 微信小程序——修改data里面数组某一个值
比如我现在有个data数据如下: data: { playIndex: null, courseList: [{ videoId: '0', isPlaying: false, }, { videoI ...
- Navi.Soft31.阅读导航
Navi.Soft31.核心类库 Navi.Soft31.WinForm框架 Navi.Soft31.WebMVC框架 Navi.Soft31.微信WinForm框架 Navi.Soft31.Mobi ...
- sps和pps的简单理解记录
最近博客写出了日记的既视感... 使用RTP传输H264的时候,需要用到sdp协议描述,其中有两项:Sequence Parameter Sets (SPS) 和Picture Parameter S ...
- Python 内置方法new
class Dog(object): def __new__(self): print("i am new .") def __init__(self): print(" ...
- 自然语言交流系统 phxnet团队 创新实训 个人博客 (九)
情感倾向可认为是主体对某一客体主观存在的内心喜恶,内在评价的一种倾向.它由两个方面来衡量:一个情感倾向方向,一个是情感倾向度. 情感倾向方向也称为情感极性.在微博中,可以理解为用户对某客体表达自身观点 ...
- 《FPGA全程进阶---实战演练》第十一章 VGA五彩缤纷
1基础理论部分 VGA(video graphics array)即视频图形阵列,是IBM在1987年随PS/2一起推出的使用模拟信号的一种视频传输标准.VGA相比与现在的视频传输接口来说已经过时,不 ...
- Idea maven项目不能新建package和class的解决
如图,新建的maven项目不能新建package 这是因为Java是普通的文件夹,要设置为 现在就可以了
- C++ 把枚举变量的名称,直接当字符串使用方法 字符串化符号 #
#include <stdio.h> #include <typeinfo> #include <string> using namespace std; enum ...
- Mybatis接口注解
在上一章中,我们已经搭建了 myeclipse,mybatis,mysql 的开发环境,并且实现了 mybatis 的一个简单的查询.要注意的是,这种方式是用 SqlSession 实例来直接执行在U ...