23
回答
Spring内存溢出问题
注册华为云得mate10,2.9折抢先购!>>>   
  各位看官,我先描述下问题背景:
    我的应用运行了两年多,期间内存溢出每个星期2次左右,内存溢出后内存又恢复正常,内存溢出不影响        正常使用,内存溢出不宕机,java进程也不变,Tomcat没有重启。
    因为不影响使用,也就一直没有管,但是近期发现CPU使用率特别高,不管都不行了。
    排查方法:http://www.blogjava.net/hankchen/archive/2012/08/09/377735.html
    很好用,定位了问题代码也:
   
public String getActionName(HttpServletRequest request) {
String _actionName = null;
if ( null != request && null != this.methodNameResolver ) {
try {
_actionName = this.methodNameResolver.getHandlerMethodName(request);
} catch (NoSuchRequestHandlingMethodException e) {
logger.error("获取请求方法名称时失败!", e);
}
}
return _actionName;
}
       问题出在第5行代码,查看Spring源码发现,是这句代码:
String servletPath = (String) request.getAttribute(WebUtils.INCLUDE_SERVLET_PATH_ATTRIBUTE);
     我测试了下,发现从request.getAttribute中取数据就会特别慢,CPU就高,然后我写了测试代码
int count = 0;
Enumeration  em = request.getAttributeNames();
while(em.hasMoreElements()){
count++;
String name = em.nextElement().toString();
logger.info("name:"+name+",value:"+request.getAttribute(name).toString());
System.out.println("name:"+name+",value:"+request.getAttribute(name).toString());
}
if(count>20){
logger.info("====================================================count:"+count+",URI:"+uri);
}
    结果第3行一直占用CPU,我纠结了,什么情况?
    以上几段代码描述的是问题一,CPU占用高。
    我换了个写法,暂时绕开了这个问题,但是没有解决,求高人指点,代码如下:
public String getActionName(HttpServletRequest request) {
String _actionName = null;
if(null != request){
String uri = request.getRequestURI();
_actionName = uri.substring(uri.lastIndexOf("/")+1,uri.indexOf(".do")); 
}
return _actionName;
}
     在这里主要是请教下内存溢出问题,内存溢出是使用ibm memory analyzer工具分析的,分析了五六个内存溢出文件,都是同一个问题,最多的对象是java.lang.Object[293479271] @ 0x708309d20 是个Object数组,数组中存放的都是org.springframework.web.servlet.DispatcherServlet.LOCALE_RESOLVER 或者 org.springframework.web.servlet.DispatcherServlet.THEME_RESOLVER。全部是spring request Attribute 中的某个key值,每次溢出都是包含几百万个key(某一个key,重复的)

  

  Object数组中存放的数据见下图:


     开始以为是存在内存泄漏,我输出gc日志,查看内存很平稳,只是忽然下就内存溢出了,而且溢出时间没有规律,非高峰期,有时都是凌晨3点、5点,根本很少人访问。用gcviewer工具分析gc日志,截图如下:

      最高的那根线就是内存溢出了,之后自己就恢复了。
      分析了好几天,也没有思路了,但是总是觉得cpu高和内存溢出是同一个问题导致的,内存溢出时,内存中存放的都是spring request Attribute 中的某个key值,而cpu高,是从request Attribute中取值。难道是Attribute中存放了几百万个key?

      麻烦大家帮忙看看,给个思路也好啊,多谢了!

补充:

造成内存溢出的堆栈

举报
周勇god
发帖于4年前 23回/3K+阅
共有23个答案 最后回答: 4年前
request.getAttribute是servlet的api了,如果attribute的数量不多,那说明已经不是spring的问题了。可以检查一下servlet相关包,另外,怀疑晚上有人攻击你的网站,可以检查一下你的web日志。

引用来自“huan”的答案

