问候,
我有丰富的面孔应用程序(3.3.2.SR1)。该应用程序使用 ModelPanel 来查看实体。所有模式面板在我想要显示它们之前都不会渲染(rendered = false)。应用程序变得很大,并且使用一个面板到其他面板的大量关系。一切正常,但看起来 richfaces 在内存中为所有可能的情况创建 UIComponent 树(如果组件 rendred 为 true 或 false)。当我尝试检查应用程序的内存使用情况时(我使用 YourKit Java Profiler 来满足这些需求),我发现它在一个 session 中使用了大量内存。
我正在将 Facelets 与 richfaces 一起使用,并且我尝试使用
<c:if test="rendred condition"... /> content </c:if>
它开始使用明显更少的内存,但是...... 当我使用面板重新渲染该区域时,父屏幕上的控件将停止工作。我怀疑这是因为每次更改组件树时,它都会重新创建整个树,并且我有不同步的客户端(html)和服务器(faces)部分。
有人可以建议我减少内存使用的方法吗?我有一个真正的问题,因为 HeapMemory 中的 StandardSession 对象使用 60-150Mb。几乎所有内存都用于 UIControl。
问题示例:
我的页面引用了 panel1、panel2、panel3。
面板是:
<rich:modalPanel >
<a4j:outputPanel layout="block"
rendered="#{PanelBeanHolder.renderedViewScreen}">
<ui:insert name="panelContent" />
</a4j:outputPanel>
</rich:modalPanel>
仅当执行此操作时,我才会渲染面板。并且在需要之前不想加载输出面板的 UI 控件。
提前谢谢您。
附注我尝试执行以下操作来改善情况
在 web.xml 中配置 session 中的 View 数:
<context-param>
<param-name>com.sun.faces.numberOfViewsInSession</param-name>
<param-value>4</param-value>
</context-param>
<context-param>
<param-name>com.sun.faces.numberOfLogicalViews</param-name>
<param-value>4</param-value>
</context-param>
它必须改进 StateHolder 对象,但没有多大帮助。我做了测量,当这些数字增加时,内存使用量也会增加。但是,当我厌倦将它们设置为 1,1 时 - 有些页面停止工作。有时请求会转发到欢迎页面。 2,2改善了情况,但转发到欢迎页面的问题仍然发生。
尝试在 javax.faces.STATE_SAVING_METHOD 中使用客户端模式。 UIComponent 模型仍然使用大量内存。即使对象被序列化并且必须存储在表单中。
尝试重写stateManager 在 faces.config 中:
<state-manager>org.ajax4jsf.application.CompressAjaxStateManager</state-manager>
并重写buildViewState和restoreView来压缩流。 没有多大帮助。
最佳答案
JSF 使用在请求之间维护的有状态组件树。默认情况下,这通常在 session 中维护。您可以使用一些功能来控制它。
配置状态保存参数
通常有特定于实现的参数来控制 session 中存储的 View 数量 - 根据您的应用程序的行为方式,这可能是一个轻松的胜利。
您可以使用javax.faces.STATE_SAVING_METHOD
参数将状态保存在表单中。但是,请注意,每个请求都会发送更多信息,并且允许客户端决定服务器端状态存在安全风险(确保您对实现加密此数据的方式感到满意)。您需要检查与组件库(即 RichFaces)的兼容性,尤其是在使用 AJAX 时。
JSF 2 使用新的状态保存机制来减少 session 开销;您的 faces-config.xml
需要更新到 2.0 版本。我相信这个想法来自 Apache Trinidad ,因此您可以从那里提取 JSF 2 之前的版本。
进行自己的状态保存和/或 View 创建
实现您自己的StateManager
和/或ViewHandler
允许您以编程方式控制 View 的处理方式。例如,您可以编写一个将 View 持久保存到数据库的 StateManager
(具有适当的超时和清理功能)。
使用组件绑定(bind)和 transient 控件
您可以通过编程方式控制组件的创建方式。从绑定(bind)规范来看:
- When a component instance is first created (typically by virtue of being referenced by a
UIComponentELTag
in a JSP page), the JSF implementation will retrieve theValueExpression
for the name binding, and callgetValue()
on it. If this call returns a non-nullUIComponent
value (because the JavaBean programmatically instantiated and configured a component already), that instance will be added to the component tree that is being created. If the call returns null, a new component instance will be created, added to the component tree, andsetValue()
will be called on theValueExpression
(which will cause the property on the JavaBean to be set to the newly created component instance).- When a component tree is recreated during the Restore View phase of the request processing lifecycle, for each component that has a
ValueExpression
associated with the name “binding”,setValue()
will be called on it, passing the recreated component instance.
您可能可以将其与 transient 一起使用子组件的属性以编程方式控制子组件的创建/销毁。这是手动的,有点困惑,但在极端情况下可能有效。
我确信这不是一个详尽的列表。
关于ajax - uiComponent树内存使用情况,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4843465/