2013-10-11 15 views
7

Nota: sto utilizzando mojarra 2.1.20 e facce avanzate 4.2.2.JSF che perde memoria tramite EL e componenti compositi

Ho analizzato un heapdump e ho notato che le espressioni EL risiedono in LRUMap nella sessione. Qualcuno sa perché e cosa fare per evitarlo?

Il problema che ho è relativo a un componente composito contenente seguente riga:

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

con my.package.MultiComboSelection supporto fagiolo. Ovviamente my.package.MultiComboSelection ha un metodo definito named listValuesChangeListener.

Il problema che vedo è che LRUMap contiene ContextualCompositeMethodExpression (rappresentazione dell'espressione per valueChangeListener sopra), che attributo di cc fa riferimento a MultiComboSelection. MultiComboSelection estende UINamingContainer e, come tale, ha proprietà padre/figlio - ha riferimenti alla struttura dei componenti.

Il risultato è che 16 MB di memoria può non essere Cestino perché v'è una catena di riferimento:

session-> LRUMap-> ContextualCompositeMethodExpression-> MultiComboSelection-> parent e 16 MB

La domanda è: perché sta accadendo e come risolverlo o aggirarlo?

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 |    
-------------------------------------------------------------------------------------------------------------------------------------------- 

risposta

6

Il ContextualCompositeMethodExpression fa riferimento l'intero componente composito esempio variabile come conseguenza di una correzione a issue 1462. Un utente ha segnalato esattamente questo problema di perdita di memoria come issue 1940. E in seguito la variabile di istanza è stata contrassegnata con transient come conseguenza di una correzione a issue 1943. Tuttavia, il problema 1940 è stato per qualche motivo contrassegnato come duplicato del 1943. Due utenti hanno giustamente commentato esattamente il tuo problema in fondo al numero 1940 che il problema di perdita di memoria è ancora aperto, ma non vedo nessun nuovo rapporto relativo ai problemi a quello dopo. Il problema infatti si manifesta solo quando il componente composito contiene un'espressione di metodo come un listener di modifica del valore.

In teoria, questo problema può essere risolto dicendo a Mojarra di serializzare lo stato di visualizzazione in sessione invece di mantenere un riferimento allo stato di visualizzazione. Poiché la variabile di istanza è contrassegnata con transient, verrà ignorata. È possibile ottenere che il seguente parametro contesto in web.xml:

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

Anche in questo caso, in teoria; Non l'ho provato.

Si potrebbe anche voler provare MyFaces invece, non posso dire che lo risolverà, ma so che MyFaces 2.x è finora generalmente più attento di Mojarra per quanto riguarda la gestione dello stato, l'utilizzo della memoria e le prestazioni.

Nel frattempo, consiglio vivamente di creare un nuovo numero per Mojarra, facendo riferimento al numero 1940, a questa domanda sull'overflow dello stack e ai risultati. Il riferimento ai componenti dell'interfaccia utente nello stato di visualizzazione non è assolutamente corretto. Le istanze del componente UI sono intrinsecamente richieste per ambito, non per ambito.


Aggiornamento: questo è stato nuovamente segnalato come issue 3198 che è fissato in Mojarra 2.2.8 e secondo issue 3544 backport in Mojarra 2.1.29. Pertanto, se si esegue l'aggiornamento ad almeno tali versioni, è necessario correggere questa perdita di memoria quando non si utilizza com.sun.faces.serializeServerState=true (o javax.faces.SERIALIZE_SERVER_STATE=true come da JSF 2.2).

+0

Grazie. Segnalerò questo problema. – mabn

+0

Siamo stati colpiti da questo. Era chiaro dal mucchio discariche che ContextualCompositeMethodExpression di prese 6.5 MB ciascuno. La soluzione ha risolto il problema. – ymajoros

2

Abbiamo avuto un problema simile con un composite-element con una actionListener. L'elemento composito ha raccolto uno List di DataObjects, anche se dovrebbero essere garbageCollected. Abbiamo scoperto, list.clear() prima di ricaricare l'elenco aiuta a prevenire questa perdita di memoria.