问候,
我有丰富的面孔应用程序(3.3.2.SR1)。该应用程序使用ModelPanel查看实体。在我想要显示它们之前,不会渲染所有模态面板(render = false)。应用程序变得很大,并且从一个面板到其他面板使用很多关系。一切正常,但看起来richfaces在内存中为所有可能的情况创建UIComponent树,如果component rendred为true或false。当我尝试检查应用程序的内存使用情况时(我使用了YourKit Java Profiler来满足这些需求)我发现它在一个会话中占用了大量内存。
我正在使用Facelets和richfaces,我尝试使用
<c:if test="rendred condition"... /> content </c:if>
它开始使用明显更少的内存,但...... 当我用面板重新渲染区域时,父屏幕上的控件将停止工作。我怀疑这是因为每次更改组件树时它会重新创建整个树,并且我有不同步的客户端(html)和服务器(面)部分。
有人可以建议我如何减少内存使用量吗?我真的有问题,因为HeapMemory中的StandardSession对象使用60-150Mb。几乎所有这些内存都用于UIControls。
问题示例:
我的页面引用了panel1,panel2,panel3。
小组是:
<rich:modalPanel >
<a4j:outputPanel layout="block"
rendered="#{PanelBeanHolder.renderedViewScreen}">
<ui:insert name="panelContent" />
</a4j:outputPanel>
</rich:modalPanel>
我只在执行此操作时才渲染面板。并且在我需要之前不想为输出面板加载UI控件。
提前谢谢。
P.S。我试图做以下事情来改善这种情况
使用以下命令在web.xml中配置会话中的视图数:
<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以压缩流。 它没有多大帮助。
答案 0 :(得分:3)
JSF使用在请求之间维护的有状态组件树。默认情况下,这通常在会话中维护。您可以使用一些功能来控制它。
配置状态保存参数
通常有特定于实现的参数来控制会话中存储的视图数量 - 这取决于应用程序的行为方式,这可能很容易获胜。
您可以使用javax.faces.STATE_SAVING_METHOD
参数在表单中保存状态。但是,请注意,每个请求都会发送更多信息,并且允许客户端指定服务器端状态存在安全风险(确保您对实现如何加密此数据感到满意)。您需要检查与组件库(即RichFaces)的兼容性,特别是如果您使用的是AJAX。
JSF 2使用新的状态保存机制来减少会话开销;您的faces-config.xml
需要更新为2.0版本。我相信这个想法来自Apache Trinidad,所以你可以从那里提取一个前JSF 2版本。
执行自己的状态保存和/或视图创建
通过实施自己的StateManager
和/或ViewHandler
,您可以对视图的处理方式进行编程控制。例如,您可以编写一个StateManager
持久化视图到数据库(具有适当的超时和清理)。
使用组件绑定和瞬态控制
您可以对组件的创建方式进行编程控制。从绑定规范:
- 首次创建组件实例时(通常由JSP页面中的
UIComponentELTag
引用),JSF实现将检索名称绑定的ValueExpression
,并调用{{ 1}}就可以了。如果此调用返回非空getValue()
值(因为JavaBean已经以编程方式实例化并配置了组件),则该实例将添加到正在创建的组件树中。如果调用返回null,将创建一个新的组件实例,添加到组件树中,并在UIComponent
上调用setValue()
(这将导致JavaBean上的属性设置为新创建的组件实例)。- 在请求处理生命周期的“还原视图”阶段重新创建组件树时,对于具有与“绑定”名称关联的
ValueExpression
的每个组件,将在其上调用ValueExpression
,传递重新创建的组件实例。
您可以在子项上使用transient属性来控制以编程方式控制子组件的创建/销毁。这是手动的,有点乱,但可能在极端情况下有用。
我确定这不是一份详尽的清单。