JAVA memory leak analysis and solution

1. The problem-generating
    project uses Tomcat6.0 as the server, mysql5.1 as the database, hibernate3.0 as the database persistence layer, and springMVC3.0 as the framework. 4 records/S, 4 updates/S, access 300 times/S, the running speed is smooth in the early stage, but it starts to run slowly after three days, and ends with throwing Java heap space after the access volume reaches 1500W times.
2. Problem analysis
    1. Early stage The analysis is that the connection pool memory overflows. During this period, the connection pool parameters are optimized, the tomcat thread parameters are adjusted, and the database connection pool is replaced. The problem is still
    2. It seems that the problem is not a simple parameter configuration, and a little in-depth research and analysis is required. After studying some information, I have a certain understanding of JAVA's garbage collection mechanism. The memory model of JVM is divided into new generation and old generation. JDK itself provides a monitoring tool jconsole.exe. After entering the bin folder to open, select the connection --tomcat--memory, you can start to monitor the JVM memory recovery. After a period of monitoring, it is found that there is an abnormality in the memory recovery of the old generation.


 
As can be seen from the above figure, the memory recovered each time is less than the last time. It can be judged that the memory of the old generation has leaked.
    3. Although we know that there is a memory leak, we cannot judge where the leak occurred. For this reason, we need to export the heap (dump) for analysis. JDK also provides an export tool jvisualvm. exe, right-click thread-heap Dump after startup, you can export the Dump file.
    4. Use MAT (MemoryAnalyzer) to analyze the Dump file. The download address of the tool is: http://www.eclipse.org/mat , you can download offline It can also be integrated into eclipse, which is very convenient to use. Open the tool and import the Dump file, and after a while, you can get the analysis report provided by MAT


 
MAT pointed out that a HashMap instance in the Dump had a memory leak, occupying JVM819M of memory. Continue to click Details to get more detailed information. This detail points out the problem in detail. A hashMap instance called viewCache occupies a total of 859M of memory. , although each instance is only a few hundred bytes, but a total of 134W instances are generated.     5. After analyzing this problem, the next step is to troubleshoot the code problem. The code check shows that the project uses springMVC, of ​​which viewCache is used in spring A view cache in the project, such as a code that handles view jumps: 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); 
 

 











Since paramValue is a dynamically generated uuid every time, the mvvalue is different every time, so a different view will be generated every time. When such views accumulate to more than 100 W, the tomcat is finally overwhelmed. Baidu, and sure enough, someone has noticed this problem: http://jackyrong.iteye.com/blog/1744342.
    6. After knowing the problem, you can modify the code. We need to fix the view name of ModelAndView, Dynamic parameters can be passed in through the addObject method provided by ModelAndView. The modified code is as follows:

       // Judge if the view name contains "snms_result.jsp", then unify the return value of the view name to solve the memory caused by too many dynamically generated view names Leaking issue, by feitianbubu 27 May 2013 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会比较频繁)
可以看出老生代内存得到有效回收,内存泄露的问题得到解决 

Guess you like

Origin http://10.200.1.11:23101/article/api/json?id=326983944&siteId=291194637