在Glassfish中创建了多余的SFSB,从而泄漏了内存

时间:2012-03-27 17:03:37

标签: jsf-2 java-ee-6 glassfish-3 stateful-session-bean

我正在尝试将单个SFSB注入到Glassfish 3.1.1中的ViewScoped JSF支持bean中。

我的日志显示了这一点,即创建了两个SFSB,尽管只注入了第二个:

INFO: constructed a new sfsb: com.example.test.service.impl._TestSFSBImpl_Serializable@f48cde0
INFO: constructed a new sfsb: com.exmaple.test.service.impl._TestSFSBImpl_Serializable@13dbf5ce
INFO: constructed a new view scoped bean: com.example.test.ui.TestViewScopedSFSB@4de6b191

稍后,当我离开并且ViewScoped bean超出范围时,我在SFSB上调用remove(),所以我在日志中看到了这一点:

INFO: destroying view scoped bean: com.example.test.ui.TestViewScopedSFSB@4de6b191
INFO: removing sfsb: com.example.test.service.impl._TestSFSBImpl_Serializable@13dbf5ce
INFO: destroying sfsb: com.example.test.service.impl._TestSFSBImpl_Serializable@13dbf5ce

但是在@ f48cde0结尾的多余的第一个从未被注入,所以我没有它的句柄,它永远不会被删除。直到稍后,当我关闭服务器时,我发现它已被删除。

这是我的代码:

支持bean:

package com.example.test.ui;

import java.io.Serializable;
import java.util.logging.Logger;

import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;
import javax.ejb.EJB;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.ViewScoped;
import javax.faces.event.AjaxBehaviorEvent;

import com.example.test.service.api.TestSFSB;

@ManagedBean(name = "testViewScopedSFSB")
@ViewScoped
public class TestViewScopedSFSB implements Serializable {

  private static final long serialVersionUID = 1L;
  private static final Logger LOGGER = Logger.getLogger(TestViewScopedSFSB.class.getCanonicalName());

  @EJB
  private TestSFSB testSFSB;

  @PostConstruct
  public void postConstruct() {
    LOGGER.info("constructed a new view scoped bean: " + this);
  }

  public int getNumClicks() {
    return testSFSB.getNumClicks();
  }

  public void clicked(AjaxBehaviorEvent event) {
    testSFSB.clicked();
  }

  @PreDestroy
  public void preDestroy() {
    LOGGER.info("destroying view scoped bean: " + this);
    testSFSB.remove();
  }

}

SFSB接口:

package com.example.test.service.api;

public interface TestSFSB {

  void clicked();

  int getNumClicks();

  void remove();

}

SFSB实施:

package com.example.test.service.impl;

import java.util.logging.Logger;

import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;
import javax.ejb.Local;
import javax.ejb.Remove;
import javax.ejb.Stateful;

import com.example.test.service.api.TestSFSB;

@Stateful
@Local(TestSFSB.class)
public class TestSFSBImpl implements TestSFSB {

  private static final long serialVersionUID = 1L;
  private static final Logger LOGGER = Logger.getLogger(TestSFSBImpl.class.getCanonicalName());

  int numClicks = 0;

  @PostConstruct
  public void postConstruct() {
    LOGGER.info("constructed a new sfsb: " + this);
  }

  @Override
  public void clicked() {
    numClicks++;
  }

  @Override
  public int getNumClicks() {
    return numClicks;
  }

  @Override
  @Remove
  public void remove() {
    LOGGER.info("removing sfsb: " + this);
  }

  @PreDestroy
  public void preDestroy() {
    LOGGER.info("destroying sfsb: " + this);
  }

}

最后,jsf页面:

<?xml version="1.0" encoding="ISO-8859-1" ?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<h:html xmlns="http://www.w3.org/1999/xhtml"
    xmlns:c="http://java.sun.com/jsp/jstl/core"
    xmlns:f="http://java.sun.com/jsf/core"
    xmlns:h="http://java.sun.com/jsf/html"
    xmlns:ui="http://java.sun.com/jsf/facelets">

<h:head>

</h:head>

<h:body>
    <h:form>
        <h:commandLink action="/public/publicResource.jsf" value="Home" />
        <h:panelGrid id="panel1">
            <h:commandButton value="Click me">
                <f:ajax event="click" listener="#{testViewScopedSFSB.clicked}"
                    render="panel1" />
            </h:commandButton>
            <h:outputText value="#{testViewScopedSFSB.numClicks}" />
        </h:panelGrid>
    </h:form>

</h:body>
</h:html>

这是一个如此简单的设置......它究竟是什么?也许是Glassfish中的一个错误?

