【问题标题】:How to hunt memory leaks in webapp?如何在 webapp 中寻找内存泄漏?
【发布时间】:2017-07-11 15:39:32
【问题描述】:

我的 Web 应用程序存在内存泄漏问题。应用程序在被少数人使用时会在大约 7 小时后耗尽内存。

这就是我的应用程序的工作方式:

  • 用户登陆登录页面,登录,成功登录用户 POJO 对象添加到会话映射中,如下所示: FacesContext.getCurrentInstance().getExternalContext().getSessionMap().put("user", user);
  • 在每个后续页面请求中,AuthFilter 都会检查会话映射中是否存在“用户”对象并允许进一步访问;
  • 我有 SessionScoped bean (LoggedUserBean) 保存用户信息(连同特权,在登录时初始化),因为它被非常频繁地访问。 LoggedUserBean 被注入到大多数 bean 中,也可以直接从 XHTML 页面访问。
  • 还有一些其他 SessionScoped bean 应该保持它们的状态。大多数 bean 都注入了​​ DAO 对象(@Named,默认为 @Dependent)。很少 bean 和所有 DAO 对象都注入了 DatabaseConnection 对象(@Named 与在构造函数中创建的数据源如下: dataSource = (DataSource) new InitialContext().lookup("java:comp/env/" + "jdbc/MyResName");)。
  • 用于验证动态创建的组件树的 Primefaces 对话框的 (@Named) 验证器很少:

<h:inputHidden value="true"> <f:validator binding="#{someValidator}"/> </h:inputHidden>

实现是这样的:

@Named
public class SomeValidator extends ValidatorCommon implements Validator {

    private final static Logger LOGGER = Logger.getLogger(SomeValidator.class);

