【问题标题】:JSF leaking memory through EL and composite componentsJSF 通过 EL 和复合组件泄漏内存
【发布时间】:2013-10-19 01:29:53
【问题描述】:

注意:我使用的是 mojarra 2.1.20 和丰富的面孔 4.2.2。

我分析了一个堆转储,并注意到 EL 表达式驻留在会话中的 LRUMap 中。有谁知道为什么以及如何避免它?

我遇到的问题与包含以下行的复合组件有关:

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

带有支持 bean my.package.MultiComboSelection。显然 my.package.MultiComboSelection 定义了一个名为 listValuesChangeListener 的方法。

我看到的问题是LRUMap包含ContextualCompositeMethodExpression(上面valueChangeListener的表达式的表示),其中cc属性引用了MultiComboSelection。 MultiComboSelection 扩展 UINamingContainer 并因此具有父/子属性 - 具有对组件树的引用。

结果是16MB内存不能被垃圾回收,因为有引用链:

session->LRUMap->ContextualCompositeMethodExpression->MultiComboSelection->parent 和 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 |              
--------------------------------------------------------------------------------------------------------------------------------------------

【问题讨论】:

    标签: jsf memory-leaks el composite-component


    【解决方案1】:

    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、这个 Stack Overflow 问题和您的发现。在视图状态下引用 UI 组件肯定是不对的。 UI 组件实例本质上是请求范围的,而不是视图范围的。


    更新:这被重新报告为 issue 3198,它在 Mojarra 2.2.8 中已修复,并且根据 issue 3544 在 Mojarra 2.1.29 中向后移植。因此,如果您至少升级到这些版本,那么当您不使用 com.sun.faces.serializeServerState=true(或根据 JSF 2.2 的 javax.faces.SERIALIZE_SERVER_STATE=true)时,应该修复此内存泄漏。

    【讨论】:

    • 谢谢。我会报告这个问题。
    • 我们受到了影响。从堆转储中可以清楚地看出 ContextualCompositeMethodExpression 每个占用 6.5 mb。解决方法确实解决了问题。
    【解决方案2】:

    我们在使用 actionListener 的 Composite-Element 时遇到了类似的问题。 Composite-Element 收集了ListDataObjects,尽管它们应该是garbageCollected。我们发现,list.clear() 在重新加载列表之前有助于防止这种内存泄漏。

    【讨论】:

      【解决方案3】:

      这可能已由 Mojarra 上的 https://java.net/jira/browse/JAVASERVERFACES-3544 修复。

      【讨论】:

        猜你喜欢
        • 2012-09-25
        • 2012-07-15
        • 1970-01-01
        • 2014-03-07
        • 1970-01-01
        • 2020-06-03
        • 2016-01-20
        • 1970-01-01
        • 2016-02-13
        相关资源
        最近更新 更多