JSF通过EL和复合组件泄漏内存 [英] JSF leaking memory through EL and composite components

查看:114
本文介绍了JSF通过EL和复合组件泄漏内存的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

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

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

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

带有后备豆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 |              
--------------------------------------------------------------------------------------------------------------------------------------------

解决方案

由于修复了问题1940 .然后,由于修复了问题1943 transient >.但是,由于某些原因,问题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更为谨慎. /p>

与此同时,我强烈建议为Mojarra创建一个新问题,请参考第1940期,此Stack Overflow问题和您的发现.在视图状态下引用UI组件绝对是不正确的. UI组件实例本质上是请求范围的,而不是视图范围的.


更新:重新报告为问题3198 已在Mojarra 2.2.8中修复,并且根据在Mojarra 2.1中反向移植的 issue 3544 进行了修复. 29.因此,如果至少升级到那些版本,则应该修复不使用com.sun.faces.serializeServerState=true(或JSF 2.2中的javax.faces.SERIALIZE_SERVER_STATE=true)时发生的内存泄漏.

Note: I'm using mojarra 2.1.20 and rich faces 4.2.2.

I've analyzed a heapdump and I've noticed that EL expressions reside in LRUMap in the session. Does anyone know why and what to do to avoid it?

The problem I have is related to a composite component containing following line:

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

with backing bean my.package.MultiComboSelection. Obviously my.package.MultiComboSelection has a method defined named listValuesChangeListener.

The problem I see is that LRUMap contains ContextualCompositeMethodExpression (representation of the expression for valueChangeListener above), which cc attribute references MultiComboSelection. MultiComboSelection extends UINamingContainer and as such has parent/children properties - has references to component tree.

The result is that 16MB of memory cannot be garbage-collected because there is a reference chain:

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

The question is - why is it happening and how to fix it or work around it?

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

解决方案

The ContextualCompositeMethodExpression is referencing the whole composite component as instance variable as consequence of a fix to issue 1462. An user has reported about exactly this memory leak problem as issue 1940. And then later on the instance variable was marked transient as consequence of a fix to issue 1943. However, issue 1940 was for some reason been marked as duplicate of 1943. Two users have rightfully commented about exactly your problem in the bottom of issue 1940 that the memory leak issue is still open, but I'm not seeing any new issue reports related to that afterwards. The problem indeed only manifests when the composite component contains any method expression like a value change listener.

Theoretically, this problem can be workarounded by telling Mojarra to serialize the view state in session instead of keeping a reference to the view state. As the instance variable is marked transient, it would be bypassed. You can achieve that by the following context parameter in web.xml:

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

Again, theoretically; I did not test that.

You might also want to try MyFaces instead, I can't tell that it would fix that, but I know that MyFaces 2.x is so far generally more careful than Mojarra as to state management, memory usage and performance.

In the meanwhile, I strongly recommend to create a new issue for Mojarra, referencing issue 1940, this Stack Overflow question and your findings. Referencing UI components in the view state is definitely not right. UI component instances are inherently request scoped, not view scoped.


Update: this was re-reported as issue 3198 which is fixed in Mojarra 2.2.8 and as per issue 3544 backported in Mojarra 2.1.29. So, if you upgrade to at least those versions, then this memory leak when you don't use com.sun.faces.serializeServerState=true (or javax.faces.SERIALIZE_SERVER_STATE=true as per JSF 2.2) should be fixed.

这篇关于JSF通过EL和复合组件泄漏内存的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