    @Override
    public void validate(FacesContext fc, UIComponent uic, Object o) throws ValidatorException {...}
{...}

这是我的 context.xml:

<Resource auth="Container"
          driverClassName="org.sqlite.JDBC"
          maxTotal="1"
          maxIdle="1"
          minIdle="1"
          maxWaitMillis="5000"
          initialSize="1"
          name="jdbc/MyResName"
          type="javax.sql.DataSource"
          removeAbandonedOnBorrow="true"
          removeAbandonedTimeout="5"
          logAbandoned="true"
          validationQuery="SELECT 1"
          url="jdbc:sqlite:path/to/db/db.db">
</Resource>

我已经使用 VisualVM 创建了堆转储,MAT 显示了这个泄漏嫌疑人 (https://i.imgur.com/wGsnyt5.png):

据我所知,RequestScoped bean 是在每次请求/访问时创建的,而 SessionScoped 是从容器中检索特定会话的(或者如果它不存在则创建)所以即使我的豆子,这一切都应该可以正常工作。

这就是我真正需要帮助的地方:如何分析这些泄漏的来源?肯定有什么东西不允许内存被释放,但是怎么找到呢?

我正在使用 Primefaces 6.0、Apache Tomcat (TomEE)/8.5.3 (7.0.1)、JDK 1.7.0_80-b15、Mojarra 2.2.6、sqlite-jdbc 3.14.2.1。

如果需要任何其他文件,请告诉我,我将编辑此帖子以添加它们。

Web.xml:

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xmlns="http://java.sun.com/xml/ns/javaee" 
         xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
         xsi:schemaLocation="http://java.sun.com/xml/ns/javaee 
    http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
         id="WebApp_ID" version="3.0">

    <context-param>
        <param-name>javax.faces.PROJECT_STAGE</param-name>
        <param-value>Development</param-value>
    </context-param>

    <context-param>
        <param-name>javax.faces.STATE_SAVING_METHOD</param-name>
        <param-value>client</param-value>
    </context-param>

    <context-param>
        <param-name>primefaces.FONT_AWESOME</param-name>
        <param-value>true</param-value>
    </context-param>

    <resource-env-ref>
        <resource-env-ref-name>jdbc/MyResName</resource-env-ref-name>
        <resource-env-ref-type>javax.sql.DataSource</resource-env-ref-type>
    </resource-env-ref>

    <!-- Welcome page -->
    <welcome-file-list>
        <welcome-file>pages/pub/login.xhtml</welcome-file>
    </welcome-file-list>

    <!-- Error pages -->
    <error-page>
        <exception-type>javax.faces.application.ViewExpiredException</exception-type>
        <location>/pages/pub/err/expired.xhtml</location>
    </error-page>

    <!-- Prevents comments in xhtml pages to be placed in final html and evaluated -->
    <context-param>
        <param-name>javax.faces.FACELETS_SKIP_COMMENTS</param-name>
        <param-value>true</param-value>
    </context-param>

    <!-- JSF mapping -->
    <servlet>
        <servlet-name>Faces Servlet</servlet-name>
        <servlet-class>javax.faces.webapp.FacesServlet</servlet-class>
        <load-on-startup>1</load-on-startup>
    </servlet>

    <servlet-mapping>
        <servlet-name>Faces Servlet</servlet-name>
        <url-pattern>*.xhtml</url-pattern>
    </servlet-mapping>

    <!-- Primefaces theme -->
    <context-param>
        <param-name>primefaces.THEME</param-name>
        <param-value>cupertino</param-value>
    </context-param>

    <session-config>
        <session-timeout>120</session-timeout>
    </session-config>

    <filter>
      <filter-name>forceUTF8CharSet</filter-name>
      <filter-class>org.apache.catalina.filters.SetCharacterEncodingFilter</filter-class>
      <init-param>
        <param-name>encoding</param-name>
        <param-value>utf-8</param-value>
      </init-param>
    </filter>

    <filter-mapping>
      <filter-name>forceUTF8CharSet</filter-name>
      <url-pattern>*</url-pattern>
    </filter-mapping>

    <mime-mapping>
        <extension>ttf</extension>
        <mime-type>application/font-sfnt</mime-type>
    </mime-mapping>
    <mime-mapping>
        <extension>woff</extension>
        <mime-type>application/font-woff</mime-type>
    </mime-mapping>
    <mime-mapping>
        <extension>woff2</extension>
        <mime-type>application/font-woff2</mime-type>
    </mime-mapping>
    <mime-mapping>
        <extension>eot</extension>
        <mime-type>application/vnd.ms-fontobject</mime-type>
    </mime-mapping>
        <mime-mapping>
        <extension>eot?#iefix</extension>
        <mime-type>application/vnd.ms-fontobject</mime-type>
    </mime-mapping>
    <mime-mapping>
        <extension>svg</extension>
        <mime-type>image/svg+xml</mime-type>
    </mime-mapping>
    <mime-mapping>
        <extension>svg#latobold</extension>
        <mime-type>image/svg+xml</mime-type>
    </mime-mapping>
    <mime-mapping>
        <extension>svg#latoblack</extension>
        <mime-type>image/svg+xml</mime-type>
    </mime-mapping>
        <mime-mapping>
        <extension>svg#latolight</extension>
        <mime-type>image/svg+xml</mime-type>
    </mime-mapping>
    <mime-mapping>
        <extension>svg#latoregular</extension>
        <mime-type>image/svg+xml</mime-type>
    </mime-mapping>
    <mime-mapping>
        <extension>svg#fontawesomeregular</extension>
        <mime-type>image/svg+xml</mime-type>
</mime-mapping>
</web-app>

【问题讨论】:

    标签: java sqlite tomcat jsf primefaces


    【解决方案1】:

    也许可以从尝试 TomEE 7.0.2 开始。如果没有帮助,请尝试调试 WebContext 映射以检查哪些 CDI bean 未发布,那么您将能够知道谁(tomee、tomcat、primefaces、其他)负责它并检查您是否可以修复它。

    【讨论】:

    • 我会先尝试更新的 TomEE。让我感到惊讶的是,我没有考虑调试 Tomcat……我会试一试,会在 8 小时内回复您。
    【解决方案2】:

    我已经设法解决了我的问题。

    我的问题不在于我的任何 bean、处理程序、验证器、身份验证机制等。真正的问题是我在 pom.xml 中包含了两个库:

    <dependency>
        <groupId>com.sun.faces</groupId>
        <artifactId>jsf-api</artifactId>
        <version>2.2.6</version>
    </dependency>
    <dependency>
        <groupId>com.sun.faces</groupId>
        <artifactId>jsf-impl</artifactId>
        <version>2.2.6</version>
    </dependency>
    

    我不太清楚 TomEE 在遇到两个单独的实现(TomEE 自己的和更高版本)时会如何表现,但似乎有什么东西阻止了释放对某些资源的引用,这导致 WebContext 总是变大(它持有所有参与请求处理的对象 - 跨多个页面)。或者这可能是 jsf 实现中的一个错误?

    如果有人可以解释实际发生的事情,那么我会接受这样的答案作为我的问题的解决方案。在那之前,这个答案(无需太多推理)就是解决方案。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-05-11
      • 1970-01-01
      • 2011-02-25
      • 1970-01-01
      • 1970-01-01
      • 2012-06-16
      相关资源
      最近更新 更多