2013-10-11 13 views
7

Hinweis: Ich verwende Mojarra 2.1.20 und reiche Gesichter 4.2.2.JSF undichtem Speicher durch EL und Composite-Komponenten

Ich habe einen Heapdump analysiert und festgestellt, dass EL-Ausdrücke in LRUMap in der Sitzung enthalten sind. Weiß jemand, warum und was zu tun, um es zu vermeiden?

Ich habe das Problem bezieht sich auf eine Verbundkomponente folgende Zeile enthält:

<rich:select ... valueChangeListener="#{cc.listValuesChangeListener}" 

mit Träger bean my.package.MultiComboSelection. Offensichtlich hat my.package.MultiComboSelection eine Methode namens listValuesChangeListener.

Das Problem, das ich sehe, ist, dass LRUMap ContextualCompositeMethodExpression (Darstellung des Ausdrucks für valueChangeListener oben) enthält, die cc Attribut verweist MultiComboSelection. MultiComboSelection erweitert UINamingContainer und hat daher übergeordnete/untergeordnete Eigenschaften - weist Verweise auf die Komponentenstruktur auf.

Das Ergebnis ist, dass 16 MB Speicher kann nicht Garbage Collection werden, weil es eine Kette Referenz:

Session-> LRUMap-> ContextualCompositeMethodExpression-> MultiComboSelection-> parent und 16MB

Die Frage ist - warum passiert es und wie kann man es reparieren oder umgehen?

Class Name                     | Shallow Heap | Retained Heap | Retained Heap 
-------------------------------------------------------------------------------------------------------------------------------------------- 
my.package.MultiComboSelection @ 0x78dc2bd50             |   96 | 16 466 272 | 16 466 272 
|- component javax.faces.component.UIComponentBase$FacetsMap @ 0x78dbbbd58     |   48 |   128 |    
|- parent javax.faces.component.UIPanel @ 0x78dbbbdd8          |   88 |   760 |    
|- cc com.sun.faces.facelets.el.ContextualCompositeMethodExpression @ 0x78dc2bce0   |   32 | 16 466 384 |    
| |- [0] java.lang.Object[2] @ 0x78dc2bc90             |   24 | 16 466 464 |    
| | '- [0] java.lang.Object[1] @ 0x78dc2bc78            |   24 | 16 466 488 |    
| |  '- [0] java.lang.Object[5] @ 0x78dc2bc20           |   40 | 16 466 576 |    
| |  '- [0] java.lang.Object[2] @ 0x78dc2bc08           |   24 | 16 466 600 |    
| |   '- [0] java.lang.Object[4] @ 0x78dc2bbe8          |   32 | 16 466 632 |    
| |    '- value java.util.HashMap$Entry @ 0x78dc2bb40        |   32 | 16 466 800 |    
| |     '- [1579] java.util.HashMap$Entry[2048] @ 0x78dbf61b8     |  8 208 | 33 552 536 |    
| |     '- table java.util.HashMap @ 0x78dbb6860        |   48 | 33 552 584 |    
| |      '- [1] java.lang.Object[2] @ 0x78ad95340       |   24 | 33 552 608 |    
| |       '- value java.util.LinkedHashMap$Entry @ 0x78ad952c0   |   40 | 33 552 736 |    
| |        |- after, before java.util.LinkedHashMap$Entry @ 0x78acbe6a0|   40 |   40 |    
| |        |- [0] java.util.HashMap$Entry[2] @ 0x78ad952a8    |   24 |   24 |    
| |        | '- table com.sun.faces.util.LRUMap @ 0x78ad95270   |   56 | 33 552 856 |    
-------------------------------------------------------------------------------------------------------------------------------------------- 

Antwort

6

The ContextualCompositeMethodExpression verweisen auf die gesamte Verbundkomponente als Instanzvariablen als Folge der Fix issue 1462. Ein Benutzer hat über genau dieses Speicherverlustproblem wie issue 1940 berichtet. Und später wurde die Instanzvariable als als Folge einer Behebung auf issue 1943 markiert. Ausgabe 1940 wurde jedoch aus irgendeinem Grund als Duplikat von 1943 markiert. Zwei Benutzer haben am Ende der Ausgabe 1940 zu Recht Ihr Problem genau kommentiert, dass das Speicherleckproblem noch offen ist, aber ich sehe keine neuen Problemberichte dazu später. Das Problem tritt tatsächlich nur dann auf, wenn die zusammengesetzte Komponente einen Methodenausdruck wie einen Wertänderungs-Listener enthält.

Theoretisch kann dieses Problem umgangen werden, indem Mojarra angewiesen wird, den Ansichtszustand in der Sitzung zu serialisieren, anstatt einen Verweis auf den Ansichtszustand beizubehalten. Da die Instanzvariable mit gekennzeichnet ist, wird sie umgangen.

<context-param> 
    <param-name>com.sun.faces.serializeServerState</param-name> 
    <param-value>true</param-value> 
</context-param> 

Wieder theoretisch;: Sie können in web.xml, dass durch den folgenden Kontextparameter erreichen Das habe ich nicht getestet.

Vielleicht möchten Sie auch MyFaces ausprobieren, ich kann nicht sagen, dass es das beheben würde, aber ich weiß, dass MyFaces 2.x bisher im Allgemeinen vorsichtiger ist als Mojarra hinsichtlich Statusverwaltung, Speichernutzung und Leistung.

In der Zwischenzeit empfehle ich dringend, eine neue Ausgabe für Mojarra zu erstellen, Verweis auf Frage 1940, diese Stack Overflow Frage und Ihre Ergebnisse. Das Referenzieren von UI-Komponenten im Ansichtszustand ist definitiv nicht richtig. UI-Komponenteninstanzen sind von Natur aus Anforderungsbereich, nicht Sichtbereich.


aktualisieren: dies wurde als issue 3198 wieder berichtet, die in Mojarra 2.2.8 und gemäß issue 3544 in Mojarra 2.1.29 zurückportiert fixiert ist. Wenn Sie also mindestens auf diese Versionen aktualisieren, sollte dieser Speicherverlust, wenn Sie com.sun.faces.serializeServerState=true (oder javax.faces.SERIALIZE_SERVER_STATE=true gemäß JSF 2.2) nicht verwenden, behoben werden.

+0

Danke. Ich werde dieses Problem melden. – mabn

+0

Wir waren davon betroffen. Aus Heap-Dumps wurde klar, dass ContextualCompositeMethodExpression 6.5 MB pro Stück benötigte. Die Problemumgehung hat das Problem gelöst. – ymajoros

2

Wir hatten eine ähnliche Ausgabe mit einem Composite-Element mit einer actionListener. Das Composite-Element sammelte eine List von DataObjects, obwohl sie garbageCollected sein sollte. Wir haben herausgefunden, list.clear() vor dem erneuten Laden der Liste hilft, dieses Speicherleck zu verhindern.