org.springframework.web.servlet.view.InternalResourceViewResolver 内存泄露问题
2015-05-31 12:29
716 查看
Spring使用 org.springframework.web.servlet.view.InternalResourceViewResolver 内存泄露问题
通过
Eclipse Memory Analyzer (http://www.eclipse.org/mat/)分析工具如下,堆内存中50.51%
是由InternalResourceViewResolver 产生的。
我当前使用的Spring版本是:Spring 3.1.1.RELEASE
One instance of "org.springframework.web.servlet.view.InternalResourceViewResolver" loaded by"org.apache.catalina.loader.WebappClassLoader @ 0x6e0024ca0" occupies2,342,803,136 (50.51%) bytes.
The memory is accumulated in one instance of"java.util.HashMap$Entry[]" loaded by"<system class loader>".
Keywords
org.springframework.web.servlet.view.InternalResourceViewResolver
java.util.HashMap$Entry[]
org.apache.catalina.loader.WebappClassLoader @ 0x6e0024ca0
在经过对线上的服务监控,发现系统发生了很多次的full gc,为什么频繁的Full GC不能回收掉的呢;原因是大量存活对象对HashMap持有强引用关系导致的。
JVM内存对象回收策略是经过GC ROOT可达性分析,当一个对象经过GC Root 不可达时,说明这个对象已经dead,下次就就可以被回收掉。
接下来我们从代码中分析下,看是什么原因导致的。
#我想做JAVA的同学,以下代码是不是感觉很熟悉,单从这方法看是不是觉得没有问题.....
那么我们在看下Spring对这个返回重定向的处理方式吧
在InternalResourceViewResolver的父类AbstractCachingViewResolver
在这里Spring 使用viewName+locale 作为Cache key 将创建的View ,Cache到HashMap了,避免每次重新创建View。以下就是Spring viewCache 实例对象源码
通过
Eclipse Memory Analyzer (http://www.eclipse.org/mat/)分析工具如下,堆内存中50.51%
是由InternalResourceViewResolver 产生的。
我当前使用的Spring版本是:Spring 3.1.1.RELEASE
One instance of "org.springframework.web.servlet.view.InternalResourceViewResolver" loaded by"org.apache.catalina.loader.WebappClassLoader @ 0x6e0024ca0" occupies2,342,803,136 (50.51%) bytes.
The memory is accumulated in one instance of"java.util.HashMap$Entry[]" loaded by"<system class loader>".
Keywords
org.springframework.web.servlet.view.InternalResourceViewResolver
java.util.HashMap$Entry[]
org.apache.catalina.loader.WebappClassLoader @ 0x6e0024ca0
在经过对线上的服务监控,发现系统发生了很多次的full gc,为什么频繁的Full GC不能回收掉的呢;原因是大量存活对象对HashMap持有强引用关系导致的。
JVM内存对象回收策略是经过GC ROOT可达性分析,当一个对象经过GC Root 不可达时,说明这个对象已经dead,下次就就可以被回收掉。
接下来我们从代码中分析下,看是什么原因导致的。
#我想做JAVA的同学,以下代码是不是感觉很熟悉,单从这方法看是不是觉得没有问题.....
@RequestMapping(value = "/index.do",params="userId") public ModelAndView index(String userId,ModelAndView mv) { // TODO 业务处理... mv.setViewName("redirect:/your_uri.do?userId="+userId); return mv; }
那么我们在看下Spring对这个返回重定向的处理方式吧
在InternalResourceViewResolver的父类AbstractCachingViewResolver
public View resolveViewName(String viewName, Locale locale) throws Exception { if (!isCache()) { return createView(viewName, locale); } else { Object cacheKey = getCacheKey(viewName, locale); synchronized (this.viewCache) { View view = this.viewCache.get(cacheKey); if (view == null && (!this.cacheUnresolved || !this.viewCache.containsKey(cacheKey))) { // Ask the subclass to create the View object. view = createView(viewName, locale); if (view != null || this.cacheUnresolved) { this.viewCache.put(cacheKey, view); if (logger.isTraceEnabled()) { logger.trace("Cached view [" + cacheKey + "]"); } } } return view; } } }
在这里Spring 使用viewName+locale 作为Cache key 将创建的View ,Cache到HashMap了,避免每次重新创建View。以下就是Spring viewCache 实例对象源码
/** Map from view key to View instance */ private final Map<Object, View> viewCache = new HashMap<Object, View>();由于我们return ModelAndView 对象的URI 中存在动态参数,每个用户返回的URI都不一样,所有导致Cache Key无法命中,进而创建大量View ,Cache到viewCache.
"redirect:/your_uri.do?userId="+userId如果需要使用Spring重定向建议采用RedirectView 处理,例如:
@RequestMapping(value = "/index.do", params = "userId") public RedirectView index(RedirectView mv,String userId) { // TODO 业务处理 UriComponentsBuilder builder = UriComponentsBuilder.fromPath("/xxx.do"); builder.queryParam("userID", userId); mv.setUrl(builder.build().encode().toUriString()); return mv; }
相关文章推荐
- javaweb-servlet开发
- Java中浮点数的精度问题 【转】
- java中用jsoup抓取网页源码,并批量下载图片
- java float double精度为什么会丢失?浅谈java的浮点数精度问题 【转】
- Selection sort的java语言实现
- LeakCanary Eclipse
- java 设计模式-----适配器模式
- java个人学习笔记:switch
- JAVA -- 线程sleep()和yield()、join()方法区别
- JAVA -- 线程sleep()和yield()、join()方法区别
- JAVA -- 线程sleep()和yield()、join()方法区别
- Maven的包依赖冲突可引发java.lang.IncompatibleClassChangeError错误
- myeclipse 8.5 序列号
- Java Reflection - Dynamic Class Loading and Reloading
- Java Reflection - Arrays
- Java Reflection - Generics
- Java Reflection - Dynamic Proxies
- Java Reflection - Annotations
- Java Reflection - Getters and Setters
- Java Reflection - Private Fields and Methods