2012-10-26 11 views
7

In unserem JavaEE6-Projekt (EJB3, JSF2) auf JBoss 7.1.1 scheint es einen Speicherverlust mit @ViewScoped-Beans zu geben. Letzte Baumtage habe ich Zeit mit dieser Thematik verbracht. Also habe ich ein einfaches Projekt mit zwei Seiten erstellt, um zu garantieren, dass nach dem Verlassen der ersten Seite @ViewScoped Bean veröffentlicht wird.Verknüpfte ViewScoped-Beans führen zu Speicherlecks

<context-param> //web.xml 
    <param-name>javax.faces.STATE_SAVING_METHOD</param-name> 
    <param-value>server</param-value> 
</context-param> 
<context-param> 
    <param-name>javax.faces.PARTIAL_STATE_SAVING</param-name> 
    <param-value>false</param-value> 
</context-param> 

TreeBean.java

@ManagedBean 
@ViewScoped 
public class TreeBean implements Serializable { 
private TreeNode root; 
public static AtomicInteger count = new AtomicInteger(0); 

@Override 
protected void finalize() throws Throwable { 
    System.out.println("TreeBean beans count: " + count.decrementAndGet() + " (FINALISATION)"); 
} 


public TreeBean() { 
    super(); 
    System.out.println("TreeBean beans count: " + count.incrementAndGet() + " (INITIALISATION)"); 
} 

first.xhtml

.... 
    <h:form id="frm"> 
     <p:tree 
      value="#{treeBean.root}" 
      var="node" 
      id="tree"> 
    .... 
    <p:commandLink 
      action="second.xhtml?faces-redirect=true" 
      value="toSecond" /> 
    ....    

second.xhtml

.... 
    <h:form id="frm"> 
    .... 
    <p:commandLink 
      action="first.xhtml?faces-redirect=true" 
      value="toFirst" /> 
    .... 

sysout:

INFO [stdout] (http--0.0.0.0-8080-4) TreeBean beans count: 1 (INITIALISATION) 
    INFO [stdout] (http--0.0.0.0-8080-4) TreeBean beans count: 2 (INITIALISATION) 
    INFO [stdout] (http--0.0.0.0-8080-4) TreeBean beans count: 3 (INITIALISATION) 
    ...... 
    INFO [stdout] (Finalizer) TreeBean beans count: 2 (FINALISATION) 
    INFO [stdout] (Finalizer) TreeBean beans count: 1 (FINALISATION) 
    INFO [stdout] (Finalizer) TreeBean beans count: 0 (FINALISATION) 

und alle denken kam gut, bis ich Abhängigkeit zu anderen @ViewScoped Bohne

TreeBean.java

@ManagedBean 
@ViewScoped 
public class TreeBean implements Serializable { 
private TreeNode root; 

@ManagedProperty(value = "#{treeNodeBean}") 
private TreeNodeBean treeNodeBean; 


public static AtomicInteger count = new AtomicInteger(0); 

@Override 
protected void finalize() throws Throwable { 
    System.out.println("TreeBean beans count: " + count.decrementAndGet() + " (FINALISATION)"); 
} 


public TreeBean() { 
    super(); 
    System.out.println("TreeBean beans count: " + count.incrementAndGet() + " (INITIALISATION)"); 
} 

TreeNodeBean.java

@ManagedBean 
@ViewScoped 
public class TreeNodeBean implements Serializable { 

    private String treeNodeItem="TreeNodeItem"; 

} 

Und danach niemand hinzugefügt haben Bean wurde veröffentlicht. Weiß jemand, wie man damit umgeht? Ist das ein Fehler oder kann es irgendwo konfiguriert werden?

+0

Siehe diesen Link. Work around getan für JSf 2.1 & 2.2 http://stackoverflow.com/questions/12182844/memory-leak-with-viewscoped-bean –

Antwort

5

Leider sind Sie richtig, Es gibt bekannte Probleme mit @ViewScoped Speicherverwaltung (und ist nicht nur mit der Verkettung der Ansichten betroffen), wie Sie here und here sehen werden. Schauen Sie sich auch this question an. Sie könnten damit experimentieren, das UIViewRoot Objekt in der aktuellen Sitzung zu bekommen und getViewMap().remove("myView") basierend auf einem Ereignis aufzurufen. Sie könnten auch versuchen, this

Unabhängig davon, warum verketten Sie sehen sphärische Bohnen? Sie sollen als benannte Ansichten verwendet werden. Sind Sie gezwungen, die SessionScoped zu verwenden?

+0

Ich obwohl vievscoped ist für kürzere Zeiträume der Benutzeraktivität konzipiert. So Bean ist live, bis Sie die aktuelle Seite verlassen. Sessionscoped länger leben, bis Web-Session fallen. Meine Wahl war also, die Erinnerung zu retten. – bohdanius

+1

@bohdanius, ich vermutete, dass Sie sowieso schon eine Session-Bean in Ihrer Web-App hatten und wenn Sie dies tun, sollte alles, was Sie in dem View-Bereich speichern, den Sie in 3 separaten Ansichten referenzieren müssen, dort bleiben. Sie können dann die Säuberung übernehmen (indem Sie die vars auf null oder was auch immer setzen) oder sie zusammen mit der Sitzung löschen lassen. Wenn Sie keine Session Bean eingerichtet haben, ist dies ein starker Fall für einen. Eine andere Alternative ist der Flash-Bereich, der hauptsächlich anwendbar ist, wenn die drei Ansichten sequentiell sind – kolossus