修改 为了消除对我报告的真实性的任何“疑虑”,这是我加载页面10次时的日志。注意20个SFSB创建,每次2个,但是当我离开时只清理了1个。

INFO: constructed a new sfsb: com.example.test.service.impl._TestSFSBImpl_Serializable@561b0019
INFO: constructed a new sfsb: com.example.test.service.impl._TestSFSBImpl_Serializable@2767c7d9
INFO: constructed a new view scoped bean: com.example.test.ui.TestViewScopedSFSB@7b239469
INFO: destroying view scoped bean: com.example.test.ui.TestViewScopedSFSB@7b239469
INFO: removing sfsb: com.example.test.service.impl._TestSFSBImpl_Serializable@2767c7d9
INFO: destroying sfsb: com.example.test.service.impl._TestSFSBImpl_Serializable@2767c7d9

INFO: constructed a new sfsb: com.example.test.service.impl._TestSFSBImpl_Serializable@5c8608b9
INFO: constructed a new sfsb: com.example.test.service.impl._TestSFSBImpl_Serializable@63a6d923
INFO: constructed a new view scoped bean: com.example.test.ui.TestViewScopedSFSB@5ef9bbf1
INFO: destroying view scoped bean: com.example.test.ui.TestViewScopedSFSB@5ef9bbf1
INFO: removing sfsb: com.example.test.service.impl._TestSFSBImpl_Serializable@63a6d923
INFO: destroying sfsb: com.example.test.service.impl._TestSFSBImpl_Serializable@63a6d923

INFO: constructed a new sfsb: com.example.test.service.impl._TestSFSBImpl_Serializable@31a4ef37
INFO: constructed a new sfsb: com.example.test.service.impl._TestSFSBImpl_Serializable@43551d57
INFO: constructed a new view scoped bean: com.example.test.ui.TestViewScopedSFSB@8f95d4a
INFO: destroying view scoped bean: com.example.test.ui.TestViewScopedSFSB@8f95d4a
INFO: removing sfsb: com.example.test.service.impl._TestSFSBImpl_Serializable@43551d57
INFO: destroying sfsb: com.example.test.service.impl._TestSFSBImpl_Serializable@43551d57

INFO: constructed a new sfsb: com.example.test.service.impl._TestSFSBImpl_Serializable@69e3f60e
INFO: constructed a new sfsb: com.example.test.service.impl._TestSFSBImpl_Serializable@5f91e550
INFO: constructed a new view scoped bean: com.example.test.ui.TestViewScopedSFSB@63661834
INFO: destroying view scoped bean: com.example.test.ui.TestViewScopedSFSB@63661834
INFO: removing sfsb: com.example.test.service.impl._TestSFSBImpl_Serializable@5f91e550
INFO: destroying sfsb: com.example.test.service.impl._TestSFSBImpl_Serializable@5f91e550

INFO: constructed a new sfsb: com.example.test.service.impl._TestSFSBImpl_Serializable@266c4c10
INFO: constructed a new sfsb: com.example.test.service.impl._TestSFSBImpl_Serializable@ff5c225
INFO: constructed a new view scoped bean: com.example.test.ui.TestViewScopedSFSB@4f9d1352
INFO: destroying view scoped bean: com.example.test.ui.TestViewScopedSFSB@4f9d1352
INFO: removing sfsb: com.example.test.service.impl._TestSFSBImpl_Serializable@ff5c225
INFO: destroying sfsb: com.example.test.service.impl._TestSFSBImpl_Serializable@ff5c225

INFO: constructed a new sfsb: com.example.test.service.impl._TestSFSBImpl_Serializable@42650c3b
INFO: constructed a new sfsb: com.example.test.service.impl._TestSFSBImpl_Serializable@7806178a
INFO: constructed a new view scoped bean: com.example.test.ui.TestViewScopedSFSB@57f3a295
INFO: destroying view scoped bean: com.example.test.ui.TestViewScopedSFSB@57f3a295
INFO: removing sfsb: com.example.test.service.impl._TestSFSBImpl_Serializable@7806178a
INFO: destroying sfsb: com.example.test.service.impl._TestSFSBImpl_Serializable@7806178a

INFO: constructed a new sfsb: com.example.test.service.impl._TestSFSBImpl_Serializable@70879d38
INFO: constructed a new sfsb: com.example.test.service.impl._TestSFSBImpl_Serializable@5763013f
INFO: constructed a new view scoped bean: com.example.test.ui.TestViewScopedSFSB@24e6fbeb
INFO: destroying view scoped bean: com.example.test.ui.TestViewScopedSFSB@24e6fbeb
INFO: removing sfsb: com.example.test.service.impl._TestSFSBImpl_Serializable@5763013f
INFO: destroying sfsb: com.example.test.service.impl._TestSFSBImpl_Serializable@5763013f