request.getAttribute是servlet的api了,如果attribute的数量不多,那说明已经不是spring的问题了。可以检查一下servlet相关包,另外,怀疑晚上有人攻击你的网站,可以检查一下你的web日志。

三台服务器的内存溢出时间如下:

-rw------- 1 root root       3767277860 Dec 16 13:07 java_pid25024.hprof
-rw------- 1 root root       3866787894 Dec  6 14:11 java_pid4202.hprof
-rw------- 1 root root       3776245966 Dec  5 05:47 java_pid14670.hprof
-rw------- 1 root root       3838480211 Dec  3 23:08 java_pid28773.hprof
-rw------- 1 root root       3748418732 Dec  3 06:28 java_pid12718.hprof


-rw------- 1 root root       3834388780 Dec 16 13:56 java_pid8519.hprof
-rw------- 1 root root       3787603312 Dec 13 22:45 java_pid1241.hprof
-rw------- 1 root root       3786757154 Dec  7 09:19 java_pid32593.hprof
-rw------- 1 root root       3846078343 Dec  4 13:51 java_pid26359.hprof


-rw------- 1 root root 3831551786 Dec 16 16:32 java_pid27189.hprof
-rw------- 1 root root 3782997045 Dec 13 22:42 java_pid32300.hprof
-rw------- 1 root root  296706311 Dec 12 18:21 java_pid21597.hprof
-rw------- 1 root root 3896330384 Dec  6 14:35 java_pid31877.hprof
-rw------- 1 root root 3799366187 Dec  4 03:45 java_pid31466.hprof
-rw------- 1 root root 3911132652 Dec  1 10:14 java_pid13423.hprof

看这时间节点,不像被人攻击,而且检查了nginx日志,没有发现异常。

引用来自“dever2011”的答案

貌似是的,是不是遭受攻击了

我们前端有6台nginx服务器,如果被攻击,nginx日志应该可以看出点猫腻吧?

请教下如何排查,是否被攻击了,我们检查6台nginx的日志,也没有发现什么异常

引用来自“周勇god”的答案

引用来自“huan”的答案

request.getAttribute是servlet的api了,如果attribute的数量不多,那说明已经不是spring的问题了。可以检查一下servlet相关包,另外,怀疑晚上有人攻击你的网站,可以检查一下你的web日志。

三台服务器的内存溢出时间如下:

-rw------- 1 root root       3767277860 Dec 16 13:07 java_pid25024.hprof
-rw------- 1 root root       3866787894 Dec  6 14:11 java_pid4202.hprof
-rw------- 1 root root       3776245966 Dec  5 05:47 java_pid14670.hprof
-rw------- 1 root root       3838480211 Dec  3 23:08 java_pid28773.hprof
-rw------- 1 root root       3748418732 Dec  3 06:28 java_pid12718.hprof


-rw------- 1 root root       3834388780 Dec 16 13:56 java_pid8519.hprof
-rw------- 1 root root       3787603312 Dec 13 22:45 java_pid1241.hprof
-rw------- 1 root root       3786757154 Dec  7 09:19 java_pid32593.hprof
-rw------- 1 root root       3846078343 Dec  4 13:51 java_pid26359.hprof


-rw------- 1 root root 3831551786 Dec 16 16:32 java_pid27189.hprof
-rw------- 1 root root 3782997045 Dec 13 22:42 java_pid32300.hprof
-rw------- 1 root root  296706311 Dec 12 18:21 java_pid21597.hprof
-rw------- 1 root root 3896330384 Dec  6 14:35 java_pid31877.hprof
-rw------- 1 root root 3799366187 Dec  4 03:45 java_pid31466.hprof
-rw------- 1 root root 3911132652 Dec  1 10:14 java_pid13423.hprof

看这时间节点,不像被人攻击,而且检查了nginx日志,没有发现异常。

可否共享一两个hprof文件,大家分析分析
--- 共有 1 条评论 ---
周勇god内存分析我上面有贴图 4年前 回复
顶部