Tomcat JSP请求消耗全部堆空间

4
我正在尝试解决我们Tomcat Java Web应用程序中的内存泄漏问题,认为当我对其中一个JSP进行重复请求时找到了它。然而,在将其简化为单个空JSP并将其放入运行在jdk1.6上的Tomcat 6.0.37实例中后,我仍然看到相同的情况。
我使用最大堆大小(-Xmx)256m启动Tomcat,并且在我的测试类中进行约282,000次请求后,堆空间将耗尽。
为了进行比较,我还创建了一个HttpServlet,该HttpServlet执行与JSP相同的操作,并修改了我的测试客户端以调用该HttpServlet,这样就可以在不耗尽内存的情况下运行整天。
我已经开始尝试分析堆以弄清楚发生了什么,但没有真正进展。那么,到底是怎么回事?
<%@ 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个回答

5
JSP请求会隐式地创建HTTP会话。如果您没有在HTTP客户端中维护HTTP会话,则每个请求都会创建一个全新的HTTP会话。这些会话默认的过期时间为30分钟。显然,所有这些请求都是在30分钟内发出的。
当您在servlet方法中执行request.getSession()时,您将面临完全相同的问题。
为了“解决”这个“问题”(在现实世界中不太可能发生;在裸机Tomcat实例上有282K并发HTTP会话则非常可观),可以禁用JSP中的隐式创建HTTP会话:
<%@page session="false">

或者告诉客户端通过以下行在while循环之前维护cookie以重用相同的HTTP会话:
CookieHandler.setDefault(new CookieManager(null, CookiePolicy.ACCEPT_ALL));

另一种方法是减少会话超时时间,以便在服务器导致堆溢出之前有机会清除它们,例如在web.xml中将其设置为5分钟:

<session-config>
    <session-timeout>5</session-timeout>
</session-config>

您可以实现一个 HttpSessionListener 来跟踪 HTTP session 的创建和销毁。

啊,那就有道理了。我看到我的堆中大约有与请求数量相同的“StandardSession”对象。而且你是对的,这不是“真实世界问题”,但理解这一点可以帮助我调整我的测试,以便找到实际的问题。 - schmimd04
不用谢。使用分析器可能更有帮助,可以找到实际的问题。 - BalusC

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接