为了确定这个错误,我将我的代码剥离到以下部分:
一个非常简单的 JSF2 页面:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:f="http://java.sun.com/jsf/core">
<h:head>
<f:facet name="first">
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>Simple OOM Check</title>
</f:facet>
</h:head>
<h:body>
<h:outputText value="#{oomCheckBean.testString}"/>
</h:body>
</html>
以及使用的@ViewScoped bean oomCheckBean:
@ViewScoped
@ManagedBean(name = "oomCheckBean")
public class OomCheckBean implements Serializable {
private static final long serialVersionUID = 6325712415478215045L;
private String testString;
@PostConstruct
public void init() {
testString = "Hello World";
System.out.println("I will survive ....");
}
@PreDestroy
public void destroy() {
System.out.println("... klaaatsch!");
}
/**
* @return the testString
*/
public String getTestString() {
return testString;
}
/**
* @param testString the testString to set
*/
public void setTestString(String testString) {
this.testString = testString;
}
}
在此之后,我将我的 JMeter 测试用例更改为登录,调用此 oomCheck.xhtml 页面并注销。不久之后,我停止了测试执行,并使用 JMX 首先手动调用垃圾收集器(java.lang.Memory --> Operations --> gc())。在此之后,我调用方法来创建堆转储(com.sun.management.HotSpotDiagnostic --> Operations --> dumpHeap())。
结果就像我在问题中提到的那样,内存中有很多 OomCheckBean 对象。所有者对象是org/jboss/as/web/deployment/ConcurrentReferenceHashMap$HashEntry
。任何解决此问题的帮助表示赞赏。就像我上面提到的,如果 JSF 版本升级到 2.1.16,这些 @ViewScoped bean 将被销毁,留下其他“错误”,如缺少 doctype 和 AJAX 问题。因此,如果有人知道如何在会话无效时销毁 @ViewScoped bean,我会很高兴。