2013-10-11 53 views
7

注意:我使用mojarra 2.1.20和豐富的面孔4.2.2。JSF通過EL和複合組件泄漏內存

我分析過一個heapdump,我注意到EL表達式駐留在會話的LRUMap中。有誰知道爲什麼和如何做以避免它?

我的問題是關係到含有以下行復合部件:

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

與支持bean my.package.MultiComboSelection。顯然my.package.MultiComboSelection有一個名爲listValuesChangeListener的方法。

我看到的問題是LRUMap包含ContextualCompositeMethodExpression(上面的valueChangeListener表達式的表示),其中cc屬性引用MultiComboSelection。 MultiComboSelection擴展UINamingContainer,並且具有父/子屬性 - 具有對組件樹的引用。

結果是16MB內存不能被垃圾收集,因爲有一個參考鏈:

會話級> LRUMap-> ContextualCompositeMethodExpression-> MultiComboSelection->父 和16MB

現在的問題是 - 爲什麼會發生這種情況,以及如何解決或解決這個問題?

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

回答

6

ContextualCompositeMethodExpression所引用整個複合組件作爲實例變量作爲一個修復可issue 1462的後果。用戶已報告有關此內存泄漏問題issue 1940。然後後面的實例變量被標記爲transient,作爲修復issue 1943的結果。然而,1940年問題出於某種原因被標記爲1943年的重複。兩位用戶在問題1940底部正確評論了您的問題,即內存泄漏問題仍然存在,但我沒有看到任何與此相關的新問題報告之後。問題確實只在複合組件包含任何方法表達式(如值更改偵聽器)時纔會顯現。

理論上講,可以通過告訴Mojarra在會話中序列化視圖狀態而不是保持對視圖狀態的引用來解決此問題。由於實例變量標記爲transient,它將被繞過。您可以通過web.xml中的以下上下文參數來實現:

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

同樣,理論上,我沒有測試過。

您可能也想嘗試MyFaces,我不能說它會解決這個問題,但我知道MyFaces 2.x到目前爲止一般比Mojarra更注重狀態管理,內存使用和性能。

與此同時,我強烈建議爲Mojarra創建一個新問題,引用問題1940,這個堆棧溢出問題和您的發現。在視圖狀態下引用UI組件肯定是不正確的。 UI組件實例本質上是請求作用域,而不是視圖作用域。


更新:此重新報告爲issue 3198,其固定在鑽嘴魚科2.2.8和按issue 3544在鑽嘴魚科2.1.29反向移植。因此,如果您升級到至少這些版本,那麼當您不使用com.sun.faces.serializeServerState=true(或根據JSF 2.2的javax.faces.SERIALIZE_SERVER_STATE=true)應該修復此內存泄漏。

+0

謝謝。我會報告這個問題。 – mabn

+0

我們受此影響。從堆轉儲清楚地看到,ContextualCompositeMethodExpression每個都佔用了6.5 MB。解決方法確實解決了問題。 – ymajoros

2

我們對actionListener有複合元素的類似問題。複合元素收集DataObjectsList,儘管它們應該被垃圾收集。我們發現,list.clear()在重新加載List之前有助於防止這種內存泄漏。