In unserem JavaEE6 Projekt (EJB3, JSF2) auf JBoss 7.1.1, es scheint, dass wir @ViewScoped
ein Speicherleck mit SeamFaces haben.Speicherleck mit ViewScoped Bean?
Wir machten einen kleinen Prototyp, die Tatsache zu überprüfen:
- wir JMeter verwenden, um rufen eine Seite 200mal;
- die Seite enthält und ruft eine viewscoped Bean, die eine Stateful EJB injiziert;
- wir die Session-Timeout 1 Minute zu beheben.
Am Ende des Tests prüfen wir den Inhalt des Speichers mit VisualVM, und hier, was wir haben:
- mit einer
@ViewScoped
Bohne, bekommen wir noch 200 Fälle von der StatefulMyController
- und die@PreDestroy
Methode wird nie aufgerufen; - mit einer
@ConversationScoped
Bohne wird@preDestroy
Methode eine der Sitzung Ende und dann bekamen wir einen sauberen Speicher genannt.
Verwenden wir den Ansichtsbereich schlecht oder handelt es sich wirklich um einen Fehler?
Hier ist die XHTML-Seite:
<!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:f="http://java.sun.com/jsf/core"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:ui="http://java.sun.com/jsf/facelets"
xmlns:s="http://jboss.org/seam/faces">
<f:metadata>
<f:viewParam name="u" value="#{myBean.uselessParam}" />
<s:viewAction action="#{myBean.callService}" />
</f:metadata>
<h:body >
<f:view>
</f:view>
</h:body>
</html>
nun die mitgelieferte Bohne myBean
. Für die Variante sind alle kommentierten Teile unkommentiert.
@ViewScoped
// @ConversationScoped
@Named
public class MyBean implements Serializable
{
@Inject
MyController myController;
//@Inject
//Conversation conversation;
private String uselessParam;
public void callService()
{
//if(conversation.isTransient())
//{
// conversation.begin();
//}
myController.call();
}
public String getUselessParam()
{
return uselessParam;
}
public void setUselessParam(String uselessParam)
{
this.uselessParam = uselessParam;
}
}
Und dann die injizierte Stateful Bean MyController
:
@Stateful
@LocalBean
public class MyController
{
public void call()
{
System.out.println("call ");
}
@PreDestroy
public void destroy()
{
System.out.println("Destroy");
}
}
Wir versuchten mit CODI und der Test ging gut. Nett! –