【问题标题】:GWT Java - Memory Leak - ServletContextListener issueGWT Java - 内存泄漏 - ServletContextListener 问题
【发布时间】:2014-05-12 23:31:51
【问题描述】:

我的朋友在服务器上设置了我的应用程序(使用 Eclipse Kepler Service Release 2、GWT 2.6.0、Tomcat 6 开发 - 下一个版本,我正在测试的将是 Tomcat 7),我收到了这个来自他的消息: “当我在 Apache Tomcat 中运行诊断程序时收到此消息时,您能否检查应用程序中是否存在内存泄漏: 以下 Web 应用程序已停止(重新加载、取消部署),但它们的

以前运行的类仍然加载到内存中,从而导致内存 泄漏(使用分析器确认): /awardtracker"

所以我调查并发现我需要使用 ServletContextListener 可以清理那些引用。所以我找到了一个例子;请看下文。

我有两个问题。

首先,我应该在 "context.setAttribute("TEST", "TEST_VALUE");" 行中添加什么代替“TEST”和“TEST_VALUE”?

其次,当我运行应用程序时,我收到消息“上下文已创建”,但是当我关闭应用程序时没有收到消息“上下文已销毁”(我只需关闭浏览器即可)。如何销毁上下文?

package org.AwardTracker.server;

import javax.servlet.ServletContext;
import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;
import javax.servlet.annotation.WebServlet;

/**
 * Servlet implementation class ServletContextImpl
 */
@WebServlet("/ServletContextImpl")

public class ServletContextImpl implements ServletContextListener{ 

 ServletContext context; 

 public void contextInitialized(ServletContextEvent contextEvent) { 

     System.out.println("Context Created"); 

     context = contextEvent.getServletContext(); 

     // set variable to servlet context 

     context.setAttribute("TEST", "TEST_VALUE"); 

 } 

 public void contextDestroyed(ServletContextEvent contextEvent) { 

     context = contextEvent.getServletContext(); 

     System.out.println("Context Destroyed"); 

 }

}

和xml:

<listener> 
     <listener-class> 
         org.AwardTracker.server.ServletContextImpl 
     </listener-class> 
</listener>

【问题讨论】:

  • 题外话:你对@WebServlet的用法是错误的。
  • 您必须提供更多日志。如果由 Servlet 容器管理,此类中的任何内容都不会导致内存泄漏。
  • 嗨 Sotirios,我已将“@WebServlet”更改为“@WebListener”。谢谢你。我还向我的朋友索要服务器日志的副本。我会尽快发布。问候,格林
  • 嗨,Sotirios,我已经和我的朋友谈过了,他没有任何进一步的信息。我会研究我能跑什么。问候,格林。
  • 嗨 Sotirios,我现在已经安装了 JProfiler。有很多选项(实时内存、堆遍历器、CPU 视图、线程、监视器和锁、遥测、数据库、JEE 和探测器)。我需要记录哪些?问候,格林。

标签: java eclipse tomcat gwt memory-leaks


【解决方案1】:

您不需要将ServletContext 作为ServletContextImpl 类的实例成员。

当您需要它时,只需从ServletContextEvent 访问它,因为您已经在下面的代码中这样做了:

context = contextEvent.getServletContext(); 

在应用程序中,您可以通过HttpSession#getServletContext() 访问ServletContext

ServletContext context = request.getSession().getServletContext();

欲了解更多信息,请查看How to get the Servlet Context from ServletRequest in Servlet 2.5?


其次,当我运行应用程序时,我收到消息“上下文已创建”,但是当我关闭应用程序时没有收到消息“上下文已销毁”(我只需关闭浏览器即可)。强>

仅仅关闭浏览器并不会破坏上下文。应用程序上下文不仅用于每个客户端,而且在应用程序范围内使用。您可以为每个客户端使用一个 HTTP 会话。

当服务器以标准方式正常停止时,方法contextDestroyed()将被调用。

更多信息请看下面的帖子


如何销毁上下文?

理想情况下,ServletContext 会在应用服务器(Tomcat 或 JBoss)关闭或有时甚至重新启动时被销毁。

请查看以下链接:

【讨论】:

  • 嗨,Braj,非常感谢。首先,从我所有的阅读来看,我仍然认为我对 ServeletContext 的理解存在巨大的漏洞。我的理解是我添加它以帮助防止内存泄漏。我现在理解,无论对错,它都以服务器开始和结束,并且在应用程序的生命周期内不需要与它进行任何交互(即,除了在 serverlet 中已经完成的调用之外,代码中没有调用。
  • 关闭服务器后,哪些类型的对象仍在内存中? ServeletContext 用于在应用程序启动或建立数据库连接或在contextInitialized() 方法中执行任何预热活动时从 web.xml 中读取一些 init 参数和读取属性文件。同理可以在contextDestroyed()中释放数据库连接或者其他外部获取的资源。
  • 其次,您的问题促使我朝着正确的方向前进。最初我认为“我关闭了应用程序(我通过简单地关闭浏览器来做到这一点)”。事后看来,并回顾第一点,这是不正确的。当我停止服务器时,应用程序完成。当我停止服务器时,会显示“上下文已破坏”消息。
  • 所以这只是留下与“context.setAttribute("TEST", "TEST_VALUE");" 相关的问题。这是必需的吗?如果是,当前属性是否正确,或者我应该将它们设置为其他属性吗?再次非常感谢您的帮助。问候,格林。
  • 您正在应用程序上下文中设置一个键值,该值将在应用程序的生命周期内一直存在,直到上下文被销毁。如果您想释放内存,则可以在需要且根本不需要时将其设置为null。现在它取决于价值。值有多复杂?或多大?
猜你喜欢
  • 2015-12-28
  • 2021-03-28
  • 1970-01-01
  • 2016-07-28
相关资源
最近更新 更多