INFO: constructed a new sfsb: com.example.test.service.impl._TestSFSBImpl_Serializable@49649260
INFO: constructed a new sfsb: com.example.test.service.impl._TestSFSBImpl_Serializable@552ee43b
INFO: constructed a new view scoped bean: com.example.test.ui.TestViewScopedSFSB@798a092d
INFO: destroying view scoped bean: com.example.test.ui.TestViewScopedSFSB@798a092d
INFO: removing sfsb: com.example.test.service.impl._TestSFSBImpl_Serializable@552ee43b
INFO: destroying sfsb: com.example.test.service.impl._TestSFSBImpl_Serializable@552ee43b

INFO: constructed a new sfsb: com.example.test.service.impl._TestSFSBImpl_Serializable@1a722605
INFO: constructed a new sfsb: com.example.test.service.impl._TestSFSBImpl_Serializable@3c1e1fd3
INFO: constructed a new view scoped bean: com.example.test.ui.TestViewScopedSFSB@5dbb747a
INFO: destroying view scoped bean: com.example.test.ui.TestViewScopedSFSB@5dbb747a
INFO: removing sfsb: com.example.test.service.impl._TestSFSBImpl_Serializable@3c1e1fd3
INFO: destroying sfsb: com.example.test.service.impl._TestSFSBImpl_Serializable@3c1e1fd3

INFO: constructed a new sfsb: com.example.test.service.impl._TestSFSBImpl_Serializable@21da38c0
INFO: constructed a new sfsb: com.example.test.service.impl._TestSFSBImpl_Serializable@7dc3d69c
INFO: constructed a new view scoped bean: com.example.test.ui.TestViewScopedSFSB@443edc45
INFO: destroying view scoped bean: com.example.test.ui.TestViewScopedSFSB@443edc45
INFO: removing sfsb: com.example.test.service.impl._TestSFSBImpl_Serializable@7dc3d69c
INFO: destroying sfsb: com.example.test.service.impl._TestSFSBImpl_Serializable@7dc3d69c

最后,当我卸载应用程序时,请注意10个多余的SFSB最终被破坏:

INFO: destroying sfsb: com.example.test.service.impl._TestSFSBImpl_Serializable@561b0019
INFO: destroying sfsb: com.example.test.service.impl._TestSFSBImpl_Serializable@5c8608b9
INFO: destroying sfsb: com.example.test.service.impl._TestSFSBImpl_Serializable@31a4ef37
INFO: destroying sfsb: com.example.test.service.impl._TestSFSBImpl_Serializable@69e3f60e
INFO: destroying sfsb: com.example.test.service.impl._TestSFSBImpl_Serializable@266c4c10
INFO: destroying sfsb: com.example.test.service.impl._TestSFSBImpl_Serializable@42650c3b
INFO: destroying sfsb: com.example.test.service.impl._TestSFSBImpl_Serializable@70879d38
INFO: destroying sfsb: com.example.test.service.impl._TestSFSBImpl_Serializable@49649260
INFO: destroying sfsb: com.example.test.service.impl._TestSFSBImpl_Serializable@1a722605
INFO: destroying sfsb: com.example.test.service.impl._TestSFSBImpl_Serializable@21da38c0

根据我的声誉表达我的观点,该行为适用于100次点击,导致相同模式的200个豆子。

1 个答案:

答案 0 :(得分:0)

这不是一个错误,它是一个功能。而且很重要。在Java EE中,容器创建了一些不同事物的实例(例如无状态bean,消息驱动的bean,实体和sfsbs)以及池和托管它们,以及什么不是。让容器执行和处理这是使用Java EE的原因之一。您可以在大多数容器中配置此行为。

来自Glassfish文档:

  

此外,GlassFish Server支持许多可调参数   可以控制“有状态”实例数量的参数   (有状态会话bean和实体bean)缓存以及   他们被缓存的持续时间。

[..]

  

GlassFish Server池最重要的参数之一是   稳定池大小。当steady-pool-size设置为大于的值时   0,容器不仅预先填充bean池   指定的bean数量,也试图确保这一点   免费游泳池中始终提供豆类数量。这确保了   在准备服务状态下有足够的bean来处理   用户请求。

http://docs.oracle.com/cd/E18930_01/html/821-2418/beahn.html#beahq

如果您不想要此行为,可以将其配置为:阅读并按照上面链接中的相应链接进行操作。