gpt4 book ai didi

JSF 通过 EL 和复合组件泄漏内存

转载 作者:行者123 更新时间:2023-12-01 21:57:22 24 4
gpt4 key购买 nike

注意:我使用的是 mojarra 2.1.20 和 rich faces 4.2.2。

我分析了堆转储,并注意到 EL 表达式驻留在 session 中的 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 and 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 |
--------------------------------------------------------------------------------------------------------------------------------------------

最佳答案

由于修复 issue 1462ContextualCompositeMethodExpression 将整个复合组件作为实例变量引用。 。一位用户报告了这个内存泄漏问题:issue 1940 。后来,由于 issue 1943 的修复,实例变量被标记为 transient 的。 。然而,由于某种原因,问题 1940 被标记为 1943 的重复。两个用户在问题 1940 的底部正确地评论了您的问题,即内存泄漏问题仍然悬而未决,但我没有看到任何相关的新问题报告到后来。实际上,只有当复合组件包含任何方法表达式(例如值更改监听器)时,问题才会出现。

理论上,这个问题可以通过告诉 Mojarra 在 session 中序列化 View 状态而不是保留对 View 状态的引用来解决。由于实例变量被标记为“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 问题和您的发现。在 View 状态中引用UI组件肯定是不对的。 UI 组件实例本质上是请求范围的,而不是 View 范围的。

<小时/>

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

关于JSF 通过 EL 和复合组件泄漏内存,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19310154/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com