Tomcat JSP请求占用了所有堆空间

时间:2013-10-03 18:53:40

标签: java jsp tomcat heap

我正在尝试在我们的Tomcat Java Web应用程序中发生内存泄漏,并且认为我在向其中一个JSP发出重复请求时发现了它。然而,在将其拆分为单个空的JSP后,将其放入在jdk1.6上运行的开箱即用的Tomcat 6.0.37实例中,我仍然看到同样的事情。

我正在启动Tomcat,最大堆大小(-Xmx)为256m,并且在我的测试类下面发出大约282,000个请求后,堆空间用完了。

为了进行比较,我还创建了一个HttpServlet,它与JSP完成相同的操作,并修改了我的测试客户端来调用它,这将在一整天内运行而不会耗尽内存。

我已经开始尝试分析堆来弄清楚这里发生了什么,但并没有真正到达任何地方。 Soooo,这里发生了什么?

测试JSP

<%@ page language="java" import="java.util.*" pageEncoding="ISO-8859-1"%>
<%@ page contentType="text/plain"%>
<% System.out.println("Page requested: " + new Date()); %>
This is a test response

Java测试客户端

public static void main(String[] args) throws Exception {
  int i=0;
  while(true) {
    java.net.URL url = new java.net.URL("http://localhost:8080/test.jsp");
    InputStream is = url.openStream();
    while(is.read() != -1) {
      //nothing, just read the stream
    }
    is.close();
    System.out.println("Requests made: " + i++);
  }
}

1 个答案:

答案 0 :(得分:5)

JSP请求隐式创建HTTP会话。您没有在HTTP客户端中维护HTTP会话,因此每次请求都会创建一个全新的HTTP会话。这些会话的到期时间默认为30分钟。显然所有这些请求都是在30分钟内被解雇的。

当您在servlet方法中执行request.getSession()时,您将在servlet中遇到完全相同的问题。

为了“修复”这个“问题”(在现实世界中不太可能发生;另一方面,在准系统Tomcat实例上282K并发HTTP会话非常可观),要么在JSP中禁用隐式创建HTTP会话:

<%@page session="false">

或告诉客户端重复使用相同的HTTP会话,方法是在 while循环之前通过以下行维护cookie:

CookieHandler.setDefault(new CookieManager(null, CookiePolicy.ACCEPT_ALL));

另一种方法是减少会话超时,以便服务器有机会在它导致堆溢出之前收获它们,例如:在web.xml

中按照以下5分钟
<session-config>
    <session-timeout>5</session-timeout>
</session-config>

您可以实施HttpSessionListener来跟踪HTTP会话的创建并销毁。